基于边沿采样的 RS485 帧格式自识别解码方法

概述
本方法用于将 RS485 总线电平翻转边沿的时间序列还原为原始字节流,在RS485多主多从总线仲裁的基础上实现波特率自适应、帧格式自识别的无侵入总线数据监测。
效果演示:

硬件基础
边沿捕获
解码的数据来源是定时器捕获的连续边沿时间戳。当 RS485 总线上发生电平翻转(上升沿/下降沿)时,触发定时器中断,记录当前计数值存入环形缓冲区。
边沿跳变: ‾‾\__/‾‾\__/‾‾\__/‾‾‾‾‾‾‾‾‾‾‾\__/‾‾ |
每个字节至少产生一个起始位下降沿,加上数据位内部的翻转,一个字节通常产生多个边沿。
最小位宽
采样过程中会对边沿间隔做最小簇均值滤波:
- 记录每个边沿与上一个边沿的时间差,记作脉宽
Wₑ。 - 首个脉宽误差较大,直接丢弃。
- 若
Wₑ < Wᵦ * (0.5 + 0.1):发现更小的边沿间隔,重置位宽加权平均值Wᵦ。 - 若
Wₑ < Wᵦ * (1.0 + 0.1):视作等宽的边沿间隔,纳入位宽加权平均值Wᵦ。
这样得到一个零样本的先验位宽均值 Wᵦ,单位为定时器时钟周期数。
若前 X 个字节是以 81O 发送的连续 0xF0 或者以 81E 发送的连续 0xE0 或其他类似的情况,在位宽推测期间得到的最小脉宽与实际位宽不符,则无法正确解码。
8/1/O |
解码流程
完整解码经过以下几个阶段:
波特率匹配
建立一张常用波特率表:
| 波特率 | 理论位宽 |
|---|---|
| 300 | 3333 |
| 600 | 1667 |
| 1200 | 833 |
| 2400 | 417 |
| 4800 | 208 |
| 9600 | 104 |
| 19200 | 52 |
| 38400 | 26 |
| 57600 | 17 |
| 115200 | 9 |
理论位宽 = Round(定时器频率(1MHz) / 波特率)
将实测的位宽以 ±1% 容错率与上表匹配,匹配成功则用理论位宽替换实测值,失败则用实测值继续。这样既能适应非标准波特率,又能规整常见波特率的位宽,提升后续解码准确率。
时间戳对齐
输入:原始边沿时间序列
输出:规整边沿时间序列
目的:将受硬件噪声、布线延迟等影响的原始时间戳”对齐”到理想位宽的整数倍位置上。
为什么要对齐?
下图中橙色折线是采样边沿,蓝色折线是理论边沿。看似误差不大,但随着时间积累,误差线性递增,会导致后续的位宽步进扫过时无法正确判断边沿位置,最终导致比特流重建失败。

虽然边沿误差会越来越大,但是脉宽误差却是比较稳定的,通过规整脉宽将采样边沿对齐到最近的位宽整数倍位置,可以大幅提高解码准确率。

比特流重建
输入:理想边沿时间序列
输出:二进制比特流数组
目的:按理想位宽步进扫过时间轴,在每个理想位宽位置判断是否有真实边沿落在容差范围内。有边沿则翻转比特值,无边沿则保持。目的是补全缺失的边沿位置(如连续多个相同电平位),确保时间轴是均匀的位宽步进。

0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 1 0 1 1 |
帧格式识别
从重建的比特流中自动推断 UART 帧格式(数据位数、是否有校验位、校验位类型),为后续比特流还原成字节提供依据。
[起始位(0)] [数据位(5/6/7/8/9)] [校验位(N/O/E)] [停止位(1/2/1.5)] |
候选格式
由于数据位和停止位自动识别的成功率不高且应用较少,目前只考虑 8 数据位和 1 停止位的情况。
| 候选 | 数据位 | 校验位 | 帧长度 | 帧布局 |
|---|---|---|---|---|
| 81N | 8 | 0 | 10 | S(0) | D0‥D7 | S(1) |
| 81P | 8 | 1 | 11 | S(0) | D0‥D7 | P | S(1) |
评分体系
第一轮评分不区分奇/偶,只判断校验位是否存在。第二轮再用奇/偶校验公式推测校验类型。
分值 = 起始位匹配帧数 × 10 + 停止位匹配帧数 × 2 + 校验位规律帧数 × (6 or 1 or 0) |
| 项目 | 权重 | 检查条件 |
|---|---|---|
| 起始位=0帧数 | ×2 | 每帧必查 |
| 停止位=1帧数 | ×10 | 每帧必查 |
| 校验位有规律 | +6 | 有校验位且停止位有效 |
| 校验位无规律 | +1 | 有校验位且停止位有效 |
取样帧数:平衡样本量与计算量,最多检查前 8 帧。
| 真实格式 | 81N 得分 | 81P 得分 |
|---|---|---|
| 81N | = N × 12 | ≈ N × 05 |
| 81P | ≈ N × 05 | = N × 18 |
只要 N ≥ 1,错误候选的分差远大于正确候选,格式识别非常可靠。
字节流提取
按照上面识别出来的帧格式,逐帧校验:
- 起始位必须为 0
- 停止位必须为 1
通过校验后,提取数据位,组装为字节值:
M1: (115200/8/1/E) (9±1) 20: |