OPENWRT串口收發測試詳解

        最近剛剛開始接觸Linux內核編程,第一項就是串口編程,結果卡在這裏了,卡了好久,後來發現問題其實挺簡單的,只是沒有想到,現在把代碼放在下面,代碼內有詳細的註釋,就不多做說明了,而我當時出問題的地方我也做了特殊說明,希望你們注意一下(實驗環境是microwrt)

/*
 *按照教程學習串口的編程
 *網址1:http://blog.csdn.net/shanzhizi/article/details/9241393
 *網址2:http://blog.csdn.net/shui1025701856/article/details/7571686
 *網址3:http://wenku.baidu.com/link?url=TsZc-rSDq_8ayNdWXYzkJRHLEowtx7OQMiFj_BH4M3VfvDrw4hU785aIciwS1xAmViJmz6pN0ety1_Zv8-AM2OAflOB3-UiMu9RvcSQKrAG
 */
//頭文件
#include <stdio.h> 	//標準輸入輸出定義
#include <stdlib.h>	//標準函數庫定義
#include <unistd.h>	//Unix標準函數定義
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> 	//文件控制定義
#include <termios.h>	//POSIX中斷控制定義
#include <errno.h>	//錯誤號定義
#include <string.h>

#define serial_device "/dev/ttyS1"
//打開串口
int open_port(void)
{
	int fd;		//串口的標識符
	//O_NOCTTY用來告訴Linux這個程序不會成爲“控制終端”
	//O_NDELAY用來告訴Linux這個程序不關心DCD信號
	fd=open(serial_device,O_RDWR | O_NOCTTY | O_NDELAY);
	if(fd == -1)
	{
		//不能打開串口
		perror("open_port: Unable to open /dev/ttyS0 -");
		return(fd);
	}
	else
	{
		fcntl(fd, F_SETFL, 0);
		printf("open ttys1 .....\n");
		return(fd);
	}
}

//設置波特率
void set_speed_and_parity(int fd, int speed)
{
	int i=0;		//設置循環標誌——注意不要在for內設置,否則會出錯
	struct termios Opt;	//定義termios結構
	if(tcgetattr(fd,&Opt)!=0)
	{
		perror("tcgetattr fd");
		return;
	}
	tcflush(fd, TCIOFLUSH);
	cfsetispeed(&Opt, speed);
	cfsetospeed(&Opt, speed);
	/*tcsetattr函數標誌:
	TCSANOW:立即執行而不等待數據發送或者接受完成。
	TCSADRAIN:等待所有數據傳遞完成後執行。
	TCSAFLUSH:Flush input and output buffers and make the change
	*/
	if(tcsetattr(fd, TCSANOW, &Opt) != 0)
	{	
		perror("tcsetattr fd");
		return;
	}
	tcflush(fd, TCIOFLUSH);
	//設置奇偶校驗——默認8個數據位、沒有校驗位
        
    	Opt.c_cflag &= ~PARENB;
   	 Opt.c_cflag &= ~CSTOPB;
    	Opt.c_cflag &= ~CSIZE;
    	Opt.c_cflag |= CS8;
	
	//其他的一些配置
	//原始輸入,輸入字符只是被原封不動的接收
	Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
	//軟件流控制無效,因爲硬件沒有硬件流控制,所以就不需要管了
	Opt.c_iflag &= ~(IXON | IXOFF | IXANY);
	//原始輸出方式可以通過在c_oflag中重置OPOST選項來選擇:
	Opt.c_oflag |= ~OPOST;
	//VMIN可以指定讀取的最小字符數。如果它被設置爲0,那麼VTIME值則會指定每個字符讀取的等待時間。
    	Opt.c_cc[VTIME] = 0;
    	Opt.c_cc[VMIN] = 0;
//    	Opt.c_cflag &= ~INPCK;
//    	Opt.c_cflag |= (CLOCAL | CREAD);
//	
//    	Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// 
//    	Opt.c_oflag &= ~OPOST;
   	Opt.c_oflag &= ~(ONLCR | OCRNL);    
//
   	Opt.c_iflag &= ~(ICRNL | INLCR);
//    	Opt.c_iflag &= ~(IXON | IXOFF | IXANY);    
//    
//    	Opt.c_cc[VTIME] = 0;
//    	Opt.c_cc[VMIN] = 0;
    
    	tcflush(fd, TCIOFLUSH);

}


/**
  *串口發送數據函數
  *fd:串口描述符
  *data:待發送數據
  *datalen:數據長度
  */
int serial_write(int fd ,char *data, int datalen)
{
	int len=0;
	//獲取實際傳輸數據的長度
	len=write(fd,data,datalen);
	printf("send data OK! datalen=%d\n",len);
	return len;	
}

/** 
  *串口接收數據 
  *要求啓動後,在pc端發送ascii文件 
  */ 
int serial_read(int fd,char buff[],int datalen)
{
	int nread=0;
	printf("Ready for receiving data...");
	nread=read(fd,buff,datalen);
	if(nread>0)
	{
		printf("readlength=%d\n",nread);
		buff[nread]='\0';
		printf("%s\n",buff);
	}
	return nread;
}

int serialport()
{
	int fd;	
	//打開串口
	if((fd=open_port())<0)
    	{
        	perror("open_port error");
        	return 0;
    	}
	//設置波特率和校驗位
	set_speed_and_parity(fd,115200);
	return (fd);
}

int main(void)
{
	int fd;
	int nread,i,n =0,datalen=255, len = 0;
	char testbuff[]="Hello\r\n";
	char readbuff[256];
	
	fd=serialport();
	printf("fd=%d\n",fd);
	//嘗試先寫內容
	nread=write(fd,testbuff,datalen);
	if(nread==-1)
	{
		printf("write bad\n");
	}
	else{
		printf("the test is ok!\n");
	}	
	//循環讀取串口並輸出
	while(1)
	{
		printf("enter the while loop\n");
		
		//這個是重點,當時我就是這個問題出錯了,每次讀之前必須清空一次。
		bzero(readbuff, sizeof(readbuff));
		datalen=serial_read(fd,readbuff,512);
		if(datalen > 0)
		{
			if(readbuff[0]=='O'&&readbuff[1]=='F'&&readbuff[2]=='F')
			{
				 break;
			}
			serial_write(fd,readbuff,datalen);
		}
	}
}


這個程序的目的是實現先輸出測試內容,然後讀取串口內容並輸出出去。測試可用,如果不能用請提出,我進一步修正或答疑解惑。。

謝謝關注。。。大笑


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章