linux 串口 特殊字符


近日在寫一個linux的串口程序,發現大多數情況下數據接收沒問題,但是有時卻有問題。主要是接收的字符串中包含有0x03這個字符,會造成與它相鄰的字符同時也接收不到,搞了好久才發現這個錯誤。查找資料后發現許多ARM板也存着這個問題,存在問題的字符串還包括0x13、0x0D等特殊含義的字符。

解決方法

方法比較簡單,接收數據前,對串口的文件描述符fd進行如下設置, 

  1. <pre name="code" class="cpp">struct termios options;  
  2.     if  ( tcgetattr( fd,&options)  !=  0)  
  3.     {  
  4.         perror("SetupSerial 1");  
  5.         return(FALSE);  
  6.     }  
  7.     options.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);  
  8.     options.c_oflag &= ~OPOST;  
  9.     options.c_cflag |= CLOCAL | CREAD;  
  10.     options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  
  11.     tcsetattr(fd,TCSAFLUSH,&options);  
代碼用於修改與文件描述符fd相關的標志.c_oflag和.c_oflag和.c_iflag,重置了一些特殊字符的處理方式。現在通過fd的串口接收任何字符都應該不成問題了。


現在問題應該可以解決了。如果你還想了解的更深入的話,可以接着往下看看。

屬性獲取

 

  1. 函數:int tcgetattr(int fd, struct termios *termios_p);  
成功返回零;失敗返回非零,發生失敗接口將設置errno錯誤標識。

參數說明:

 

tcgetattr函數用於獲取與終端相關的參數。參數fd為終端的 文件描述符,返回的結果保存在 termios  結構體中,該結構體一般包括如下的成員:
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_cc[NCCS];
其具體意義如下。
c_iflag:輸入模式標志,控制終端輸入方式,具體參數如表1所示。
表1 c_iflag參數表
鍵 值
說 明
IGNBRK
忽略BREAK鍵輸入
BRKINT
如果設置了IGNBRK,BREAK鍵輸入將被忽略
IGNPAR
忽略奇偶校驗錯誤
PARMRK
標識奇偶校驗錯誤
INPCK
允許輸入奇偶校驗
ISTRIP
去除字符的第8個比特
INLCR
將輸入的NL(換行)轉換成CR(回車)
IGNCR
忽略輸入的回車
ICRNL
將輸入的回車轉化成換行(如果IGNCR未設置的情況下)
IUCLC
將輸入的大寫字符轉換成小寫字符(非POSIX)
IXON
允許輸出時對XON/XOFF流進行控制
IXANY
輸入任何字符將重啟停止的輸出
IXOFF
允許輸入時對XON/XOFF流進行控制
IMAXBEL
當輸入隊列滿的時候開始響鈴
c_oflag:輸出模式標志,控制終端輸出方式,具體參數如表2所示。
表2 c_oflag參數
鍵 值
說 明
OPOST
處理后輸出
OLCUC
將輸入的小寫字符轉換成大寫字符(非POSIX)
ONLCR
將輸入的NL(換行)轉換成CR(回車)及NL(換行)
OCRNL
將輸入的CR(回車)轉換成NL(換行)
ONOCR
第一行不輸出回車符
ONLRET
不輸出回車符
OFILL
發送填充字符以延遲終端輸出
OFDEL
以ASCII碼的DEL作為填充字符,如果未設置該參數,填充字符為NUL
NLDLY
換行輸出延時,可以取NL0(不延遲)或NL1(延遲0.1s)
CRDLY
回車延遲,取值范圍為:CR0、CR1、CR2和 CR3
TABDLY
水平制表符輸出延遲,取值范圍為:TAB0、TAB1、TAB2和TAB3
BSDLY
空格輸出延遲,可以取BS0或BS1
VTDLY
垂直制表符輸出延遲,可以取VT0或VT1
FFDLY
換頁延遲,可以取FF0或FF1
c_cflag:控制模式標志,指定終端硬件控制信息,具體參數如表3所示。
表3 c_cflag參數
鍵 值
說 明
CBAUD
波特率(4+1位)(非POSIX)
CBAUDEX
附加波特率(1位)(非POSIX)
CSIZE
字符長度,取值范圍為CS5、CS6、CS7或CS8
CSTOPB
設置兩個停止位
CREAD
使用接收器
PARENB
使用奇偶校驗
PARODD
對輸入使用奇偶校驗,對輸出使用偶校驗
HUPCL
關閉設備時掛起
CLOCAL
忽略調制解調器線路狀態
CRTSCTS
使用RTS/CTS流控制
c_lflag:本地模式標志,控制終端編輯功能,具體參數如表4所示。
表4 c_lflag參數
鍵 值
說 明
ISIG
當輸入INTR、QUIT、SUSP或DSUSP時,產生相應的信號
ICANON
使用標准輸入模式
XCASE
在ICANON和XCASE同時設置的情況下,終端只使用大寫。
ECHO
顯示輸入字符
ECHOE
如果ICANON同時設置,ERASE將刪除輸入的字符
ECHOK
如果ICANON同時設置,KILL將刪除當前行
ECHONL
如果ICANON同時設置,即使ECHO沒有設置依然顯示換行符
ECHOPRT
如果ECHO和ICANON同時設置,將刪除打印出的字符(非POSIX)
TOSTOP
向后台輸出發送SIGTTOU信號
c_cc[NCCS]:控制字符,用於保存終端驅動程序中的特殊字符,如輸入結束符等。c_cc中定義了如表5所示的控制字符。
表5 c_cc支持的控制字符
說 明
說 明
VINTR
Interrupt字符
VEOL
附加的End-of-file字符
VQUIT
Quit字符
VTIME
非規范模式讀取時的超時時間
VERASE
Erase字符
VSTOP
Stop字符
VKILL
Kill字符
VSTART
Start字符
VEOF
End-of-file字符
VSUSP
Suspend字符
VMIN
非規范模式讀取時的最小字符數
   
