2. UART协议基础:帧格式、波特率、奇偶校验、流控机制

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是嵌入式系统中最基础、最广泛使用的串行通信协议之一。在深入DMA驱动开发之前,必须透彻理解UART的物理层与数据链路层规范。本章将系统梳理UART帧结构、速率计算、差错检测与流量控制四大核心要素,为后续描述符配置与多串口并发传输奠定理论基础。

核心要点:UART是异步、全双工、点对点通信协议,依赖双方预先约定的帧格式与波特率完成数据收发,无需独立的时钟线。

2.1 UART帧格式

UART以字符(通常为5~8位)为单位进行传输,每个字符被封装在一个帧(Frame)中。标准UART帧由以下字段组成:

  • 起始位(Start Bit):1位,逻辑低电平(0),标志帧的开始,用于接收方同步时钟。
  • 数据位(Data Bits):5~8位,通常为8位(1字节),低位在前(LSB first)。
  • 奇偶校验位(Parity Bit):可选,0或1位,用于简单的差错检测。
  • 停止位(Stop Bit):1、1.5或2位,逻辑高电平(1),标志帧的结束。

下图展示了标准8N1(8数据位、无校验、1停止位)帧的时序结构:

UART 帧格式(8N1) 空闲 高电平 起始 低电平 D0 LSB D1 D2 D3 D4 D5 D6 D7 MSB 停止 高电平 空闲 时间轴(从左到右) 说明:8N1 表示 8 数据位、无校验(None)、1 停止位。每帧固定 10 位(1+8+1),是嵌入式系统默认配置。
驱动开发提示:在Linux内核中,帧格式通过struct termios的c_cflag字段配置。例如设置8N1:c_cflag |= CS8; c_cflag &= ~PARENB; c_cflag &= ~CSTOPB;。DMA描述符的配置必须与termios中的帧格式严格一致,否则接收端会出现帧错误(Frame Error)。

2.2 波特率

波特率(Baud Rate)定义每秒传输的符号数。对于UART,每个符号对应1位,因此波特率等于比特率(bps)。标准波特率包括:9600、19200、38400、57600、115200、230400、460800、921600等。

波特率决定了每一位的持续时间:

位时间 (T_bit) = 1 / 波特率

示例:波特率 115200 bps
T_bit = 1 / 115200 ≈ 8.68 μs
每帧(8N1)传输时间 = 10 × T_bit ≈ 86.8 μs
理论最大吞吐量 = 115200 / 10 = 11520 字节/秒

波特率误差容忍度:接收方通常允许 ±2%~±3% 的波特率偏差。超过此范围会导致采样点偏移,产生帧错误或数据错位。

波特率 (bps) 位时间 (μs) 8N1帧时间 (μs) 理论吞吐量 (KB/s) 典型应用场景
9600 104.17 1041.7 0.96 调试控制台、低速率传感器
115200 8.68 86.8 11.52 GPS模块、蓝牙串口
921600 1.09 10.9 92.16 高速数据采集、FPGA通信
3000000 0.33 3.3 300.00 UART-over-USB、高速外设
DMA驱动关键点:高波特率(如921600以上)下,CPU轮询方式会严重占用处理器资源。此时必须启用DMA模式,将数据搬运工作卸载给DMA控制器。描述符的传输粒度(单次DMA传输的字节数)应匹配波特率与系统中断延迟,避免FIFO溢出。

2.3 奇偶校验

奇偶校验(Parity Check)是一种简单的差错检测机制,通过统计数据位中1的个数,在奇偶校验位填入0或1,使总1的个数满足约定条件。

  • 无校验(None):不发送校验位,帧中无奇偶位。
  • 奇校验(Odd):数据位 + 校验位中1的总数为奇数。
  • 偶校验(Even):数据位 + 校验位中1的总数为偶数。
  • 强制校验(Mark/Space):校验位固定为1(Mark)或0(Space),不用于检错,仅用于特定协议。

奇偶校验只能检测奇数个位错误,无法检测偶数个位错误,也无法纠错。在噪声较大的工业环境中,建议配合CRC或更高级的链路层协议使用。

