一、在struct termios結構體中,對串口進行基本配置(如波特率設置,校驗位和停止位設置 等)。 (一): struct termios //串口的設置主要是設置struct termios結構體的各成員 { tcflag_t c_iflag; //input mode flags 輸入模式 ...
一、在struct termios結構體中,對串口進行基本配置(如波特率設置,校驗位和停止位設置 等)。
(一):
struct termios //串口的設置主要是設置struct termios結構體的各成員
{
tcflag_t c_iflag; //input mode flags 輸入模式標誌。
tcflag_t c_oflag; //output mode flags 輸出模式標誌
tcflag_t c_cflag; //control mode flags 控制模式標誌
tcflag_t c_lflag; //local mode flags 本地模式標誌。
cc_t c_line; //line discipline 線路規程(速率)。
cc_t c_cc[NCCS]; //control characters 控制字元數組
};
1、c_cflag代表控制模式
CLOCAL含義為忽略所有數據機的狀態行,這個目的是為了保證程式不會占用串口。CREAD代表啟用字元接收器,目的是是的能夠從串口中讀取輸入的數據。
CS5/6/7/8表示發送或接收字元時使用5/6/7/8比特。
CSTOPB表示每個字元使用兩位停止位。
HUPCL表示關閉時掛斷數據機。
PARENB:啟用奇偶校驗碼的生成和檢測功能。
PARODD只使用奇校驗而不使用偶校驗。
2、c_iflag代表輸入模式。
BRKINT:當在輸入行中檢測到一個到一個終止狀態時,產生一個中斷。
TGNBRK:忽略輸入行中的終止狀態。
TCRNL:將接受到的回車符轉換為新行符。
TGNCR:忽略接受到的新行符。
INLCR:將接受到的新行符轉換為回車符。
IGNPAR:忽略奇偶校檢錯誤的字元。
INPCK:對接收到的字元執行奇偶校檢。
PARMRK:對奇偶校檢錯誤作出標記。
ISTRIP:將所有接收的字元裁減為7比特。
IXOFF:對輸入啟用軟體流控。
IXON:對輸出啟用軟體流控。
3、c_cc特殊的控制字元。
標準模式和非標準模式下,c_cc數組的下標有不同的值:
(1)標準模式:
VEOF:EOF字元
VEOL:EOF字元
VERASE:ERASE字元
VINTR:INTR字元
VKILL:KILL字元
VQUIT:QUIT字元
VSTART:START字元
VSTOP:STOP字元
(2)非標準模式:
VINTR:INTR字元
VMIN:MIN值
VQUIT:QUIT字元
VSUSP:SUSP字元
VTIME:TIME值
VSTART:START字元
VSTOP:STOP字元
(二):其中,通過對c_cflag賦值,可以設置波特率、字元大小、數據位、停止位、奇偶校驗位和硬體流控等。
程式例如:
struct termios options; // 串口配置結構體
tcgetattr(fd,&options); //獲取當前設置
bzero(&options,sizeof(options));
options.c_cflag |= B115200 | CLOCAL | CREAD; // 設置波特率,本地連接,接收使能
options.c_cflag &= ~CSIZE; //屏蔽數據位
options.c_cflag |= CS8; // 數據位為 8 ,CS7 for 7
options.c_cflag &= ~CSTOPB; // 一位停止位, 兩位停止為 |= CSTOPB
options.c_cflag &= ~PARENB; // 無校驗
//options.c_cflag |= PARENB; //有校驗
//options.c_cflag &= ~PARODD // 偶校驗
//options.c_cflag |= PARODD // 奇校驗
options.c_cc[VTIME] = 0; // 等待時間,單位百毫秒
//************************************************************************************
沒滿足條件或讀緩衝區中剩下的數據會在0百毫秒後讀出。另外特別註意的是當設置VTIME後,如果read第三個參數小於VMIN ,將會將VMIN 修改為read的第三個參數,即使用read(fd,&buf,m);,以下設置變為:options.c_cc[VMIN] = m;
************************************************************************************//
options.c_cc[VMIN] = 0; // 最小位元組數
//************************************************************************************
(1)VMIN = 0,當緩衝區位元組數 >= 0 時進行讀操作,實際上這時讀串口操作並未被阻塞,因為條件始終被滿足。
(2)VMIN = 1,當緩衝區位元組數 >= 1 時進行讀操作,當沒有數據時讀串口操作被阻塞。
(3)VMIN = 4,當緩衝區位元組數 >= 4 時進行讀操作,否則讀串口操作被阻塞。每次讀出的最大位元組數由read函數中第三個參數決定。直到緩衝區剩下的數據< read 第三個參數 並且< 4 (如果這時read第三參數為 1 則進行4次讀操作直至讀完緩衝區,如read第三參數為2,連續進行讀操作,直至緩衝區空或還剩一個字元)。
(4)沒有設置VTIME,剩下的字元沒有確定的期限,直到下次滿足讀條件的時候才被讀出。
***********************************************************************************//
tcflush(fd, TCIOFLUSH);
// TCIFLUSH刷清輸入隊列。
//TCOFLUSH刷清輸出隊列。
//TCIOFLUSH刷清輸入、輸出隊列。
tcsetattr(fd, TCSANOW, &options);
// TCSANOW立即生效;
//TCSADRAIN:Wait until everything has been transmitted;
//TCSAFLUSH:Flush input and output buffers and make the change
上述中,在設置波特率時需要在數字前加上'B'。程式例:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
二、對串口進行操作。(串口是一個終端設備)。
(一)操作命令如下:
打開串口:fd = open( "/dev/ttyS0", O_RDWR|O_NOCTTY|O_NDELAY);
O_RDWR 讀寫方式打開;
O_NOCTTY 不允許進程管理串口;通知linix系統,這個程式不會成為這個埠的控 制終端。
O_NDELAY 非阻塞(預設為阻塞,打開後也可以使用fcntl()重新設置)。通知Linux 系統不關心DCD信號線所處的狀態(埠的另一端是否激活或者停止)。
寫入串口:n = write(fd, "linux", 5);
n實際寫入位元組數;
讀取串口:res = read(fd,buf,len);
res 讀取的位元組數;
設置串口:fcntl(fd, F_SETFL, FNDELAY); //非阻塞
fcntl(fd, F_SETFL, 0); // 阻塞
關閉串口:close(fd);
(二)總體上:
1、在創建的函數open_port()中要實現的函數:
程式例如:
(1)open("/dev/ttys0",O_RDWR | O_NOCTTY | O_NDELAY);/*打開串口0*/
(2)fcntl(fd,F_SETFL,0)/*恢復串口為阻塞狀態*/
(3)isatty(STDIN_FILENO) /*測試是否為中斷設備 非0即是中斷設備*/
2、配置串口參數函數set_opt()中要實現的函數:
(1)保存原先有串口配置
tcgetattr(fd,&oldtio);
(2)先將新串口配置清0
bzore(&newtio,sizeof(newito));
(3)激活選項CLOCAL和CREAD 用於本地連接和接收使用;
newtio.c_cflag |=CLOCAL | CREAD;
(4)並設置數據位大小 ,需使用掩碼設置
newtio.c_cflag &= ~CSIZE;
newtio.c_cflag |=CS8;
(5)設置奇偶校驗
奇校驗:
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
偶校驗:
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PAREND;
newtio.c_cflag &= ~PARODD;
無奇偶校驗:
newtio.c_cflag &= ~PARENB;
(6) 設置停止位,通過激活c_cflag中的CSTOPB實現。若停止位為1,則清除CSTOPB,若停止位為2,則激活CSTOPB。
newtio.c_cflag &= ~CSTOPB; /*停止位為1*/
newtio.c_cflag |= CSTOPB;/*停止位為0*/
(7)設置波特率:
cfsetispeed(&newtio,B115200);
cfsetospeed(&newtio,B115200);
(8)設置等待時間和最小接受字元。對於接收字元和等待時間沒有特別的要求時,可設為0:
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
(9)處理為接收字元(處理要寫入的引用對象)。tcflush函數刷清(拋棄)輸入緩存(終端驅動程式已接收到,但用戶程式尚未讀)或輸出緩存(用戶程式已經寫,但尚未發送).
tcflush(fd,TCIFLUSH);
// TCIFLUSH 刷清輸入隊列。即刷新收到的數據但是不讀
// TCOFLUSH 刷清輸出隊列。即刷新寫入的數據但是不傳送
// TCIOFLUSH 刷清輸入、輸出隊列。即同時刷新收到的數據但是不讀,並且刷新寫入的數據但是不傳送。
(10)激活新配置:
tcsetattr(fd,TCSANOW,&newtio);
3、讀寫串口
write(fd,buff,8);
read(fd,buff,8);
(三)另外:
1、獲取文件的flags,即open函數的第二個參數:
flags = fcntl(fd,F_GETFL,0);
2、設置文件的flags:
fcntl(fd,F_SETFL,flags);
3、增加文件的某個flags,比如文件是阻塞的,想設置成非阻塞:
flags = fcntl(fd,F_GETFL,0);
flags |= O_NONBLOCK;
fcntl(fd,F_SETFL,flags);
4、取消文件的某個flags,比如文件是非阻塞的,想設置成為阻塞:
flags = fcntl(fd,F_GETFL,0);
flags &= ~O_NONBLOCK;
fcntl(fd,F_SETFL,flags);