1. UART基础回顾
1.1 UART通信协议原理
UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是一种采用异步串行通信方式的物理层协议。通信双方无需共享时钟信号,而是通过预先约定的波特率和帧格式完成数据收发。
核心特点:全双工、异步、点对点、无时钟线、依赖起始位同步。
UART通信的基本链路包含三根信号线:
- TXD(Transmit Data):发送数据线
- RXD(Receive Data):接收数据线
- GND(Ground):共地参考
1.2 UART帧格式详解
UART数据以帧为单位传输,每一帧由以下字段按顺序组成:
| 字段 | 位宽 | 电平状态 | 说明 |
|---|---|---|---|
| 起始位 | 1 bit | 逻辑 0(低电平) | 标志帧开始,接收端通过下降沿同步 |
| 数据位 | 5 ~ 9 bits | LSB 优先 | 实际有效数据,常用 8 bits |
| 校验位 | 0 / 1 bit | 奇/偶/无 | 可选,用于检错 |
| 停止位 | 1 / 1.5 / 2 bits | 逻辑 1(高电平) | 帧结束标志,保证帧间间隔 |
常见配置:8N1 = 8 数据位 + 无校验 + 1 停止位,是嵌入式 Linux 中最常用的 UART 帧格式。
1.3 波特率计算
波特率(Baud Rate)表示每秒传输的符号数。在 UART 中,1 个符号 = 1 bit,因此波特率等于比特率(bps)。
1.3.1 波特率与时钟分频
UART 外设通常由系统时钟(如 50 MHz、100 MHz)驱动,通过分频器产生目标波特率时钟。通用计算公式如下:
波特率 = 时钟频率 / (16 × 分频系数)
其中:
- 时钟频率:UART 模块输入时钟(Hz)
- 16:过采样因子(多数 UART IP 使用 16 倍过采样)
- 分频系数:可编程整数或小数分频值
示例:若 UART 时钟 = 50 MHz,目标波特率 = 115200,则分频系数 = 50,000,000 / (16 × 115200) ≈ 27.13。实际取整后,真实波特率会有微小偏差,需确保误差 < 2%。
1.3.2 常用波特率对照表
| 波特率(bps) | 位时间(μs) | 1 字节传输时间(8N1) | 典型应用场景 |
|---|---|---|---|
| 9600 | 104.17 | 1.04 ms | 调试终端、低速率传感器 |
| 19200 | 52.08 | 0.52 ms | 工业控制、GPS 模块 |
| 38400 | 26.04 | 0.26 ms | 蓝牙模块、串口屏 |
| 115200 | 8.68 | 86.8 μs | Linux 内核调试串口(最常用) |
| 230400 | 4.34 | 43.4 μs | 高速数据采集 |
| 921600 | 1.09 | 10.9 μs | 高速透传、FPGA 通信 |
波特率误差警告:Linux 内核中 UART 驱动通过
uart_get_baud_rate() 函数计算实际分频值。若分频取整后误差超过 ±2%,可能导致接收端采样点偏移,产生误码。驱动开发中务必通过 clk_round_rate() 确认实际时钟精度。
1.4 本章小结
- UART 是异步串行通信协议,依赖起始位下降沿同步,无需时钟线。
- 标准帧格式包含:起始位(1) + 数据位(5~9) + 校验位(0/1) + 停止位(1/2),8N1 是 Linux 串口默认配置。
- 波特率由系统时钟经 16 倍过采样分频 产生,驱动开发中必须校验分频误差 < 2%。
- Linux 内核通过
uart_get_baud_rate()和uart_update_timeout()管理波特率与超时参数,后续章节将深入 FIFO 与中断交互。