跳转至

UART、串行成帧与错误边界

通用异步收发器(UART,Universal Asynchronous Receiver/Transmitter)把字节转换为按时间变化的电平。UART通常只负责字符边界,不知道上层消息的帧头、长度、校验或权限。

UART成帧与错误链

UART字符

常见8N1表示:

  • 1个起始位;
  • 8个数据位;
  • 无校验位;
  • 1个停止位。

一个8位字节因此占用10个线路位。若标称速率为115200比特每秒,忽略间隔时理论上限为:

115200 bit/s ÷ 10 bit/byte = 11520 byte/s

8E2则表示8个数据位、偶校验和2个停止位,每字节在线路上占12位。协议带宽预算必须使用真实字符格式。

波特率不是有效载荷率

线路时间还会消耗在:

  • UART起始、校验和停止位;
  • 协议帧头、长度、地址和校验;
  • 请求、响应和确认;
  • 半双工换向;
  • 设备处理间隔;
  • 重试;
  • 流量整形和空闲窗口。

配置为某个波特率,不代表应用载荷可以持续达到相同比特率。

电气接口不能由UART名称推断

“UART”不能说明:

  • 逻辑高电压;
  • 是否容忍5伏;
  • 是否反相;
  • 推挽还是开漏;
  • 单线还是双线;
  • 是否使用RS-232、RS-485或其他收发器;
  • 是否需要公共参考地;
  • 接口空闲电平。

微控制器的3.3伏逻辑UART不能直接连接传统RS-232电平。连接前必须同时核对两端原理图和规格。

发送与接收方向

普通全双工UART使用独立的发送端(TX,Transmit)和接收端(RX,Receive),并连接参考地(GND,Ground):

设备A TX → 设备B RX
设备A RX ← 设备B TX
设备A GND ─ 设备B GND

半双工或单线UART可能复用同一信号,要求:

  • 只有一端在给定时刻驱动;
  • 发送后在规定时间释放总线;
  • 接收端忽略或处理本机回显;
  • 引脚模式在输入、输出或开漏状态间正确切换。

推挽输出(Push-Pull Output)会主动驱动高、低电平;开漏输出(Open-Drain Output)只主动拉低,释放后由上拉电阻形成高电平。把半双工设备按普通推挽全双工方式连接,或者直接连接两个推挽输出,可能形成总线争用。

极性与反相

常规TTL风格UART空闲通常为高电平,起始位拉低。部分遥控协议采用反相信号,空闲和位电平含义相反。

“软件支持反相”还要确认:

  • 处理器UART是否具有硬件反相;
  • 板级是否使用外部反相器;
  • 当前焊盘经过哪条电路;
  • 发送和接收是否分别可反相;
  • 半双工时引脚模式是否仍正确。

不能只根据配置界面的“Inverted”选项判断任意焊盘都支持。

UART错误

硬件常见错误包括:

错误 含义 常见原因
帧错误 预期停止位位置没有有效停止位 速率、字符格式、极性或噪声错误
奇偶校验错误 校验位不符合配置 一端配置不一致或传输错误
溢出 新字符到达时旧字符未及时取走 中断延迟、缓冲不足或输入过载
噪声错误 硬件检测到采样异常 电气干扰、边沿或地参考问题
断路状态 线路持续处于有效低电平 短路、反相或发送端异常

UART硬件没有报告错误,不代表上层帧校验一定通过;帧校验通过也不代表消息语义安全。

上层成帧

常见方法:

固定长度

接收固定数量字节后交付一帧。实现简单,但一个字节丢失后可能长期错位,需要额外同步标记或超时。

起始标记加长度

解析器先寻找帧头,再读取长度。需要处理:

  • 帧头出现在载荷中;
  • 长度被破坏;
  • 超长声明;
  • 帧在中途停止;
  • 连续帧无间隔;
  • 从任意位置重新同步。

分隔符与转义

特殊字节标记帧尾,载荷中的同值字节需要转义。解析器必须定义非法转义和截断转义的处理。

空闲间隔

