Linux串口编程_termios
1.1?Linux串口編程主要是設置structtermios結構體的個成員值。Termios是在POSIX規范中定義的標準接口,表示終端設備(包括虛擬終端丶串口等),串口是一種終端設備,一般通過終端編程接口對其進行配置和控制。
串口的配置最重要的是以下結構體定義中標明紅色的條目,配置方法如下:
? 某幾位清0:struct_name.flag&=? ~(MASK1 | MASK 2….)
? 某幾位置1:struc_name.flag|=??? (MASK1 | MASK2…)
1.2例如:設置115200的波特率:
??????? Structtermios new_cfg;
??????? New_cfg.c_cflag|= B115200
1.3本文寫作目的旨在方便查閱串口設置結構體的組成,方便開發
二、結構體定義
#include<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];???????//控制特性
Speed_t c_ispeed;???????????? ?//輸入速度
Speed_t c_ospreed;????????????//輸出速度
}
??2.1?輸入模式標志(c_iflag:16bit)
??
| INPCK | 奇偶校驗使能 |
| IGNPAR | 忽略奇偶校驗錯誤 |
| PARMRK | 奇偶校驗錯誤掩碼 |
| ISTRIP | 裁剪掉第8比特 |
| IXON | 啟動輸出軟件控制流 |
| IXOF | 啟動輸入軟件控制流 |
| IXANY | 輸入任意字符可以重新啟動輸入(默:起始字符) |
| IGNBRK | 忽略輸入終止條件 |
| BRKINT | 當檢測到輸入終止條件時發送SIGINT信號 |
| INLCR | 當收到NL(換行符)轉換CR(回車符) |
| IGNCR | 忽略收到的CR |
| ICRNL | 當收到CR轉換為NL |
| IUCLC | 講接收到的大寫字符映射為小寫字符 |
| IMAXBEL | 當輸入隊列滿時響鈴 |
2.2輸出模式標志(c_oflag :16bit)
| OPOST | 啟動輸出處理功能,如果不設置,其他位忽略 |
| OLCUC | 將輸出中的大寫字符轉換成小寫字符 |
| ONLCR | 將輸出中的換行符(‘\n’)轉換成回車符(‘\r’) |
| ONOCR | 如果當前列號為0,則不輸出回車字符 |
| OCRNL | 將輸出中的回車符轉換成換行 |
| ONLRET | 不輸出回車符 |
| OFILL | 發送填充字符以提供延時 |
| OFDEL | 如果設置該標志,則表示填充字符為DEL字符,否則為NUL |
| NLDLY | 換行延時掩碼 |
| CRDLY | 回車延時掩碼 |
| TABDLY | 制表符延時掩碼 |
| BSDLY | 水平退格符延時掩碼 |
| VTDLY | 垂直退格符延時掩碼 |
| FFLDY | 換頁符延時掩碼 |
2.3控制模式標志(c_cflag:16bit)
| CBAUD | 波特率的位掩碼 |
| B0 | 0波特率(放棄DTR) |
| … | … |
| B1800 | 1800的波特率 |
| B2400 | 2400的波特率 |
| B4800 | 4800的波特率 |
| B9600 | 9600的波特率 |
| B19200 | 19200的波特率 |
| B38400 | 38400的波特率 |
| B57600 | 57600的波特率 |
| B115200 | 115200的波特率 |
| EXTA | 外部時鐘率 |
| EXTB | 外部時鐘率 |
| CSIZE | 數據位的位掩碼 |
| CS5 | 5個數據位 |
| CS6 | 6個數據位 |
| CS7 | 7個數據位 |
| CS8 | 8個數據位 |
| CSTOPB | 2個停止位(不設置則是一個) |
| GREAD | 接收使能 |
| PARENB PARODD | 校驗使能位 使用奇校驗而不是偶校驗 |
| HUPCL | 最后關閉時掛線(放棄DTR) |
| CLOCAL | 本地連接(不改變端口所有者) |
| CRTSCTS | 硬件流控 |
?
?
2.4本地模式標志(c_lflag:16bit)
| ISIG | 若收到信號字符(INTR,QUIT等)則會產生相應的信號 |
| ICANON | 啟動規范模式 |
| ECHO | 啟動本地回顯功能 |
| ECHOE | 若設置ICANON則允許退格操作 |
| ECHOK | 若設置ICANON,則KILL字符會刪除當前行 |
| ECHONL | 若設置ICANON,則允許回顯換行符 |
| ECHOCTL | 若設置ECHO,則控制字符會顯示成^x,其中x的ASCII碼等于給相應的控制字符的ASCII碼加上0x40. |
| ECHOPRT | 若設置ICANON和IECHO,則刪除字符和被刪除的字符都會被顯示 |
| ECHOKE | 若設置ICANON,則允許回顯在ECHOE和ECHOPRT中設定的KILL字符 |
| NOFLASH | 在通常情況下,當接收到INTR,QUIT,SUSP控制字符時,會清空輸入和輸出隊列。如果設置改標志,則所有的隊列不會被清空 |
| TOSTOP | 若一個后臺進程師徒向他的控制終端進行寫操作,則系統向改后臺進程的進程組發送SIGTTOU信號。該信號通常終止進程的執行 |
| IEXTEN | 啟動輸入處理功能 |
2.5控制特性(c_cc[])
| VINTR | 中斷控制字符,對應的鍵位ctrl+c |
| VQUIT | 退出操作符,對應的鍵為ctrl+z |
| VERASE | 刪除操作符,對應Backspace |
| VKILL | 刪除行符,對應的鍵為ctrl+u |
| VEOF | 文件結尾符,對應的鍵為ctrl+d |
| VEOL | 附加行結尾符,對應的鍵為carriage return |
| VEOL2 | 第二行結尾符,對應的鍵為line feed |
| VMIN | 指定最少讀取的字符數 |
| VTIME | 指定讀取的每個字符之間的超時時間 |
三、串口配置基本流程
3.1保存串口配置
??int tcgetattr(int fd, struct termios *termios_p);
3.2激活選項
?CLOCAL和CREAD分別用于本地連接和接收使能,因此要先通過位掩碼的方式激活這兩個選項:
newtio.c_cflag |=CLOCAL |CREAD;
3.3設置波特率
?? 波特率的設置不能直接通過掩碼來設定,有提供設置函數:
?cfsetispeed(&new_cfg,B115200);
cfsetospeed(&new_cfg,B115200);
3.4設置數據位
首先去掉數據位中的位掩碼,再重新按要求設置:
New_cfg.c_cflag &=~CSIZE;
New_cfg.c_cflag |=CS8;
3.5設置奇偶校驗位
?New_cfg.c_cflag|=(PARODD | PARENB)???? //激活校驗位使能
New_cfg.c_iflag???????????????????????? //激活對輸入數據的奇偶校驗使能
3.6設置停止位
New_cfg.c_cflag? &= ~CSTOPB??????????? //講奇偶校驗位設置一個比特
New_cfg.c_cflag |=CSTOPB??????????????? //講奇偶校驗位設置兩個比特
3.7設置最少字符和等待時間
New_cfg.c_cc[VTIME]=0;
New_cfg.c_cc[VMIN]=0;
3.8清除串口緩存
由于串口在重新設置之后,需要對當前的串口設備進行適當的處理,這時就可以調用在<termios.h>中聲明的tcdrain(),tcflow(),tcflush()等函數來處理目前串口緩沖中的數據,格式如下:
int tcdrain(int fd)? //使程序阻塞,直到輸出緩沖區的數據全部發送完畢
int tcflow(int fd,int action)??? //用于暫停或者重新開始輸出
int tcflush(int fd,int queue_selector)? //用于清空輸入輸出緩沖區
3.9激活配置
tcsetattr(int fd,int option_action,conststruct terios *termrios_p)
Param :
Optional_options:
?????????????? TCSCANOW:配置的修改立即生效
????????????????????????????? ? TCSADRAIN:配置的修改在所有寫入fd的輸出都傳輸完畢之后生效
?????????????? TCSAFLUSH:所有已接受但未讀入的輸出都將在修改生效之前被丟棄
Return:
?? 0:成功
? -1:失敗
3.10使用串口
串口配置完成后就可以像文件一樣讀寫數據,使用read(),write()函數
四、串口配置實例(通用函數封裝)
?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include<stdbool.h>
#include <termios.h>
/*@ Fn uartOpen
? ?@param ? ? uartDevicePath ? ? ?設備文件
? ?@param ? ? speed ? ? ? ? ? ? ? ? ? ? ? 波特率,默認115200
? ?@param ? ? dataWidth ? ? ? ? ? ? ? ?數據位寬,默認8bit
? ?@param ? ? stopBit ? ? ? ? ? ? ? ? ? ? ?停止位,true:2bit; ? ?false:1bit;
?
? ?@return ? ? ? fd ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 打開文件描述符
*/?
int uartOpen(char *uartDevicePath,int speed,int dataWidth,bool stopBit)
{
?//Info
int fd=-1;
struct termios new_cfg,old_cfg;?
printf("uart path=%s\n",uartDevicePath); ?
?//open device
fd=open(uartDevicePath,O_RDWR | O_NOCTTY );
if(fd==-1)
printf("open failed!\n");
//preserve the old configuration
if(tcgetattr(fd,&old_cfg)!=0)
? printf("Old config preserve failed!\n");
//set mode
new_cfg.c_cflag |=CLOCAL |CREAD;
//set baudrate
switch(speed){
? case 1800:{
? ?cfsetispeed(&new_cfg,B1800);
? ?cfsetospeed(&new_cfg,B1800);
}break;
? case 2400:{
? ?cfsetispeed(&new_cfg,B2400);
? ?cfsetospeed(&new_cfg,B2400);
}break;
? case 4800:{
? ?cfsetispeed(&new_cfg,B4800);
? ?cfsetospeed(&new_cfg,B4800);
}break;
? case 9600:{
? ?cfsetispeed(&new_cfg,B9600);
? ?cfsetospeed(&new_cfg,B9600);
}break;
? case 19200:{
? ?cfsetispeed(&new_cfg,B19200);
? ?cfsetospeed(&new_cfg,B19200);
? }break;
? case 38400:{
? ?cfsetispeed(&new_cfg,B38400);
? ?cfsetospeed(&new_cfg,B38400);
}break;
? case 57600:{
? ?cfsetispeed(&new_cfg,B57600);
? ?cfsetospeed(&new_cfg,B57600);
}break;
? case 115200:{
? ?cfsetispeed(&new_cfg,B115200);
? ?cfsetospeed(&new_cfg,B115200);
}break;
? default:{
? cfsetispeed(&new_cfg,B115200);
? cfsetospeed(&new_cfg,B115200);
? }break;
}
//set size of data
new_cfg.c_cflag &=~CSIZE;
switch(dataWidth){
case 5:{
new_cfg.c_cflag |=CS5;
}break;
case 6:{
new_cfg.c_cflag |=CS6;
}break;
case 7:{
new_cfg.c_cflag |=CS7;
}break;
case 8:{
new_cfg.c_cflag |=CS8;
}break;
default :{
new_cfg.c_cflag |=CS8;
}break;
}
//set stopbit:true 2 stopbit,false 1 stopbit
if(stopBit)
new_cfg.c_cflag |=(CSTOPB);
else
new_cfg.c_cflag &=~(CSTOPB);
//set others
new_cfg.c_cc[VTIME]=0;
new_cfg.c_cc[VMIN]=0;
//start
if(-1==tcsetattr(fd,TCSANOW,&new_cfg))
printf("Uart setting failed!\n");
return fd;
}
void main()
{
int fd=uartOpen("/dev/ttyUSB0",115200,8,true);
while(1){
;
//handle here
}
}
總結
以上是生活随笔為你收集整理的Linux串口编程_termios的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GDB调试入门
- 下一篇: Linux C 串口属性设置