奇偶校验示例(偶校验,数据 0x53 = 0101 0011) D0=1 D1=1 D2=0 D3=0 D4=1 D5=0 D6=1 D7=0 校验=0 数据位中1的个数 = D0+D1+D4+D6 = 4(偶数) 偶校验要求总1个数为偶数,因此校验位填入0,保持总1个数仍为4(偶数) 若接收端计算总1个数为奇数,则报告校验错误(Parity Error)

2.4 流控机制

流控(Flow Control)用于协调发送端与接收端的数据速率,防止接收端缓冲区溢出。UART流控分为硬件流控和软件流控两大类。

2.4.1 硬件流控(RTS/CTS)

硬件流控使用独立的控制线实现握手:

  • RTS(Request to Send):输出信号,接收端准备好接收数据时置为有效(通常低电平有效)。
  • CTS(Clear to Send):输入信号,发送端检测到CTS有效时才能发送数据。

工作流程:

  1. 接收端缓冲区有空闲空间时,将RTS置为有效(通知发送端可以发送)。
  2. 发送端检测到CTS有效后,开始发送数据。
  3. 接收端缓冲区即将满时,将RTS置为无效(通知发送端暂停发送)。
  4. 发送端检测到CTS无效后,停止发送,直到CTS再次有效。
硬件流控(RTS/CTS)时序 发送端 接收端 TX 数据线 RTS(接收端→发送端) CTS(发送端→接收端) 流控步骤: ① 接收端缓冲区有空闲 → 置RTS有效(低电平) ② 发送端检测到CTS有效 → 开始发送数据 ③ 接收端缓冲区将满 → 置RTS无效(高电平) ④ 发送端检测到CTS无效 → 暂停发送,等待RTS再次有效

2.4.2 软件流控(XON/XOFF)

软件流控通过数据线传输特殊字符实现流量控制,无需额外硬件引脚:

  • XOFF(0x13):接收端发送此字符,通知发送端暂停发送。
  • XON(0x11):接收端发送此字符,通知发送端恢复发送。
DMA驱动注意事项:软件流控在DMA模式下存在风险——XON/XOFF字符可能被DMA直接搬运到接收缓冲区,而不会被UART硬件识别。如果必须使用软件流控,建议采用中断模式处理流控字符,或使用硬件流控替代。在Linux内核中,通过termios的CRTSCTS标志使能硬件流控。

2.5 帧错误与溢出错误

UART硬件在接收过程中会检测以下错误状态,这些状态在DMA驱动中需要通过中断或状态寄存器捕获:

错误类型 触发条件 硬件表现 驱动处理方式
帧错误(FE) 停止位采样为低电平 接收到的停止位不是高电平 丢弃该帧,统计错误计数,重新同步
奇偶错误(PE) 校验位与数据位不匹配 硬件计算校验结果不一致 丢弃该帧,或标记数据无效
溢出错误(OE) FIFO或接收缓冲区已满,新数据覆盖旧数据 丢失最早或最新的数据 增大FIFO阈值,或提高DMA传输频率
中断错误(BI) 接收线保持低电平超过一个帧时间 检测到break信号 触发break处理回调,或复位接收状态机
多串口并发传输关键:在驱动层面,每个UART端口独立维护错误状态寄存器。DMA描述符的回调函数中必须检查对应端口的LSR(Line Status Register),区分正常数据与错误数据。对于高波特率场景,溢出错误是最常见的瓶颈,需要通过合理的描述符环(Descriptor Ring)深度和DMA传输粒度来缓解。

2.6 本章小结

UART协议看似简单,但在DMA驱动开发中,帧格式、波特率、校验与流控的每一个细节都直接影响描述符的配置策略:

  • 帧格式决定DMA传输的数据位宽与帧同步方式。
  • 波特率决定DMA传输的实时性要求与FIFO阈值设置。
  • 奇偶校验影响DMA描述符的错误处理分支。
  • 流控机制决定DMA传输的启停逻辑与缓冲区管理策略。