UART串口通信的“心跳”与“边界”:起始位如何唤醒接收机,停止位怎样守住帧完整性
你有没有遇到过这样的场景:MCU明明在拼命printf("Hello"),串口助手却只显示一串乱码?或者固件升级到98%突然卡死,重试三次后又莫名其妙成功了?又或者,在电机启动瞬间,RS-485总线上几台设备同时失联,重启后恢复如初?
这些不是玄学,也不是“运气不好”。它们背后,往往藏着一个被低估、被跳过、却被UART硬件一丝不苟执行了四十多年的底层机制——起始位的唤醒逻辑和停止位的边界判定。
UART没有时钟线,没有握手信号,没有自动重传。它靠什么把一字节数据从A点送到B点,还让接收方确信:“就是这个字节,不多不少,没错”?答案就藏在一帧最不起眼的两个比特里:开头那个“0”,和结尾那一段“1”。
一帧UART数据,到底长什么样?
先抛开术语,想象你站在火车站月台等一列火车。
- 空闲时,月台是空的(高电平);
- 突然,远处传来一声汽笛(下降沿)——这是起始位,告诉你:“车来了,准备上车!”;
- 接着,车厢依次驶过(数据位),你按顺序数清每节车厢编号(LSB优先);
- 可能还有一节校验车厢(奇偶校验位),帮你快速判断是否有人中途上错车;
- 最后,列车完全驶离,月台再次空旷(高电平持续一段时间)——这就是停止位,它说:“本趟结束,你可以松口气了,下趟车来之前,先喘口气。”
这就是UART一帧的完整生命节奏。它的标准结构是:
| 字段 | 长度 | 电平 | 说明 |
|---|---|---|---|
| 起始位 | 1 bit | 0 | 唯一唤醒信号,强制触发接收采样 |
| 数据位 | 5–9 bit | 可变 | 默认8 bit(ASCII/UTF-8兼容性最佳) |
| 校验位 | 0 or 1 bit | 可变 | 奇/偶校验,简单检错,现代应用中常禁用 |
| 停止位 | 1 / 1.5 / 2 bit |