3. UART数据帧结构:起始位、数据位、校验位、停止位详解

UART通信说白了就是按“帧”来传数据。每一帧就像一封信,有固定的格式:起始位、数据位、校验位、停止位。我刚开始学的时候总觉得这些位很抽象,直到在项目里用逻辑分析仪抓波形,才真正看明白它们是怎么配合的。

咱们先看一张完整的帧结构图,心里有个整体印象:

UART 标准数据帧结构(8N1 格式) 空闲 起始 D0 D1 D2 D3 D4 D5 D6 D7 校验 停止 关键说明: • 空闲位:总线为高电平(逻辑1),表示无数据传输 • 起始位:拉低电平(逻辑0),通知接收方准备接收 • 数据位:LSB在前(D0先发),MSB在后(D7最后发) • 停止位:恢复高电平(逻辑1),表示一帧结束

3.1 起始位——通信的“发令枪”

起始位是UART帧的起点。它的作用很简单:告诉接收方“我要开始发数据了”。

具体怎么做的?发送方把TX线从空闲的高电平拉低,持续一个位时间。接收方检测到这个下降沿,就知道数据来了。

起始位核心特征:

  • 长度:固定1位
  • 电平:逻辑0(低电平)
  • 作用:同步接收方时钟,提供采样基准
  • 检测方式:下降沿触发

我在一个项目中遇到过接收端时钟漂移的问题。当时波特率设的是115200,但接收端的晶振精度不够,导致采样点偏移。后来我加了起始位重同步机制,每次检测到下降沿都重新校准采样时钟,问题就解决了。

实战技巧:接收端检测起始位时,建议在下降沿后的1/2位时间处采样一次确认。这样可以避免毛刺误触发。我习惯在驱动里加一个“去抖”逻辑,连续采样两次低电平才确认起始位有效。

3.2 数据位——真正的“干货”

数据位就是你要传的实际数据。UART支持5到9位数据位,最常用的是8位。为什么?因为一个字节正好8位,方便和内存、寄存器对接。

数据位的发送顺序是LSB(最低有效位)在前,MSB(最高有效位)在后。举个例子,你要发送0x55(二进制01010101),发送顺序是:1→0→1→0→1→0→1→0。

数据位配置 常见场景 说明
5位 老式电传机 基本淘汰,很少用
6位 某些ASCII设备 仅传部分字符集
7位 纯ASCII通信 高位不用,节省带宽
8位 绝大多数场景 标准字节传输,推荐使用
9位 多机通信/地址帧 第9位做地址/数据标志

注意:发送方和接收方的数据位长度必须一致。我曾经调试过一个设备,发送端配了8位数据,接收端配了7位,结果收到的数据全是乱的。用示波器一看才发现是数据位长度不匹配。

3.3 校验位——数据的“体检医生”

校验位用来检测数据传输过程中有没有出错。UART支持三种校验模式:无校验、奇校验、偶校验。

校验位的计算规则很简单:

  • 偶校验:数据位中1的个数 + 校验位 = 偶数
  • 奇校验:数据位中1的个数 + 校验位 = 奇数

举个例子,数据0x55(二进制01010101)有4个1:

  • 偶校验:校验位=0(4个1已经是偶数)
  • 奇校验:校验位=1(需要凑成奇数个1)
校验模式 校验位值 检测能力 适用场景
无校验(N) 无 无 短距离、高可靠性链路
奇校验(O) 使总1数为奇数 检测奇数位错误 对数据完整性要求高
偶校验(E) 使总1数为偶数 检测奇数位错误 工业现场总线常用

我的经验:校验位只能检测奇数个位的翻转错误。如果两个位同时翻转(比如00变成11),校验位是检测不出来的。所以对数据完整性要求极高的场景,建议在应用层再加CRC校验。

3.4 停止位——帧的“句号”

停止位标志一帧数据的结束。发送方把TX线拉回高电平,持续1位、1.5位或2位的时间。

停止位的作用有两个:

  1. 帧间隔:给接收方时间处理收到的数据
  2. 同步恢复:让总线回到空闲状态,准备接收下一帧
停止位长度 特点 推荐场景
1位 标准配置,效率最高 大多数通用场景
1.5位 仅用于5位数据位 老式设备兼容
2位 容错性好,效率低 噪声环境、低速设备

避坑指南:我曾经在一条长距离(约50米)的RS232链路上遇到过停止位过短导致帧错位的问题。当时环境干扰大,1位停止位不够稳定。换成2位停止位后,通信就正常了。如果你的通信环境噪声大,不妨试试2位停止位。

3.5 帧格式速查表

实际项目中,帧格式通常写成类似“8N1”这样的简写。我来解释一下:

简写 数据位 校验位 停止位 总位数
8N1 8 无 1 10
8E1 8 偶校验 1 11
8O1 8 奇校验 1 11
7E2 7 偶校验 2 11
9N1 9 无 1 11

你想想看,8N1是最常见的配置。为什么?因为它效率高——10位传8位有效数据,有效载荷80%。而且8位正好是一个字节,软件处理起来最方便。

3.6 驱动开发中的帧配置实战

在驱动里配置帧格式,其实就是设置几个寄存器。以STM32为例:

/* USART帧格式配置示例 */
USART_InitTypeDef USART_InitStructure;

/* 8位数据,无校验,1位停止位(8N1) */
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;

/* 或者 8位数据,偶校验,1位停止位(8E1) */
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_StopBits = USART_StopBits_1;

注意:配置校验位时,数据位长度要相应调整。比如8位数据+校验位,有些芯片内部会把数据位设为9位(8位数据+1位校验)。一定要看芯片手册确认。

嗯,到这里UART帧结构的四个部分就讲完了。起始位是发令枪,数据位是干货,校验位是体检医生,停止位是句号。理解了这些,你就能看懂UART波形图,也能正确配置驱动了。