tcsetattr函數用於設置終端的相關參數。參數fd為打開的終端文件描述符,參數optional_actions用於控制修改起作用的時間,而結構體termios_p中保存了要修改的參數。
optional_actions可以取如下的值:
TCSANOW:不等數據傳輸完畢就立即改變屬性。
TCSADRAIN:等待所有數據傳輸結束才改變屬性。
TCSAFLUSH:清空輸入輸出緩沖區才改變屬性。
錯誤信息:
EBADF:非法的文件描述符。
EINTR:tcsetattr函數調用被信號中斷。
EINVAL:參數optional_actions使用了非法值,或參數termios中使用了非法值。
ENCTTY:非終端的文件描述符。

屬性設置

函數:int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

tcsetattr函數用於設置終端參數。函數在成功的時候返回0,失敗的時候返回-1,並設置errno的值。

參數說明:

參數fd為打開的終端文件描述符,參數optional_actions用於控制修改起作用的時間,而結構體termios_p中保存了要修改的參數。optional_actions可以取如下的值。

 

TCSANOW:不等數據傳輸完畢就立即改變屬性。
TCSADRAIN:等待所有數據傳輸結束才改變屬性。
TCSAFLUSH:清空輸入輸出緩沖區才改變屬性。
EBADF:非法的 文件描述符
EINTR:tcsetattr 函數調用被信號中斷。
EINVAL:參數optional_actions使用了非法值,或參數termios中使用了非法值。
ENCTTY:非 終端文件描述符

示例

 

  1. #include <stdio.h>  
  2. #include <termios.h>  
  3. #include <unistd.h>  
  4. #include <errno.h>  
  5. int main(void){  
  6. //term用於存儲獲得的終端參數信息  
  7. struct termios term;  
  8. int err;  
  9. //獲得標准輸入的終端參數,將獲得的信息保存在term變量中  
  10. if(tcgetattr(STDIN_FILENO,&term)==-1){  
  11. perror("Cannot get standard input description");  
  12. return 1;  
  13. }  
  14. //修改獲得的終端信息的結束控制字符  
  15. term.c_cc[VEOF]=(cc_t)0x07;  
  16. //使用tcsetattr函數將修改后的終端參數設置到標准輸入中  
  17. //err用於保存函數調用后的結果  
  18. err=tcsetattr(STDIN_FILENO,TCSAFLUSH,&term);  
  19. //如果err為-1或是出現EINTR錯誤(函數執行被信號中斷),  
  20. //給出相關出錯信息  
  21. if(err==-1 && err==EINTR){  
  22. perror("Failed to change EOF character");  
  23. return 1;  
  24. }  
  25. return 0;  
  26. }  
用gcc編譯程序,得到可執行程序。在執行程序前,按“Ctrl+D”可以使終端結束。執行程序后,按“Ctrl+D”失去了作用,而輸入“Ctrl+G”實現了原來“Ctrl+D”的功能。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM