第二章:配置串口
這一章介紹怎樣使用C語言的POSIX終端接口配置串口。
POSIX終端接口
多數系統支持使用POSIX終端接口改變波特率、字符數等參數。首先要包含頭文件<termios.h>;這樣就定義了終端控制結構和POSIX控制函數。
兩個最重要的POSIX函數是tcgetattr(3)和tcsetattr(3),用了獲取和設置終端屬性。你可以設置一個指向termios結構的指針,這個結構包含了所有可用的串口選項:
Table 3 - Termios Structure Members
Member |
Description |
c_cflag |
Control options |
c_lflag |
Line options |
c_iflag |
Input options |
c_oflag |
Output options |
c_cc |
Control characters |
c_ispeed |
Input baud (new interface) |
c_ospeed |
Output baud (new interface) |
控制選項
c_cflag用來控制波特率、數據位、奇偶位、停止位和硬件流控制。下面是所有支持的配置的常量:
Table 4 - Constants for the c_cflag Member
Constant |
Description |
CBAUD |
Bit mask for baud rate |
B0 |
0 baud (drop DTR) |
B50 |
50 baud |
B75 |
75 baud |
B110 |
110 baud |
B134 |
134.5 baud |
B150 |
150 baud |
B200 |
200 baud |
B300 |
300 baud |
B600 |
600 baud |
B1200 |
1200 baud |
B1800 |
1800 baud |
B2400 |
2400 baud |
B4800 |
4800 baud |
B9600 |
9600 baud |
B19200 |
19200 baud |
B38400 |
38400 baud |
B57600 |
57,600 baud |
B76800 |
76,800 baud |
B115200 |
115,200 baud |
EXTA |
External rate clock |
EXTB |
External rate clock |
CSIZE |
Bit mask for data bits |
CS5 |
5 data bits |
CS6 |
6 data bits |
CS7 |
7 data bits |
CS8 |
8 data bits |
CSTOPB |
2 stop bits (1 otherwise) |
CREAD |
Enable receiver |
PARENB |
Enable parity bit |
PARODD |
Use odd parity instead of even |
HUPCL |
Hangup (drop DTR) on last close |
CLOCAL |
Local line - do not change "owner" of port |
LOBLK |
Block job control output |
CNEW_RTSCTS CRTSCTS |
Enable hardware flow control (not supported on all platforms) |
c_cflag有兩個選項需要一直使能,CLOCAL:忽略所有調制解調器的狀態信號;CREAD:啓用字符接收器。
波特率常數(CBAUD,B9600,etc.)用於缺少c_ispeed和c_ospeed 成員的舊接口。下一節介紹用於設置波特率的POSIX函數。
注:決不能直接初始化c_cflag(或其他flag)。應該使用AND,OR或NOT等位操作符來置1或清0成員中的位。不同的操作系統版本的位操作可能不同,使用位操作符可以避免錯誤操作一個新串行設備所需要的標誌位。
1)設置波特率
不同的操作系統中,波特率儲存的位置也不同。舊的接口將波特率按照Table4中的常量保存c_cflag中。新的實現方法提供了c_ispeed 和c_ospeed 來保存實際的波特率值。
cfsetospeed(3)和cfsetispeed(3)函數用來設置termios結構中的波特率,從而屏蔽了底層的操作系統。你可以使用下面的代碼設置波特率:
Listing 2 - Setting the baud rate.
struct termios options;
/*
* Get the current options for the port...
*/
tcgetattr(fd, &options);
/*
* Set the baud rates to 19200...
*/
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
/*
* Enable the receiver and set local mode...
*/
options.c_cflag |= (CLOCAL | CREAD);
/*
* Set the new options for the port...
*/
tcsetattr(fd, TCSANOW, &options);
tcgetattr(3)函數使用你提供的串口配置參數填充termios結構。設置了波特率、使能本地模式和串行數據接收後,使用tcsetattr(3)使新的配置生效。常量TCSANOW指定了新的設置立即生效,不需要等待數據接收或發生結束。還有其他常量,可以等待輸入或輸出數據結束,或清空緩衝區。
多數操作系統不支持不同的輸入和輸出速率,爲了最好的可移植性,請確保相同的輸入和輸出速率。
Table 5 - Constants for tcsetattr
Constant |
Description |
TCSANOW |
Make changes now without waiting for data to complete |
TCSADRAIN |
Wait until everything has been transmitted |
TCSAFLUSH |
Flush input and output buffers and make the change |
2)設置字符大小
與波特率設置不同,沒有方便的函數用來設置字符大小,所有必須用位掩碼。字符大小用位數指定。
options.c_cflag &= ~CSIZE; /* Mask the character size bits */
options.c_cflag |= CS8; /* Select 8 data bits */
3)設置奇偶校驗
類似設置字符大小,你必須手動設置使能奇偶校驗和奇偶校驗位數。UNIX的串口設備支持奇、偶和無校驗。
No parity (8N1):
options.c_cflag &= ~PARENB
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
Even parity (7E1):
options.c_cflag |= PARENB
options.c_cflag &= ~PARODD
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
Odd parity (7O1):
options.c_cflag |= PARENB
options.c_cflag |= PARODD
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS7;
Space parity is setup the same as no parity (7S1):
options.c_cflag &= ~PARENB
options.c_cflag &= ~CSTOPB
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
4)硬件流控制
有些UNIX版本支持使用CTS (Clear To Send)和RTS (Request To Send)信號來控制硬件流。如果你的系統定義了CNEW_RTSCTS或CRTSCTS常量 ,那就很可能支持硬件流控制。使用下面的代碼可以使能硬件流控制:
options.c_cflag |= CNEW_RTSCTS; /* Also called CRTSCTS */
關閉硬件流控制:
options.c_cflag &= ~CNEW_RTSCTS;
本地選項
本地模式成員c_lflag用於控制串行設備如何管理輸入字符。通常可以將c_lflag配置爲canonical或raw 。
Table 6 - Constants for the c_lflag Member
ISIG |
Enable SIGINTR, SIGSUSP, SIGDSUSP, and SIGQUIT signals |
ICANON |
Enable canonical input (else raw) |
XCASE |
Map uppercase /lowercase (obsolete) |
ECHO |
Enable echoing of input characters |
ECHOE |
Echo erase character as BS-SP-BS |
ECHOK |
Echo NL after kill character |
ECHONL |
Echo NL |
NOFLSH |
Disable flushing of input buffers after interrupt or quit characters |
IEXTEN |
Enable extended functions |
ECHOCTL |
Echo control characters as ^char and delete as ~? |
ECHOPRT |
Echo erased character as character erased |
ECHOKE |
BS-SP-BS entire line on line kill |
FLUSHO |
Output being flushed |
PENDIN |
Retype pending input at next read or input char |
TOSTOP |
Send SIGTTOU for background output |
選擇Canonical Input
Canonical Input是以行進行操作的。輸入的字符被放在一個可以由用戶進行交互編輯的緩衝區,知道收到回車(CR)或換行(LF)字符。選擇這個模式的話,你需要選擇ICANON,ECHO和ECHOE選項:
options.c_lflag |= (ICANON | ECHO | ECHOE);
選擇Raw Input
Raw input 是不做任何處理的。輸入字符被收到後就直接傳送。你需要取消ICANON、ECHO、ECHOE和ISIG選項來選擇Raw Input模式:
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
關於輸入回顯的說明
決不能在發生命令給一個MODOM或電腦時使能輸入回顯,那樣的話會在兩個串口之間形成一個迴環。
輸入選項
輸入模式成員變量c_iflag用於控制串口接收端的字符的處理過程。與c_cflag一樣,c_iflag的值也是將需要的選項通過OR運算得到的。
Table 7 - Constants for the c_iflag Member
Constant |
Description |
INPCK |
Enable parity check |
IGNPAR |
Ignore parity errors |
PARMRK |
Mark parity errors |
ISTRIP |
Strip parity bits |
IXON |
Enable software flow control (outgoing) |
IXOFF |
Enable software flow control (incoming) |
IXANY |
Allow any character to start flow again |
IGNBRK |
Ignore break condition |
BRKINT |
Send a SIGINT when a break condition is detected |
INLCR |
Map NL to CR |
IGNCR |
Ignore CR |
ICRNL |
Map CR to NL |
IUCLC |
Map uppercase to lowercase |
IMAXBEL |
Echo BEL on input line too long |
設置輸入奇偶校驗選項
如果已經在c_cflag中使能了奇偶校驗,那你可以使能輸入奇偶校驗。與輸入奇偶校驗相關的常量是INPCK, IGNPAR, PARMRK和ISTRIP。通常你需要選擇INPCK和ISTRIP來使能輸入奇偶校驗並去掉數據中的校驗位:
options.c_iflag |= (INPCK | ISTRIP);
IGNPAR是一個危險的選項,它告訴串口忽略校驗錯誤並讓數據通過,就想沒用發生錯誤一樣。這在測試通信連接的質量時有用,通常沒有實用價值。
PARMRK會使校驗錯誤被標記爲“marked",並使用特殊的字符放入輸入流中。如果使能IGNPAR,一個空字符(000 octal)會被加入到校驗錯誤的前面。否則,DEL(177 octal)和NUL字符會和錯誤字符一起發生。
設置軟件流控制
使用IXON、IXOFf和IXANY常量來使能軟件流控制:
options.c_iflag |= (IXON | IXOFF | IXANY);
取消軟件流控制只需掩掉這些位:
options.c_iflag &= (IXON | IXOFF | IXANY);
XON(開始數據)和XOFF(停止數據)字符定義在下面描述的c_cc數組中。
輸出選項
C_oflag成員包含了輸出過濾選項。像輸入模式一樣,你可以選擇processed或raw數據輸出。
Table 8 - Constants for the c_oflag Member
Constant |
Description |
OPOST |
Postprocess output (not set = raw output) |
OLCUC |
Map lowercase to uppercase |
ONLCR |
Map NL to CR-NL |
OCRNL |
Map CR to NL |
NOCR |
No CR output at column 0 |
ONLRET |
NL performs CR function |
OFILL |
Use fill characters for delay |
OFDEL |
Fill character is DEL |
NLDLY |
Mask for delay time needed between lines |
NL0 |
No delay for NLs |
NL1 |
Delay further output after newline for 100 milliseconds |
CRDLY |
Mask for delay time needed to return carriage to left column |
CR0 |
No delay for CRs |
CR1 |
Delay after CRs depending on current column position |
CR2 |
Delay 100 milliseconds after sending CRs |
CR3 |
Delay 150 milliseconds after sending CRs |
TABDLY |
Mask for delay time needed after TABs |
TAB0 |
No delay for TABs |
TAB1 |
Delay after TABs depending on current column position |
TAB2 |
Delay 100 milliseconds after sending TABs |
TAB3 |
Expand TAB characters to spaces |
BSDLY |
Mask for delay time needed after BSs |
BS0 |
No delay for BSs |
BS1 |
Delay 50 milliseconds after sending BSs |
VTDLY |
Mask for delay time needed after VTs |
VT0 |
No delay for VTs |
VT1 |
Delay 2 seconds after sending VTs |
FFDLY |
Mask for delay time needed after FFs |
FF0 |
No delay for FFs |
FF1 |
Delay 2 seconds after sending FFs |
選擇Processed輸出
通過設置c_oflag中的OPOST選項來選擇Processed輸出:
options.c_oflag |= OPOST;
在所有的選項中,你大概只需要用ONLCR選項將換行符映射到CR-LF上。
選擇Raw輸出
在c_oflag中重新設置OPOST選項就選擇了Raw輸出:
Options.c_oflag &= ~OPOST;
取消OPOST選項時,c_oflag中的其他選項都將被忽略。
控制字符
c_cc字符數組包含控制字符的定義和超時參數。數組的元素都定義了常量。
Table 9 - Control Characters in the c_cc Member
Constant |
Description |
Key |
VINTR |
Interrupt |
CTRL-C |
VQUIT |
Quit |
CTRL-Z |
VERASE |
Erase |
Backspace (BS) |
VKILL |
Kill-line |
CTRL-U |
VEOF |
End-of-file |
CTRL-D |
VEOL |
End-of-line |
Carriage return (CR) |
VEOL2 |
Second end-of-line |
Line feed (LF) |
VMIN |
Minimum number of characters to read |
|
VTIME |
Time to wait for data (tenths of seconds) |