UART异步通信机制:没有时钟线,怎么对得上时间?
上一章我们聊了UART的硬件引脚和基本接线。这一章,咱们深入聊聊它的核心——异步通信。
说白了,异步通信就是没有专门的时钟线。不像SPI或I2C,收发双方共用一个时钟信号。UART只有TX和RX两根数据线,数据怎么对齐?靠的是约定好的波特率。
我刚开始做嵌入式时,总觉得这玩意儿不靠谱。没有时钟,两边怎么知道什么时候该采样?后来调了几个项目才明白,UART的异步机制其实很巧妙——它把时钟信息隐含在数据帧里。
异步通信的核心:波特率与采样时钟
收发双方必须提前约定一个共同的波特率,比如9600、115200。发送方按这个速率一位一位往外发,接收方用同样的速率去采样。
但这里有个细节:接收方内部其实有一个更高频的采样时钟,通常是波特率的16倍或64倍。比如波特率9600,采样时钟就是9600×16=153.6kHz。接收方用这个高频时钟去采样RX引脚,目的是找到每个数据位的最佳采样点。
关键点:接收方不是只在每个位的中点采一次,而是采多次,然后取中间那几次的值做判决。这样能有效抵抗信号抖动和噪声。
我在一个工业控制项目里遇到过这种情况:波特率设对了,但通信就是偶尔出错。后来用示波器一看,发现发送端的时钟精度不够,累积误差导致接收端采样点偏移。换了个晶振精度更高的MCU,问题就解决了。
UART帧格式:一帧里到底装了什么?
UART的数据是以帧为单位传输的。一帧通常包含以下几部分:
| 字段 | 长度 | 说明 |
|---|---|---|
| 起始位 | 1位 | 固定为低电平(逻辑0),标志一帧开始 |
| 数据位 | 5~9位 | 最常用8位,即一个字节 |
| 校验位 | 0或1位 | 可选:无校验、奇校验、偶校验 |
| 停止位 | 1、1.5或2位 | 固定为高电平(逻辑1),标志一帧结束 |
你想想看,起始位和停止位的作用是什么?起始位告诉接收方“准备开始收”,停止位告诉接收方“这帧结束了”。没有它们,接收方根本不知道数据从哪里开始、到哪里结束。
我个人习惯用8N1格式——8位数据、无校验、1位停止位。这是最通用的配置,兼容性最好。除非项目有特殊要求,否则我一般不会改。
帧格式的细节:为什么起始位是低电平?
UART总线在空闲时,TX和RX都保持高电平。起始位拉低,相当于一个下降沿触发信号。接收方检测到这个下降沿,就知道“有数据来了”,然后启动内部的位采样定时器。
这个设计很巧妙。如果起始位是高电平,空闲时也是高电平,接收方就没法区分“空闲”和“开始”。
小技巧:调试时如果发现接收方收不到数据,先用示波器看TX引脚有没有下降沿。没有下降沿,说明发送方根本没工作,或者电平被拉死了。
常见错误帧识别:示波器一看就懂
做UART调试,示波器是必备工具。我总结了几个最常见的错误帧波形,你对照着看,基本能定位90%的问题。
1. 波特率不匹配
发送方用9600,接收方设成19200。接收方采样速度翻倍,会把一个数据位当成两个位来读。结果就是收到一堆乱码。
示波器特征:波形宽度明显不对。比如9600的位宽约104μs,如果接收方设成19200,它只采52μs就认为一个位结束了。
2. 停止位丢失
发送方在停止位阶段没有拉高电平,或者拉高时间不够。接收方检测不到停止位,会报帧错误。
示波器特征:一帧结束后,电平没有回到高电平,或者高电平持续时间很短。
3. 校验位错误
数据在传输过程中被干扰,导致校验位计算不一致。接收方会报校验错误。
示波器特征:波形本身可能看不出异常,但接收方的状态寄存器里会标记校验错误位。
4. 溢出错误
接收方的缓冲区满了,但CPU还没来及读,新数据又来了。老数据被覆盖。
示波器特征:波形完全正常,但接收方丢数据。这通常是软件问题——中断响应太慢,或者缓冲区太小。
避坑指南:我曾经在一个多串口项目中,同时接收3路UART数据,每路115200波特率。结果频繁出现溢出错误。后来发现是中断优先级没配好,低优先级的中断被高优先级的中断一直抢占,导致数据来不及读。解决办法是把UART中断优先级调高,或者用DMA。
知识结构图:UART异步通信核心逻辑
下面这张图帮你理清UART异步通信的完整流程,从发送到接收,再到错误识别:
实战:用逻辑分析仪抓一帧数据
理论说完了,咱们动手。假设你手头有一个逻辑分析仪,抓一帧UART数据,看看它长什么样。
- 设置触发条件:下降沿触发,因为起始位是低电平。
- 设置采样率:至少是波特率的4倍以上,建议16倍。比如115200波特率,采样率设2MHz以上。
- 抓取波形:发送一个字节0x55(二进制01010101),观察波形。
- 解析:起始位(低)→ D0(1)→ D1(0)→ D2(1)→ D3(0)→ D4(1)→ D5(0)→ D6(1)→ D7(0)→ 停止位(高)。
0x55的波形是方波,高低电平交替,最容易观察。如果你看到波形不是这样,说明配置有问题。
调试技巧:我习惯先用0x55和0xAA这两个字节做测试。它们能暴露大部分位序和波特率问题。如果这两个字节收发正常,基本可以排除硬件和配置问题。
常见问题速查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 完全收不到数据 | TX/RX接反、电平不匹配、波特率差太多 | 示波器看TX有无波形,检查接线 |
| 收到乱码 | 波特率偏差、数据位/校验位配置不一致 | 用逻辑分析仪抓波形,对比位宽 |
| 偶尔丢字节 | 溢出错误、中断响应慢、缓冲区太小 | 检查接收端状态寄存器,加大缓冲区 |
| 帧错误频繁 | 停止位丢失、信号干扰、地线没共地 | 示波器看停止位电平,检查共地 |
嗯,这一章的内容就到这里。UART的异步机制其实不复杂,但细节很多。你只要记住:波特率、帧格式、起始位和停止位这四个要素,调试时用示波器或逻辑分析仪看波形,大部分问题都能快速定位。