以超过阈值的静默作为边界。调度抖动、USB转串口缓冲和不同发送实现都可能改变间隔,不适合在没有明确时序保证时作为唯一边界。

增量解析器

串口读取不会保证“一次读取正好一帧”。可能得到:

  • 半个帧头;
  • 一帧的一部分;
  • 多帧拼接;
  • 前一帧尾部加后一帧头部;
  • 任意噪声字节。

解析器应把输入视为连续字节流:

寻找同步
→ 收集固定头
→ 验证长度
→ 等待完整帧
→ 校验
→ 分派消息
→ 回到寻找同步

每个状态都要有最大等待字节数或超时。发生错误时,应明确丢弃一个字节、整个候选帧还是直到下一个同步标记,避免无限循环。

环形缓冲与并发

中断或直接存储器访问(DMA,Direct Memory Access)负责收字节时,上层解析器通常读取环形缓冲。必须定义:

  • 生产者和消费者索引的原子性;
  • 缓冲满时丢弃新数据还是旧数据;
  • DMA回绕和空闲中断边界;
  • 缓存一致性;
  • 溢出计数;
  • 解析预算。

溢出后继续从原位置解析,可能把载荷字节误认成帧头。实现应进入明确的重新同步状态。

校验范围

协议文档应使用类似以下表述:

CRC输入:从Type字段第一个字节开始,到Payload最后一个字节结束
不包含:Sync、Length和接收的CRC字节
初值:0
多项式:0xD5
输出:8位

只写“使用CRC8”不够。CRC结果还取决于多项式、初值、输入/输出反射、异或输出和覆盖范围。

简单异或校验或字节求和可以发现部分错误,但检测能力弱于设计良好的CRC。无论哪一种都不提供恶意篡改防护。

超时

至少区分:

  • 字符间超时:候选帧在中途停止;
  • 请求超时:没有收到对应响应;
  • 数据新鲜度超时:曾经有效的数据已经过期;
  • 链路超时:长期没有任何有效帧;
  • 会话超时:协商或事务未完成。

一个统一的“串口超时”不能正确驱动全部状态。

自动波特率

自动探测需要明确:

  • 候选速率集合;
  • 是否会主动发送探测帧;
  • 每个速率停留时间;
  • 用什么证据确认;
  • 误识别后怎样恢复;
  • 是否保存结果;
  • 重启后是否重新探测。

偶然出现一个校验正确的短帧不足以确认长期速率。应观察多个合法帧、合理消息类型和连续时序。

捕获与测量

逻辑分析仪至少配置:

  • 正确电压容限;
  • 公共参考地;
  • 采样率明显高于最高边沿速率;
  • 正确极性;
  • 正确字符格式;
  • 足够长的捕获窗口;
  • 原始电平和原始字节同时保留。

只保存解码后的文本会丢失帧错误、脉宽和重同步证据。探头电容和长地线也可能改变高速信号。

最小测试集

正常

  • 单帧;
  • 连续多帧;
  • 最小和最大合法载荷;
  • 双向同时达到设计负载;
  • 重启后第一帧和稳态帧。

边界

  • 帧头分跨两次读取;
  • 每个可能字节位置截断;
  • 长度小于最小值;
  • 长度大于最大值;
  • 校验错误;
  • 未知消息;
  • 载荷中包含帧头;
  • 多个噪声字节后恢复;
  • 环形缓冲临界回绕。

资源

  • 最大持续合法流量;
  • 短时突发;
  • 慢速逐字节输入;
  • 长时间随机数据;
  • 错误日志限速;
  • 缓冲溢出后恢复。

主动发送异常帧只允许在隔离软件环境或拆桨且执行器动力级断开的专用台架。

检查理解

  1. 8N1传送一个8位字节为什么需要10个线路位?
  2. 为什么UART名称不能说明电压和极性?
  3. 一次系统调用读取的数据为什么不一定是一帧?
  4. 只写“CRC8”为什么不足以实现兼容校验?
  5. 溢出后解析器为什么需要重新同步?

主要参考