Linux下的串口通信
發(fā)布時間:2022-01-07 11:19:10
點擊上方藍字關(guān)注我們
串行接口簡稱串口,也稱串行通信接口或串行通訊接口(通常指COM口,在設(shè)備管理器中可以查看到),是采用串行通信方式的擴展接口。串行接口(SerialInterface)是指數(shù)據(jù)一位一位地順序傳送。其特點是通信線路簡單,只要一對傳輸線就可以實現(xiàn)雙向通信(可以直接利用電話線作為傳輸線),從而大大降低了成本,特別適用于遠距離通信,但傳送速度較慢,可以用于交換機、電腦主板接口等。
在Linux系統(tǒng)中,一切接文件,因此串口設(shè)備是通過串口終端設(shè)備文件來訪問的,也就是通過訪問/dev/ttyS0、/dev/ttyS1、/dev/ttyS2、/dev/ttyS3這些設(shè)備文件實現(xiàn)對串口的訪問。對串口進行讀寫要經(jīng)過下面幾個步驟。
與打開文件類似,打開串口同樣使用open函數(shù)。注意對于串口的打開操作,必須使用O_NOCTTY參數(shù)。該參數(shù)表示:如果打開的是一個終端設(shè)備,程序不會成為對應這個端口的控制終端。如果沒有使用該標志,任何一個輸入(例如,鍵盤中止信號等)都將影響進程。具體代碼如下:
#include
#include
#include
int main(void)
{
…
int fd;
//使用open函數(shù)打開串口,獲得串口設(shè)備文件的文件描述符
if((fd=open("/dev/ttyS0",O_RDWR|O_NOCTTY))==-1)
{
perror("Cannot open theserial port");
return 1;
}
…
}
……
串口通信參數(shù)指的是波特率、數(shù)據(jù)位、奇偶校驗位和停止位。對串口實現(xiàn)控制的時候同樣要用到termio結(jié)構(gòu)體。
1.波特率設(shè)置
獲得端口波特率信息是通過cfgetispeed函數(shù)和cfgetospeed函數(shù)來實現(xiàn)的。cfgetispeed函數(shù)用于獲得結(jié)構(gòu)體termios_p中的輸入波特率信息,而cfgetospeed函數(shù)用于獲得結(jié)構(gòu)體termios_p中的輸出波特率信息。這兩個函數(shù)的具體信息如表1所示。
頭文件 | #include #include | ||
函數(shù)形式 | speed_t cfgetispeed(const struct termios *termios_p); speed_t cfgetospeed(const struct termios *termios_p); | ||
返回值 | 成功 | 失敗 | 是否設(shè)置errno |
返回termios_p結(jié)構(gòu)中的輸入/輸出端口的波特率 | ?1 | 是 |
表1 cfgetispeed函數(shù)和cfgetospeed函數(shù)
cfsetispeed函數(shù)和cfsetospeed函數(shù)用于設(shè)置端口的輸入/輸出波特率。一般情況下,輸入和輸出波特率是相等的。cfsetispeed函數(shù)和cfsetospeed函數(shù)的函數(shù)聲明信息如表2所示。
頭文件 | |||
函數(shù)形式 | int cfsetispeed(struct termios *termios_p, speed_t speed); int cfsetospeed(struct termios *termios_p, speed_t speed); | ||
返回值 | 成功 | 失敗 | 是否設(shè)置errno |
返回termios_p結(jié)構(gòu)中的輸入/輸出端口的波特率 | ?1 | 是 |
表2 cfsetispeed函數(shù)和cfsetospeed函數(shù)
cfsetispeed函數(shù)和cfsetospeed函數(shù)會修改結(jié)構(gòu)體termios_p中的波特率信息,其中參數(shù)speed可以使用表3中所列出的宏。
宏 定 義 | 波特率(單位:bit/s) | 宏 定 義 | 波特率(單位:bit/s) |
B0 | 0 | B1800 | 1800 |
B50 | 50 | B2400 | 2400 |
B75 | 75 | B4800 | 4800 |
B110 | 110 | B9600 | 9600 |
B134 | 134 | B19200 | 19200 |
B150 | 150 | B38400 | 38400 |
B200 | 200 | B57600 | 57600 |
B300 | 300 | B115200 | 115200 |
B600 | 600 | B230400 | 230400 |
B1200 | 1200 |
表3 speed參數(shù)常用波特率信息
使用cfsetispeed函數(shù)和cfsetospeed函數(shù)進行串口波特率設(shè)置具體代碼如下所示:
#include
#include
#include < termios.h >
……
struct termios opt; /*定義指向termios結(jié)構(gòu)類型的指針opt*/
……
//獲得串口指向termios結(jié)構(gòu)的指針
tcgetattr(fd, &Opt);
cfsetispeed(&opt,B9600); /*指定輸入波特率,9600bps*/
cfsetospeed(&opt,B9600);/*指定輸出波特率,9600bps*/
//將修改后的termios數(shù)據(jù)設(shè)置到串口中
tcsetattr(fd,TCANOW,&Opt);
……
2.數(shù)據(jù)位
數(shù)據(jù)位指的是每字節(jié)中實際數(shù)據(jù)所占的比特數(shù)。要修改數(shù)據(jù)位可以通過修改termios結(jié)構(gòu)體中c_cflag成員來實現(xiàn)。CS5、CS6、CS7和CS8分別表示數(shù)據(jù)位為5、6、7和8。值得注意的是,在設(shè)置數(shù)據(jù)位時,必須先使用CSIZE做位屏蔽。具體設(shè)置代碼如下:
#include
#include
#include< termios.h >
……
structtermios opt; /*定義指向termios結(jié)構(gòu)類型的指針opt*/
.......
//獲得串口指向termios結(jié)構(gòu)的指針
tcgetattr(fd,&Opt);
…
//屏蔽其他標志
Opt.c_cflag&=~CSIZE;
//將數(shù)據(jù)位修改為8bit
Opt.c_cflag|=CS8;
…
//將修改后的termios數(shù)據(jù)設(shè)置到串口中
tcsetattr(fd,TCANOW,&Opt);
……
3.奇偶校驗位
奇偶校驗可以選擇偶校驗、奇校驗、空格等方式,也可以不使用校驗。如果要設(shè)置為偶校驗的話,首先要將termios結(jié)構(gòu)體中c_cflag設(shè)置PARENB標志,并清除PARODD標志。如果要設(shè)置奇校驗,要同時設(shè)置termios結(jié)構(gòu)體中c_cflag設(shè)置PARENB標志和PARODD標志。如果不想使用任何校驗的話,清除termios結(jié)構(gòu)體中c_cflag的PARENB位。表4所示為設(shè)置奇偶校驗的具體方法。
設(shè) 置 | 具 體 代 碼 |
無校驗 | opt.c_cflag &= ~PARENB; |
奇校驗 | opt.c_cflag |= (PARODD | PARENB); |
偶校驗 | opt.c_cflag &= ~ PARENB; opt.c_cflag &= ~PARODD; |
空格 | opt.c_cflag &= ~PARENB; opt.c_cflag &= ~CSTOPB; |
表4 設(shè)置奇偶校驗位
下面給出將串口通信的奇偶校驗設(shè)置為偶校驗的例子,具體代碼如下:
#include
#include
#include < termios.h >
……
struct termios opt; /*定義指向termios結(jié)構(gòu)類型的指針opt*/
……
//獲得串口指向termios結(jié)構(gòu)的指針
tcgetattr(fd, &Opt);
…
opt.c_cflag &= ~ PARENB;
opt.c_cflag &= ~PARODD;
…
//將修改后的termios數(shù)據(jù)設(shè)置到串口中
tcsetattr(fd,TCANOW,&Opt);
……
4.數(shù)據(jù)流控制
數(shù)據(jù)流控制指是使用何種方法來標志數(shù)據(jù)傳輸?shù)拈_始和結(jié)束??梢赃x擇不使用數(shù)據(jù)流控制、使用硬件進行流控制和使用軟件進行流控制。數(shù)據(jù)流控制設(shè)置如表5所示。
設(shè) 置 | 具 體 代 碼 |
不使用數(shù)據(jù)流控制 | opt.c_cflag &= ~CRTSCTS |
硬件 | opt.c_cflag |= CRTSCTS |
軟件 | opt.c_cflag | = IXON|IXOFF|IXANY |
由于使用硬件流控制需要相應連接的電纜,常用的流控制方法還是使用軟件進行流控制。下面給出了設(shè)置不使用數(shù)據(jù)流控制的相關(guān)代碼:
#include
#include
#include < termios.h >
……
struct termios opt; /*定義指向termios結(jié)構(gòu)類型的指針opt*/
……
//獲得串口指向termios結(jié)構(gòu)的指針
tcgetattr(fd, &opt);
…
opt.c_cflag &= ~CRTSCTS…
//將修改后的termios數(shù)據(jù)設(shè)置到串口中
tcsetattr(fd,TCANOW,&Opt);
……
讀寫串口是通過使用read函數(shù)和write函數(shù)實現(xiàn)的。在Linux系統(tǒng)中,對設(shè)備的讀寫類似于對文件的讀寫。下面給出對串口的寫操作的代碼:
……
int len;
//待發(fā)送數(shù)據(jù)
char sbuf[]={Hello,thisis a Serial_Port test!/n};
int send_len=sizeof(sbuf);
//發(fā)送緩沖區(qū)字節(jié)數(shù)定義
len= write(fd,sbuf,send_len);//
if(n == -1)
printf("Wirte sbuferror./n");
……
在完成對設(shè)備文件讀寫操作后,需要調(diào)用close函數(shù)關(guān)閉該文件描述符。
以上就是關(guān)于Linux下串口文件的相關(guān)知識,你學會了嗎?
- 上一篇:程序員編程入門須知
- 下一篇:4類程序員直呼好用的嵌入式開發(fā)輔助工具