首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux 串口編程核心:struct termios 結構體字段全解析與配置實戰

     編輯:關於C語言

前言:termios——串口配置的「控制面板」

在 Linux/Unix 系統中,struct termios 是終端/串口屬性配置的核心數據結構。掌握其四大標志組 (c_iflag/oflag/cflag/lflag) 及控制字符數組 c_cc,是編寫健壯串口通信程序、Modbus 主站、GPS 解析器、調試終端的前提。本文系統梳理每個字段含義、常用宏定義、配置函數族 (tcgetattr/setattr 等)、波特率設置、cfmakeraw 原始模式一鍵配置。

一、 termios 結構體定義

struct termios {
    tcflag_t c_iflag;   // 輸入模式標志
    tcflag_t c_oflag;   // 輸出模式標志
    tcflag_t c_cflag;   // 控制模式標志 (波特率、數據位、校驗位、停止位)
    tcflag_t c_lflag;   // 本地模式標志 (規範/非規範、回顯、信號)
    cc_t     c_cc[NCCS]; // 控制字符數組 (VMIN, VTIME, VEOF, VINTR...)
};

二、 四大標志組詳細字段表

1. c_iflag:輸入處理模式

宏功能
IGNBRK忽略 BREAK 條件
BRKINTBREAK 產生 SIGINT (若未 IGNBRK)
IGNPAR忽略奇偶校驗錯誤
PARMRK標記奇偶校驗錯誤 (前綴 0xFF 0x00)
INPCK啟用輸入奇偶校驗
ISTRIP剝離第 8 位 (7 位數據模式)
INLCRNL → CR 映射
IGNCR忽略 CR
ICRNLCR → NL 映射 (終端常用,Enter 發送 \r 轉 \n)
IXON啟用輸出軟件流控 (XON/XOFF)
IXOFF啟用輸入軟件流控
IMAXBEL輸入緩衝區滿發 BEL

2. c_oflag:輸出處理模式

宏功能
OPOST啟用輸出後處理 (其它標志生效前提)
ONLCRNL → CR+NL (終端換行顯示標準)
OCRNLCR → NL
TABDLY製表符輸出延遲 (TAB0~TAB3)

3. c_cflag:硬件控制模式 (最關鍵)

宏功能
CBAUD / CBAUDEX波特率掩碼 (配合 cfsetispeed/ospeed)
CSIZE數據位掩碼:CS5/CS6/CS7/CS8
CSTOPB2 停止位 (未置則 1 位)
CREAD啟用接收器 (必置)
PARENB啟用奇偶校驗
PARODD奇校驗 (未置則偶校驗)
HUPCL最後關閉時掛斷調制解調器
CLOCAL忽略調制解調器狀態線 (直連串口必置)
CRTSCTS硬件流控 (RTS/CTS)

4. c_lflag:本地/行規範模式

宏功能
ISIG識別 INTR/QUIT/SUSP 產生信號
ICANON規範模式 (行緩衝、編輯、EOF)
ECHO回顯輸入字符
ECHOEERASE 刪除字符 / WERASE 刪除單詞
ECHOKKILL 刪除整行
ECHONL即使無 ECHO 也回顯 NL
TOSTOP後台寫入發送 SIGTTOU

三、 核心配置函數族

1. tcgetattr / tcsetattr:屬性讀寫

int tcgetattr(int fd, struct termios *termios_p);
int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);
  • optional_actions:TCSANOW 立即生效、TCSADRAIN 等輸出完成、TCSAFLUSH 等輸出完成並刷新輸入。
  • **模式**:讀取 → 修改 → 寫回,保留未修改字段。

2. 流控與斷續函數

  • tcsendbreak(fd, duration):發送 BREAK 信號。
  • tcdrain(fd):等待輸出緩衝區排空。
  • tcflush(fd, queue_selector):TCIFLUSH 刷輸入、TCOFLUSH 刷輸出、TCIOFLUSH 雙刷。
  • tcflow(fd, action):TCOOFF 停止輸出、TCOON 恢復、TCIOFF 發 XOFF、TCION 發 XON。

3. 波特率便捷函數

speed_t cfgetospeed(const struct termios *);
int cfsetospeed(struct termios *, speed_t);
speed_t cfgetispeed(const struct termios *);
int cfsetispeed(struct termios *, speed_t);
  • 常用常量:B9600, B115200, B921600 等。
  • B0:掛斷 (降低 DTR/RTS)。
  • 修改後必須 tcsetattr 才生效。

4. cfmakeraw:一鍵進入原始模式

// 等效手動配置
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;  // 8 數據位,無校驗,1 停止位

**原始模式特點**:字節流直通、無回顯、無行緩衝、無信號干擾、無流控,適合二進制協議 (Modbus RTU、自定義幀)。

四、 實戰配置模板:115200 8N1 原始模式

int setup_serial(int fd) {
    struct termios opt;
    if (tcgetattr(fd, &opt) < 0) return -1;

    cfmakeraw(&opt);  // 基礎原始模式
    
    // 設置波特率
    cfsetispeed(&opt, B115200);
    cfsetospeed(&opt, B115200);
    
    // 8N1 顯式確認
    opt.c_cflag &= ~CSIZE;
    opt.c_cflag |= CS8;      // 8 數據位
    opt.c_cflag &= ~PARENB;  // 無校驗
    opt.c_cflag &= ~CSTOPB;  // 1 停止位
    
    // 必置標志
    opt.c_cflag |= (CLOCAL | CREAD);  // 忽略 Modem 線、啟用接收
    
    // 非規範讀取超時設置 (100ms 無數據返回)
    opt.c_cc[VMIN] = 0;
    opt.c_cc[VTIME] = 10;  // 0.1s * 10 = 1s (實際單位 0.1s)
    
    if (tcsetattr(fd, TCSANOW, &opt) < 0) return -1;
    tcflush(fd, TCIOFLUSH);  // 清空殘留數據
    return 0;
}

五、 避坑指南

  1. 打開串口必用 O_RDWR | O_NOCTTY | O_NDELAY:非控制終端、非阻塞 (配合 fcntl 切換阻塞)。
  2. 波特率設置順序:先 cfsetispeed/ospeed,再 tcsetattr。
  3. VMIN/VTIME` 交互複雜:VMIN=0, VTIME>0` 為帶超時非阻塞讀;VMIN>0, VTIME=0` 為阻塞等滿。
  4. 權限問題:需加入 dialout 組或 chmod 666 /dev/ttyUSB0。
  5. 殘留數據:配置前後 tcflush(fd, TCIOFLUSH),防舊數據干擾。

六、 總結

struct termios 是串口編程的「基因密碼」。熟記四大標志組核心宏、掌握 tcgetattr/setattr/cfmakeraw 配置流程、理解 VMIN/VTIME 讀取語義、養成「讀取-修改-寫回」習慣,即可從容應對各類串口通信場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved