2021-04-25
關鍵字:串行接口、串口屬性設置
1、什麼是串口?
串口(Serial Port)是一種常見的計算機接口,由於它所需的連線少、通信控制簡單且成本低廉,在行業內,尤其是嵌入式領域內得到了廣泛的使用。
串口是一種通信方式,其包含了多種接口標準,其中最常見的是:RS232標準。即9針D型接口標準。如下圖所示:
RS232各針序號如下圖所示:
DTE即俗話說的“串口公頭”,DCE即“串口母頭”。
9針中每一針都有其用途,具體如下所示:
針號 | 功能說明 | 縮寫 |
1 | 數據載波檢測 | DCD |
2 | 接收數據 | RXD |
3 | 發送數據 | TXD |
4 | 數據終端準備 | DTR |
5 | 信號地 | GND |
6 | 數據設備準備好 | DSR |
7 | 請求發送 | RTS |
8 | 清除發送 | CTS |
9 | 振鈴提示 | BELL |
雖然RS232標準有9根數據針腳,但實際上僅需要湊齊RXD, TXD與GND三根針腳就能完成最基礎的數據通信了。這也是爲什麼在嵌入式開發板中見到的串口經常都是三根針或四根針的原因。三根針的就表明僅需RXD, TXD與GND,四根針則多了一個VCC針用於供電。
上表每一根針的具體含義都包含在RS232標準的細節之中,因嵌入式領域很少會用到完整的9針串口通信,因此就不再此贅述了,對我們而言只需要知道最少三根針即可完成通信即可。
一般而言,串口協議所支持的最高數據傳輸速率是 115kbps,即115200的波特率,換算成字節率就是14.4kb/s的傳輸速率。但仍有一些增強型的串口可以達到更高的通信速率。不過串口高速傳輸也是有代價的,通信速率越高,有效傳輸距離就越近,成本也越高。一般而言,串口的通信距離不應超過12米。遠距離串口通信應藉助Modem設備中繼傳輸。
2、串口開發
Linux對串口已經有了很好的支持,串口在Linux中是以字符設備的形式存在的。通常在 /dev/ 目錄下 ttyS 前綴的設備節點即表示串口設備,不同串口設備以順序增長的數字來區分。ttyS0 即表示第一個串口設備,一般都是系統串口設備,即嵌入式開發板中用來查看板子打印的設備節點。
因爲串口設備是以字符設備的形式存在的,因此我們就可以以POSIX形式的接口來對它做IO操作了,一般就是 open, read, write和close,就不再詳細介紹了。
這裏重點關注下串口的屬性設置。
串口屬性一般包括:波特率、數據位、停止位和奇偶校驗位等參數。
在Linux系統中用結構體 termios 來存儲這些參數,這一結構體位於 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[NCC]; //控制字 };
其中每個字段的常用值如下表示所:
c_iflag字段:
IGNPAR | 忽略幀錯誤和奇偶校驗錯誤 |
INPCK | 啓用輸入奇偶檢測 |
ISTRIP | 去掉第8位 |
INLCR | 將輸入中的NL翻譯爲CR |
IGNCR | 忽略輸入中的回車 |
ICRNL | 將輸入中的回車翻譯爲新行(除非設置了IGNCR) |
IXON | 啓用輸出的XON/XOFF流控制 |
IXOFF | 啓用輸入的XON/XOFF流控制 |
c_oflag字段:
ONLCR | 將輸出中的新行符映射爲回車-換行 |
OCRNL | 將輸出中的回車映射爲新行符 |
ONOCR | 不在第0列輸出回車 |
ONLRET | 不輸出回車 |
OFILL | 發送填充字符作爲延時,而不是使用定時來延時。 |
c_cflag字段:
CSIZE | 字符長掩碼。取值爲CS5,CS6,CS7或CS8 |
CSTOPB | 設置兩個停止位,而不是一個。 |
CREAD | 打開接受者 |
PARENB | 允許輸出產生奇偶信息以及輸入的奇偶校驗 |
PARODD | 輸入和輸出的奇校驗 |
CLOCAL | 忽略modem控制線 |
c_lflag字段:
ISIG | 當接受到字符INTR, QUIT, SUSP或DSUSP時,產生相應的信號 |
ICANON | 啓用標準模式,允許使用特殊字符EOF, EOL, EOL2, ERASE, KILL, LNEXT, REPRINT, STATUS和WERASE,以及按行的緩衝 |
ECHO | 回顯輸入字符 |
ECHOE | 如果同時設置了ICANON,字符ERASE探險前一個輸入字符,WERASE擦除前一個詞 |
ECHOK | 如果同時設置了ICANON,字符KILL刪除當前行 |
ECHONL | 如果同時設置了ICANON,回顯字符NL,即使沒有設置ECHO |
NOFLSH | 禁止在產生SIGINT, SIGQUIT和SIGSUSP信號時刷新輸入和輸出隊列 |
TOSTOP | 向試圖寫控制終端的後臺進程組發送SIGTTOU信號 |
c_cc字段成員下標值及其所表示的含義:
VINTR | (003,ETX,ctrl+c,或者0177, DEL)中斷字符。發出SIGINT信號。當設置ISIG時可被識別,不再作爲輸入傳遞 |
VQUIT | (034, FS, crtl+\)退出字符。發出SIGQUIT信號。當設置ISIG時可被識別,不再作爲輸入傳遞 |
VERASE | (0177, DEL, 或者010, BS, ctrl+H)刪除字符。刪除上一個還沒有刪掉的字符,但不刪除上一個EOF或者行首。當設置ICANON時可被識別,不再作爲輸入傳遞 |
VKILL | (025, NAK, ctrl-U, 或者ctrl+X或@)終止字符。刪除自上一個EOF或行首以來的輸入。當設置ICANON時可被識別,不再作爲輸入傳遞 |
VEOF | (004, EOT, ctrl+D)文件尾字符。更精確地說,這個字符使得tty緩衝中的內容被送到等待輸入的用戶程序中,而不必等到EOL。如果它是一行的第一個字符,那麼用戶程序的read()將返回0,指示讀到了EOF。當設置ICANON時可被識別,不再作爲輸入傳遞 |
VMIN | 非canonical模式讀的最小字符數。 |
VEOL | (0, NUL)附加的行尾字符。當設置ICANON時可被識別 |
VTIME | 非canonical模式讀時的延時,以十分之一秒爲單位。 |
VSTART | (021, DC1, Ctrl+Q)開始字符。重新開始被Stop字符中止的輸出。當設置IXON時可被識別,不再作爲輸入傳遞 |
VSTOP | (023, DC3, ctrl+S)停止字符。停止輸出,直到輸入Start字符。當設置IXON時可被識別,不再作爲輸入傳遞。 |
VSUSP | (032, SUB, ctrl+Z)掛起字符。發送SIGTSTP信號。當設置ISIG時可被識別,不再作爲輸入傳遞。 |
根據上表,需要什麼功能或屬性,則直接在相應字段上相應位進行上述位的與或非與即可。
termios.h 中爲設置串口屬性還提供了以下函數:
#include <termios.h> #include <unistd.h> int tcgetattr(int fd, struct termios* tp); int tcsetattr(int fd, int optional_actions, struct termios* tp); int tcsendbreak(int fd, int duration); int tcdrain(int fd); int tcflush(int fd, int queue_selector); int tcflow(int fd, int action); int cfmakeraw(struct termios* tp); speed_t cfgetispeed(struct termios* tp); speed_t cfgetospeed(struct termios* tp); int cfsetispeed(struct termios* tp, speed_t speed); int cfsetospeed(struct termios* tp, speed_t speed);
tcgetattr()與tcsetattr()兩個函數用於讀取/設置指定串口的屬性。 optional_actions 表示設置的參數什麼時候起作用:TCSANOW--立即生效;TCSADRAIN--fd上所有的輸出都被傳輸後生效;TCSAFLUSH--所有引用fd對象的數據都在傳輸出去後生效。
cfmakeraw()函數設置終端爲原始數據方式,即恢復出廠設置。
最後四個函數用於讀取/設置輸入/輸出的波特率。speed_t類型的值爲 B0, B50, B1200, ... , B19200, B38400, ... , B115200, B230400。分別對應指定的波特率。