UART协议帧格式详解:起始位、数据位、校验位、停止位

UART通信,说白了就是一根线发、一根线收,双方约定好节奏,一比特一比特地往外送数据。这个“约定好的节奏”就是帧格式。我见过不少工程师,上来就调波特率,结果数据全是乱码,最后发现是帧格式配错了。嗯,咱们今天就把这个帧格式彻底掰开揉碎。

核心要点:UART帧是异步传输的基本单位,没有时钟线,全靠起始位同步、停止位对齐。帧格式一旦配错,通信必败。

2.1 帧结构总览

一个标准的UART数据帧,由4个部分组成:起始位、数据位、校验位(可选)、停止位。空闲时,TX线保持高电平。发送端拉低电平,接收端检测到下降沿,就知道“要发数据了”。

下面这张图,是我自己画的一个典型8N1帧结构(8数据位、无校验、1停止位),你一看就明白:

UART 8N1 帧结构图 空闲 高电平 起始 低电平 D0 D1 D2 D3 D4 D5 D6 D7 停止 高电平 说明: 1. 空闲时 TX 线保持高电平,接收端持续检测下降沿。 2. 起始位固定为低电平,持续 1 个比特时间。 3. 数据位 LSB 先发(D0 最先),MSB 最后(D7 最后)。 4. 停止位固定为高电平,持续 1/1.5/2 个比特时间。

2.2 起始位:通信的“发令枪”

起始位只有1个比特宽度,固定为低电平。它的作用就是告诉接收端:“注意,我要开始发数据了!”

接收端怎么知道起始位来了?它一直在采样RX线。当检测到从高电平跳变到低电平时,就认为起始位到达。然后启动内部的波特率计数器,在起始位的中间位置再采样一次确认。如果还是低电平,好,确认是起始位,开始收后面的数据位。

我的经验:我曾经遇到过一批设备,偶尔会收到0x00字节。查了半天,发现是电源纹波太大,导致空闲时TX线出现毛刺下降沿,接收端误判为起始位。后来在TX线上加了一个100kΩ上拉电阻,问题解决。起始位的检测对边沿敏感,电源噪声是常见干扰源。

2.3 数据位:真正的信息载体

数据位是帧的核心,长度可以是5、6、7、8位,最常见的是8位。为什么?因为一个字节正好8位,方便和MCU内部数据总线对齐。

这里有个关键点:数据位是LSB First,也就是最低有效位先发。比如你要发送0x55(二进制01010101),先发的是最低位1,然后是0、1、0、1、0、1、0,最后发最高位0。接收端收到后,再按LSB First拼回来。

我见过有人用逻辑分析仪抓波形,手动解析数据时按MSB顺序读,结果怎么都对不上。你想想看,顺序反了,数据肯定不对。

数据位长度 常见场景 备注
5位 老式电传打字机、某些工业协议 现在很少用
6位 某些ASCII字符集 不常见
7位 标准ASCII(0-127) 纯文本通信时用
8位 绝大多数嵌入式通信 最常用,推荐使用

注意:如果通信双方数据位长度不一致,比如发送端设8位,接收端设7位,接收端会把第8位当成校验位或停止位的一部分,结果就是数据错位、校验失败。我调试时第一件事就是检查双方的寄存器配置是否一致。

2.4 校验位:数据完整性的“小保镖”

校验位是可选的,用于检测传输过程中是否发生了单比特翻转。常见的有三种:无校验(N)、奇校验(O)、偶校验(E)。

校验位的计算范围是数据位(不包括起始位和停止位)。发送端根据数据位中1的个数,决定校验位是0还是1。

  • 无校验(N):不发送校验位,帧长度最短,效率最高。适合噪声小的环境。
  • 奇校验(O):数据位 + 校验位中1的总数为奇数。比如数据位有3个1,校验位就补0,使总数保持奇数。
  • 偶校验(E):数据位 + 校验位中1的总数为偶数。逻辑与奇校验相反。

我个人习惯在RS485总线这种长距离、易受干扰的场景下,强制使用偶校验。为什么是偶校验?因为很多MCU的UART外设默认支持偶校验,配置起来顺手。而且偶校验在检测单比特错误时,和奇校验效果一样好。

避坑指南:我曾经在一个项目中,发送端设了偶校验,接收端设了无校验。结果接收端把校验位当成数据位的一部分,每个字节都多了一个比特,数据全乱。用逻辑分析仪一看,帧长度对不上,才找到问题。记住:校验位配置必须两端一致。

2.5 停止位:帧的“句号”

停止位固定为高电平,长度可以是1、1.5或2个比特时间。它的作用是给接收端一个缓冲,让它有时间处理刚收到的字节,准备接收下一帧。

为什么会有1.5和2个比特的选项?

  • 1位停止位:最常用,效率最高。适合大多数场景。
  • 1.5位停止位:很少见,某些老式UART芯片用。我做了十几年嵌入式,只用过一次。
  • 2位停止位:给接收端更多处理时间。在低速MCU或高波特率场景下有用。比如用1MHz波特率时,MCU可能来不及处理中断,2位停止位能缓解压力。

你想想看,如果停止位太短,接收端还没处理完上一帧,下一帧的起始位就来了,就会发生帧错误(Framing Error)。逻辑分析仪上会显示“帧错误”标志,停止位采样为低电平。

2.6 常见帧格式组合

实际项目中,帧格式通常写成“数据位-校验位-停止位”的形式。比如8N1、8E1、8O2等。下面这个表,是我整理的常用组合:

格式 数据位 校验位 停止位 帧总长度(比特) 典型应用
8N1 8 无 1 10 最通用,调试首选
8E1 8 偶校验 1 11 RS485总线、工业通信
8O1 8 奇校验 1 11 某些PLC协议
7E1 7 偶校验 1 10 ASCII文本通信
8N2 8 无 2 11 低速MCU、高波特率

我的建议:如果你不确定对方的帧格式,先用逻辑分析仪抓一帧波形。数一下从起始位下降沿到停止位上升沿之间有多少个比特时间,再减去起始位和停止位,就能反推出数据位和校验位的长度。这是最直接的排查方法。

2.7 用逻辑分析仪验证帧格式

理论说完了,咱们看看实际怎么抓。假设你配置了8N1格式,波特率115200。用逻辑分析仪抓TX引脚,你会看到这样的波形:

  1. 空闲高电平 → 下降沿(起始位开始)
  2. 低电平持续1个比特时间(约8.68μs @115200)
  3. 8个数据位,LSB先发,每个比特也是8.68μs
  4. 高电平持续1个比特时间(停止位)
  5. 回到空闲高电平,等待下一帧

逻辑分析仪会自动解析这些电平,显示出十六进制数据。如果解析出来的数据和发送的不一致,先检查帧格式配置。我遇到过最坑的一次,是某国产MCU的UART外设,数据位顺序默认是MSB First,和标准UART相反。不看数据手册根本发现不了。

重要提醒:逻辑分析仪采样率至少要是波特率的4倍以上,推荐8倍。比如115200波特率,采样率至少要460.8kHz,最好用1MHz以上。采样率不够,可能漏掉起始位的下降沿,导致帧同步失败。

好了,UART帧格式的四个部分就讲到这里。起始位是发令枪,数据位是正文,校验位是防错码,停止位是句号。记住这个比喻,以后调通信心里就有底了。