1. UART基础回顾:协议帧格式、波特率与采样时钟、全双工与半双工通信模式

各位同学好,我是老周。咱们这门课叫《UART通信性能调优与硬件流控中断处理调试实战》,第一节课,先把地基打牢。UART这东西,说白了就是串口,搞嵌入式的没人不认识它。但说实话,很多人用了好几年,遇到问题还是抓瞎——乱码、丢数据、死锁,归根结底是基础没吃透。

今天我们就从帧格式、波特率、采样时钟、全双工/半双工这几个最核心的点,重新捋一遍。我会结合我这些年踩过的坑,帮你把UART的底裤扒干净。

1.1 UART协议帧格式——一个字节是怎么飞过去的?

UART是异步串行通信,没有时钟线。收发双方靠约定好的波特率,在数据线上一个bit一个bit地传。一帧数据长什么样?我画个图你就明白了。

标准UART帧结构(8-N-1):
起始位(1) + 数据位(8) + 校验位(0) + 停止位(1) = 10 bits

这是最常用的配置,也叫8N1。8个数据位,无校验,1个停止位。

UART 帧格式(8N1) 空闲 高电平 起始 低电平 D0 LSB D1 D2 D3 D4 D5 D6 D7 MSB 停止 高电平 时间方向 → 关键说明: • 空闲时 TX 线保持高电平 • 起始位拉低,告诉接收方“我要发数据了” • 数据位从 LSB(最低位)开始发送,MSB 最后 • 停止位恢复高电平,为下一帧做准备

看到这个图,你应该能理解UART为什么叫“异步”了——没有时钟线,全靠起始位和停止位来“对齐”帧边界。接收方检测到起始位的下降沿,就开始按波特率采样。

我的经验: 调试时如果发现第一个字节总是对的,后面全乱,十有八九是停止位配置不匹配。我曾经被一个设备坑过——它用1.5个停止位,我配了1个,结果每帧都错位。查了整整一个下午。

1.2 波特率与采样时钟——速度与精度的博弈

波特率就是每秒传多少个bit。115200 bps意味着每bit约8.68微秒。但问题来了:接收方怎么知道什么时候该采样?

UART接收器内部有一个采样时钟,通常是波特率的16倍或8倍。比如115200波特率,16倍过采样就是1.8432 MHz。接收方检测到起始位后,等8个采样时钟(半bit时间),然后每16个时钟采一次,正好采到每个bit的中间位置。

波特率误差容忍度:

理论上,收发双方的波特率误差不能超过 ±2%(16倍过采样时)。超过这个范围,采样点会逐渐偏离bit中心,最终导致采样错误。

波特率 (bps) 每bit时间 (μs) 16倍过采样时钟 (MHz) 常见应用
9600 104.17 0.1536 调试终端、低速传感器
115200 8.68 1.8432 标准通信、GPS模块
921600 1.09 14.7456 高速数据传输
3000000 0.33 48.0 短距离高速通信
避坑指南: 我曾经在一个项目里用STM32的HSE 8MHz晶振,想跑921600波特率。结果算出来分频系数是小数,实际波特率误差达到3.2%。通信时好时坏,换了16MHz晶振才解决。记住:整数分频才是王道,小数分频误差大。

1.3 全双工与半双工——两条线 vs 一条线

UART的全双工模式,就是TX和RX各用一条线,可以同时收发。这是最常用的方式。半双工呢?只有一条数据线,同一时间只能发或者只能收。

你可能会问:半双工UART有什么用?嗯,我在做RS485总线的时候就经常遇到。RS485是差分信号,半双工,靠使能引脚切换收发方向。如果方向切换时机没把握好,数据就撞车了。

特性 全双工 半双工
信号线数量 2条(TX + RX) 1条(共用)
同时收发 支持 不支持
典型应用 TTL串口、蓝牙模块 RS485、单线UART
方向控制 不需要 需要GPIO控制使能
调试难度 低 中(方向切换易出错)
我的习惯: 做半双工UART时,我会在发送完成后加一个微秒级的延时再切回接收。别小看这个延时,少了它,最后一个字节可能被自己回环接收。我吃过这个亏,数据包末尾总多一个0xFF,查了三天才发现是方向切换太快。

1.4 本章小结——基础决定高度

UART看似简单,但帧格式、波特率精度、全双工/半双工的选择,每一个细节都可能成为你调试路上的绊脚石。我见过太多工程师,上来就调应用层,结果发现是波特率配错了,或者停止位不对。基础不牢,地动山摇。