1. UART 基础概念

1.1 UART 通信协议原理

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种采用异步串行通信方式的硬件接口协议。与 SPI、I²C 等同步协议不同,UART 在传输数据时不依赖共享时钟信号,而是通过收发双方预先约定的波特率(Baud Rate)来同步数据采样时刻。

UART 通信的基本链路结构如下:

核心特征: 全双工(两条独立数据线 TX / RX)、异步(无时钟线)、点对点(仅两个设备通信)。
UART 点对点异步通信链路 设备 A (发送器/接收器) TX ──→ RX 设备 B (发送器/接收器) RX ←── TX TX 数据流 RX 数据流 无时钟线:收发双方依靠相同波特率实现位同步

1.2 数据帧结构:起始位 / 数据位 / 校验位 / 停止位

UART 以帧(Frame)为基本传输单元。一帧数据由以下字段按固定顺序组成:

字段 位宽 电平状态 功能说明
起始位 1 bit 高 → 低(下降沿) 标志帧开始,接收器以此边沿同步采样时钟
数据位 5 ~ 9 bit(常用 8 bit) LSB 优先或 MSB 优先 承载有效载荷数据
校验位 0 / 1 bit 奇校验 / 偶校验 / 无 可选检错机制
停止位 1 / 1.5 / 2 bit 高电平 帧结束标志,为下一帧起始位提供间隔
工程经验: 嵌入式系统中默认配置通常为 8N1(8 数据位、无校验、1 停止位)。该配置在效率和兼容性之间取得最佳平衡。
UART 数据帧结构(8N1 格式) 空闲 高电平 起始 1 bit D0 D1 D2 D3 D4 D5 D6 D7 8 位数据(LSB 优先) 停止 1 bit 空闲 一帧数据(10 bit 总长) 起始位下降沿触发接收器采样时钟同步

1.3 波特率计算

波特率(Baud Rate)定义每秒传输的符号数。在 UART 中,一个符号对应一个 bit,因此波特率等于比特率(bps)。

波特率与系统时钟、分频器的关系如下:

核心公式:
波特率 = 系统时钟频率 / (16 × 分频系数)
或:波特率 = 系统时钟频率 / (分频系数)

不同 UART 硬件实现的分频方式略有差异,常见两种模式:

模式 采样倍率 分频公式 典型应用
标准模式 16 倍过采样 DIV = CLK / (16 × BAUD) STM32、NXP LPC 系列
高速模式 8 倍过采样 DIV = CLK / (8 × BAUD) 高波特率场景(≥ 1 Mbps)

常用波特率与分频系数示例(假设系统时钟 16 MHz,16 倍过采样):

目标波特率 分频系数(DIV) 实际波特率 误差
9600 104.167 → 104 9615.38 +0.16%
19200 52.083 → 52 19230.77 +0.16%
115200 8.681 → 9 111111.11 -3.55%
921600 1.085 → 1 1000000.00 +8.51%
工程警告: 波特率误差应控制在 ±2% 以内,否则接收端采样点偏移可能导致帧错误(Framing Error)。115200 bps 在 16 MHz 下误差 -3.55%,已接近临界值,建议改用 8 倍过采样或调整系统时钟。
UART 波特率生成原理 系统时钟 CLK (16 MHz) 分频器 ÷ DIV 波特率时钟 BAUD_CLK 采样时钟 ×16 BAUD_CLK = CLK / DIV;采样时钟 = BAUD_CLK × 16(过采样) 每个 bit 被采样 16 次,取中间 3 次多数决

1.4 波特率误差与采样窗口

UART 接收器使用过采样技术(通常 16 倍)在每个 bit 周期内采集多个样本,通过多数决确定实际电平值。采样窗口位于每个 bit 的中间区域,以容忍一定的时钟偏差。

波特率误差容忍度取决于以下因素:

  • 帧长度: 帧越长(如 9 位数据 + 2 位停止),累积误差越大。
  • 过采样倍数: 16 倍过采样比 8 倍过采样容忍度更高。
  • 起始位同步精度: 起始位下降沿的检测误差直接影响后续采样点。
经验法则: 对于 8N1 帧(10 bit 总长),16 倍过采样下可容忍约 ±4% 的波特率误差;对于长帧(如 9 位数据 + 2 停止 = 12 bit),容忍度降至 ±3% 以内。

1.5 常见波特率标准与选型建议

波特率 应用场景 线缆长度 备注
9600 调试串口、低速传感器 ≤ 15 m 最通用,兼容性最好
19200 工业控制、GPS 模块 ≤ 10 m 中等速率
115200 标准调试终端、蓝牙模块 ≤ 3 m 嵌入式系统默认首选
921600 高速数据采集、固件下载 ≤ 1 m 需注意时钟误差
2 Mbps+ RS-485 高速总线 ≤ 0.5 m 需硬件流控支持
驱动开发建议: 在 Linux 内核 UART 驱动中,波特率通过 termios 结构体的 c_cflag 字段设置,驱动层调用 uart_update_timeout() 和 uart_set_termios() 回调完成分频系数重算。后续章节将深入讲解中断模式下的波特率动态切换实现。