
Linux 串口編程:解鎖設備通信的鑰匙
在嵌入式系統、物聯網(IoT)以及各類硬件設備之間,串口通信(Serial Communication)扮演著舉足輕重的角色
它以其簡單、可靠和廣泛兼容性的特點,成為許多低速率、長距離數據傳輸的首選方案
而在Linux操作系統下,通過C語言進行串口編程,不僅能夠充分發揮Linux系統的強大功能,還能實現高效、靈活的設備通信
本文將深入探討Linux串口編程的精髓,從基礎知識到實戰應用,帶你領略這一技術的無限魅力
一、串口通信基礎
串口通信,全稱為串行通信(Serial Communication),是一種數據按位順序傳輸的通信方式
與傳統的并行通信相比,雖然其傳輸速率較慢,但所需的線路資源少,易于實現長距離傳輸,且成本較低
串口通信的基本參數包括波特率(Baud Rate)、數據位(Data Bits)、停止位(Stop Bits)和奇偶校驗(Parity),這些參數決定了通信雙方如何理解彼此發送的數據
- 波特率:指每秒傳輸的比特數,常見的波特率有9600、19200、38400、115200等
- 數據位:每個數據包中的有效數據位數,通常為7位或8位
停止位:用于標識數據包結束,通常為1位或2位
- 奇偶校驗:用于檢測數據傳輸中的錯誤,分為無校驗(None)、奇校驗(Odd)、偶校驗(Even)等
二、Linux下的串口編程環境
Linux系統提供了豐富的接口和工具來支持串口編程
其中,`termios`結構體是核心,它定義了串口通信的各種參數和配置
在C語言中,通過`termios.h`頭文件中的函數,可以方便地對串口進行配置和控制
- 打開串口:使用標準的open()函數,通過指定設備文件(如`/dev/ttyS0`、`/dev/ttyUSB0`)來打開串口
- 配置串口:通過tcgetattr()獲取當前串口配置,使用`cfsetispeed()`和`cfsetospeed()`設置波特率,調整`c_cflag`、`c_lflag`、`c_iflag`、`c_oflag`等字段來配置數據位、停止位、奇偶校驗等參數,最后通過`tcsetattr()`應用配置
- 讀寫操作:使用read()和write()函數進行數據的讀寫
對于非阻塞或異步操作,可以結合`select()`、`poll()`或`epoll()`機制
- 關閉串口:使用close()函數關閉串口設備
三、實戰:Linux串口編程示例
下面是一個簡單的Linux串口編程示例,演示如何打開串口、配置參數、發送和接收數據,并最終關閉串口
include
include
include
include
include
include
include
int set_serial_attributes(int fd, int speed) {
struct termios tty;
if(tcgetattr(fd, &tty) != 0) {
perror(tcgetattr);
return -1;
}
cfsetospeed(&tty,speed);
cfsetispeed(&tty,speed);
tty.c_cflag= (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc【VMIN】 = 1; // read doesnt block
tty.c_cc【VTIME】 = 5; // 0.5 seconds read timeout
tty.c_iflag &=~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag|= (CLOCAL | CREAD); // ignore modem controls,
// enable reading
tty.c_cflag&= ~(PARENB | PARODD); // shut off parity
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if(tcsetattr(fd, TCSANOW, &tty) != 0) {
perror(tcsetattr);
return -1;
}
return 0;
}
int main() {
charportname = /dev/ttyUSB0;
int fd =open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if(fd < {
perror(open);
return 1;
}
if(set_serial_attributes(fd, B115200) < 0) {
close(fd);
return 1;
}
charwrite_buf【】 = Hello, Serial Port!
;
intn_written =write(fd,write_buf,sizeof(write_buf));
if(n_written < {
perror(write);
close(fd);
return 1;
}
charrea