通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter),一般稱做UART,是一種異步收發傳輸器,UART做爲異步串口通訊協議的一種,工做原理是將傳輸數據的每一個字符一位接一位地傳輸。linux
起始位 (邏輯0):表示傳輸字符的開始ios
數據位 :數據位的個數能夠設置爲4,5,6,7,8,構成一個字符。web
奇偶校驗位: 數據位加上奇偶校驗位後,邏輯「1」的數量爲偶數則爲偶校驗。爲奇數則爲奇校驗。在串口通訊中一種簡單的檢錯方式。有四種檢錯方式:偶、奇、高和低。固然沒有校驗位也是能夠的。對於偶和奇校驗的狀況,串口會設置校驗位(數據位後面的一位),用一個值確保傳輸的數據有偶個或者奇個邏輯高位。例如,若是數據是011,那麼對於偶校驗,校驗位爲0,保證邏輯高的位數是偶數個。若是是奇校驗,校驗位爲1,這樣就有3個邏輯高位。高位和低位不是真正的檢查數據,簡單置位邏輯高或者邏輯低校驗。這樣使得接收設備可以知道一個位的狀態,有機會判斷是否有噪聲干擾了通訊或者是否傳輸和接收數據是否不一樣步。數據結構
中止位:它是一幀數據的結束標誌。用於表示單個包的最後一位。典型的值爲1,1.5和2位。因爲數據是在傳輸線上定時的,而且每個設備有其本身的時鐘,極可能在通訊中兩臺設備間出現了小小的不一樣步。所以中止位不單單是表示傳輸的結束,而且提供計算機校訂時鐘同步的機會。適用於中止位的位數越多,不一樣時鐘同步的容忍程度越大,可是數據傳輸率同時也越慢。異步
空閒位:沒有數據傳輸時,爲邏輯「1「svg
傳輸方向:數據從高位(msb)開始傳輸仍是從低位(lsb)開始傳輸函數
函數描述了用於控制異步通訊端口的通用終端接口。參見Linux API termios描述ui
引用頭文件 spa
#include "termios.h"
結構體:3d
struct termios{
unsigned short c_iflag; /* 輸入模式標誌*/
unsigned short c_oflag; /* 輸出模式標誌*/
unsigned short c_cflag; /* 控制模式標誌*/
unsigned short c_lflag; /* 區域模式標誌或本地模式標誌或局部模式*/
unsigned char c_line; /* 行控制line discipline */
unsigned char c_cc[NCCS]; /* 控制字符特性*/
};
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 | 當輸入隊列滿的時候開始響鈴 |
IUTF9 | 當輸入是UTF8時,可以容許字符擦除在加工模式下正確執行 |
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、CR一、CR2和 CR3 |
TABDLY | 水平製表符輸出延遲,取值範圍爲:TAB0、TAB一、TAB2和TAB3 |
BSDLY | 空格輸出延遲,能夠取BS0或BS1 |
VTDLY | 垂直製表符輸出延遲,能夠取VT0或VT1 |
FFDLY | 換頁延遲,能夠取FF0或FF1 |
c_cflag:控制模式標誌,指定終端硬件控制信息
參數 | 參數說明 |
---|---|
CBAUD | 波特率(4+1位)(非POSIX) |
CBAUDEX | 附加波特率(1位)(非POSIX) |
CSIZE | 數據位長度,取值範圍爲CS五、CS六、CS7或CS8 |
CSTOPB | 設置兩個中止位 |
CREAD | 使用接收器 |
PARENB | 使用奇偶校驗 |
PARODD | 對輸入使用奇偶校驗,對輸出使用偶校驗 |
HUPCL | 關閉設備時掛起 |
CLOCAL | 忽略調制解調器線路狀態 |
CRTSCTS | 使用RTS/CTS流控制 |
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]:控制字符,用於保存終端驅動程序中的特殊字符,如輸入結束符等
NCCS | 參數說明 |
---|---|
VINTR | Interrupt字符 |
VEOL | 附加的End-of-file字符 |
VQUIT | Quit字符 |
VTIME | 非規範模式讀取時的超時時間 |
VERASE | Erase字符 |
VSTOP | Stop字符 |
VKILL | Kill字符 |
VSTART | Start字符 |
VEOF | End-of-file字符 |
VSUSP | Suspend字符 |
VMIN | 非規範模式讀取時的最小字符數 |
注意:控制符VTIME和VMIN之間有複雜的關係。VTIME定義要求等待的時間(百毫米,一般是unsigned char變量),而VMIN定義了要求等待的最小字節數(相比之下,read函數的第三個參數指定了要求讀的最大字節數)。
若是VTIME=0,VMIN=要求等待讀取的最小字節數,read必須在讀取了VMIN個字節的數據或者收到一個信號纔會返回。
若是VTIME=時間量,VMIN=0,無論可否讀取到數據,read也要等待VTIME的時間量。
若是VTIME=時間量,VMIN=要求等待讀取的最小字節數,那麼將從read讀取第一個字節的數據時開始計時,並會在讀取到VMIN個字節或者VTIME時間後返回。
若是VTIME=0,VMIN=0,無論可否讀取到數據,read都會當即返回
tcsetattr函數用於設置終端的相關參數。
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
參數fd爲打開的終端文件描述符
參數optional_actions用於控制修改起做用的時間,而結構體termios_p中保存了要修改的參數optional_actions能夠取以下的值:
參數 | 參數說明 |
---|---|
TCSANOW | 不等數據傳輸完畢就當即改變屬性。 |
TCSADRAIN | 等待全部數據傳輸結束才改變屬性。 |
TCSAFLUSH | 清空輸入輸出緩衝區才改變屬性。 |
返回值 | 參數說明 |
---|---|
EBADF | 非法的文件描述符。 |
EINTR | tcsetattr函數調用被信號中斷。 |
EINVAL | 參數optional_actions使用了非法值,或參數termios中使用了非法值。 |
ENCTTY | 非終端的文件描述符。 |
tcgetattr獲取與fd終端關聯的termios
int tcgetattr(int fd, struct termios *termios_p);
tcsetattr從新設置與fd終端關聯的termios
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
設置波特率
int cfsetispeed(struct termios *termios_p, speed_t speed); //輸入波特率
int cfsetospeed(struct termios *termios_p, speed_t speed); //輸出波特率
常見配置:
8位數據位、無校驗位:
c_cflag &= ~PARENB;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS8;
7位數據位、奇校驗:
c_cflag |= PARENB;
c_cflag |= PARODD;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS7;
7位數據位、偶校驗:
c_cflag |= PARENB;
c_cflag &= ~PARODD;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS7;
7位數據位、Space校驗:
c_cflag &= ~PARENB;
c_cflag &= ~CSTOPB;
c_cflag &= ~CSIZE;
c_cflag |= CS7;
//8位數據位,無校驗位,波特率115200
char *path = "/dev/ttyHSL1"
termios termios_p;
int fd = open(path, O_RDWR | O_NOCTTY);
tcflush(fd, TCIOFLUSH);
tcgetattr(fd, &termios_p);
termios_p.c_cflag &= ~PARENB;
termios_p.c_cflag &= ~CSTOPB;
termios_p.c_cflag &= ~CSIZE;
termios_p.c_cflag |= CS8;
cfsetispeed(&termios_p, B115200);
cfsetospeed(&termios_p, B115200);
tcsetattr(fd, &termios_p);
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path, int oflag, ... );
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
#include <unistd.h>
int close(int fd);
一個簡單的應用文本讀寫:
#include <stdio.h>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
struct {
int fd;
} global_v;
void open_t();
void read_t();
void write_t();
void close_t();
int main(){
open_t();
write_t();
read_t();
close_t();
return 0;
}
void open_t(){
char *file_path = "D:/log.txt";
int fd = open(file_path, O_RDWR | O_APPEND);
if(fd > 0){
global_v.fd = fd;
}
}
void read_t(){
if(global_v.fd < 0){
return;
}
int ret = -1;
char buf[256];
printf("read_t len = %d\n", sizeof(buf));
while((ret = read(global_v.fd, &buf, sizeof(buf))) > 0){
for(int i = 0; i < ret; i ++){
printf("%c ", buf[i]);
}
}
}
void write_t(){
if(global_v.fd < 0){
return;
}
char *write_buf = "testbuf\n";
int ret = write(global_v.fd, write_buf, strlen(write_buf));
printf("write = %d\n", ret);
}
void close_t(){
if(global_v.fd < 0){
return;
}
close(global_v.fd);
}