串口的設置主要是設置struct termios結構體的各個成員值:
#include<termios.h>
struct termios{
unsigned short c_iflag; //輸入模式標志
unsigned short c_oflag; //輸出模式標志
unsigned short c_cflag; //控制模式標志
unsigned short c_lflag; //本地模式標志
unsigned char c_line; //行標識
unsigned char c_cc[NCCS]; //控制字符
};
這個結構中最重要的是c_cflag,通過對它賦值,用戶可以設置數據傳輸率、字符大小、數據位、停止位、奇偶效驗位和硬件流控等。另外c_iflag和c_cc也是比較常用的標志。
c_cflag支持很多常量名稱,其中設置數據傳輸率為相應的數據傳輸率前要加上“B”。
c_cflag成員不能直接對其初始化,而要將其通過與、或操作使用其中的某些選項。
輸入模式c_iflag成員控制端口接收端的字符輸入處理;c_cc包含了超時參數和控制字符的定義。
設置串口屬性主要是配置termios結構體中的各個變量,其主要流程包含以下幾個步驟:
1.使用函數tcgetattr保存原串口屬性
2.通過位掩碼的方式激活本地連接和接受使能選項:CLOCAL和CREAD
3.使用函數cfsetispeed和cfsetospeed設置數據傳輸率
4.通過位掩碼設置字符大小。
5.設置奇偶效驗位需要用到兩個termios中的成員:c_cflag和c_iflag。首先要激活c_cflag中的校驗位使能標志PARENB和是否進行奇偶效驗,同時還要激活c_iflag中的奇偶效驗使能
6.激活c_cflag中的CSTOPB設置停止位。若停止位為1,則清除CSTOPB;若停止位為0,則激活CSTOPB
7.設置最少字符和等待時間。在對接收字符和等待時間沒有特別要求的情況下,可以將其設置為0
8.調用函數"tcflush(fd,queue_selector)"來處理要寫入引用的對象,queue_selector可能的取值有以下幾種。
TCIFLUSH:刷新收到的數據但是不讀
TCOFLUSH:刷新寫入的數據但是不傳送
TCIOFLUSH:同時刷新收到的數據但是不讀,並且刷新寫入的數據但是不傳送。
下面給出串口配置的完整的函數:
int set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop){
struct termios newtio,oldtio;
if(tcgetattr(fd,&oldtio)!=0){//保存測試現有串口參數設置,在這裡如果串口號出錯,會有相關的出錯信息
perror("SetupSerial 1");
return -1;
}
bzero(&newtio,sizeof(newtio));//設置字符大小
newtio.c_cflag |= CLOCAL |CREAD; //通過位掩碼的方式激活本地連接和接受使能選項
newtio.c_iflag &= ~CSIZE;
switch(nBits){//設置停止位
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |=CS8;
break;
}
switch(nEvent){//設置奇偶效驗位
case 'o': //奇數
newtio.c_cflag |= PARENB;
newtio.c_cflag |=PARODD;
newtio.c_iflag |=(INPCK | ISTRIP);
break;
case 'E': //偶數
newtio.c_iflag |=(INPCK | ISTRIP);
newtio.c_cflag |=PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N': //無奇偶效驗位
newtio.c_cflag &= ~PARENB;
break;
}
swtch(nSpeed){ //設置數據傳輸率
case 2400:
cfsetispeed(&newtio,B2400);
cfsetospeed(&newtio,B2400);
break;
case 4800:
cfsetispeed(&newtio,B4800);
cfsetospeed(&newtio,B4800);
break;
case 9600:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
case 115200:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
break;
case 460800:
cfsetispeed(&newtio,B460800);
cfsetospeed(&newtio,B460800);
break;
default:
cfsetispeed(&newtio,B9600);
cfsetospeed(&newtio,B9600);
break;
}
if(nStop == 1) //設置停止位
newtio.c_cflag &= ~CSTOPB;
else if(nStop == 2)
newtio.c_cflag |= CSTOPB;
newtio.c_cc[VTIME] = 0; //設置等待時間和最少的接收字符
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);//處理未接收字符
if((tcsetattr(fd,TCSANOW,&newtio))!=0){//激活新配置
perror("com set error");
return -1;
}
printf("set done!\n");
return 0;
}