使用 ADC 采样实现 RS485 数据接收与协议显示

一、项目背景

常规 RS485 通信中,单片机一般通过 RS485 收发器接另外一个与单片机相连接RS485模块,再通过连接硬件UART 接收数据。相当于RS485只负责远距离传输,本质还是通过uart解析,发送和接收数据。

常规的通信链路通常如下:

复制代码
单片机 UART → RS485 收发器 → A/B 总线 → RS485 收发器 → UART

本次实验没有使用收发器上述方式,而是从 USB 转 RS485 模块的 A、B 接口获取 RS485 差分总线信号。

我将 A、B 总线信号送入单片机 ADC 进行采样,并在软件中对采样结果进行电平判决、起始位识别和 UART 时序解析,最终还原出串口协议数据,再通过单片机 UART 输出到串口调试助手显示。

因此,本实验采集的是 RS485 总线侧的 A/B 信号,而不是 TTL/UART 侧的 RX 信号。

难点:波特率速率,协议解析和组合,uart串口的特性,电平判决,起始位和结束位的判断

而这次的流程如下:

复制代码
串口调试助手
    ↓
USB 转 RS485
    ↓
RS485 A/B 总线
    ↓
单片机 ADC 采样
    ↓
软件解析 UART 数据帧
    ↓
单片机 UART
    ↓
USB 转 TTL
    ↓
串口调试助手显示

二、目标

本实验的目标包括:

  1. 使用 ADC 采集 RS485 A、B 总线信号;

  2. 根据 ADC 采样结果进行逻辑电平判决;

  3. 检测 UART 起始位;

  4. 按 UART 时序依次采集数据位;

  5. 判断停止位,完成单字节接收;

  6. 将接收到的字节组合成协议帧;

  7. 通过 UART 输出协议内容,并在串口调试助手中以十六进制格式显示。

三、实现原理

RS485 使用 A、B 两根线进行差分传输。总线上的差分电压会随 UART 数据位变化而变化。

本实验通过 ADC 对 A、B 信号进行采样,并根据采样值判断当前总线状态。软件检测到起始位后,按照 UART 的位时间,在每一位的中心位置进行采样,从而依次恢复数据位。

以常见的 UART 8N1 格式为例,一帧数据包括:

复制代码
1 位起始位 + 8 位数据位 + 1 位停止位

其中:

  • 空闲状态通常为逻辑 1;

  • 起始位为逻辑 0;

  • 数据位低位先发送;

  • 停止位为逻辑 1。

软件解码过程如下:

复制代码
检测到起始位,循环判断否则读取和延迟差一点就去的数据就会差很大
    ↓
延时 0.5 个 bit 时间
    ↓
判断是否真的为起始位
    ↓
采集第 0 位数据
    ↓
每隔 1 个 bit 时间采集下一位
    ↓
连续采集 8 位数据
    ↓
判断停止位,循环判断否则读取和延迟差一点就去的数据就会差很大
    ↓
得到一个完整字节

四、关键难点

1. 波特率与 ADC 采样速率

本实验中最关键的问题是采样速率。

UART 的每一位都有固定持续时间。以 9600 bps 为例:

目前最高速率为14400,可以准确的完成目标,波特率过大,对实时性要求很高

复制代码
1 bit 时间 = 1 / 9600 ≈ 104 us

若 ADC 采样速度过慢,可能无法捕获起始位,也无法在数据位中心位置完成有效采样,最终会出现乱码、丢字节或帧错误。

为了保证解析效果,ADC 的有效采样率应明显高于 UART 波特率。实际测试中,可根据波特率、单片机性能和 ADC 转换时间调整采样频率。

波特率越高,单个 bit 的时间越短,对 ADC 速度、定时精度和程序响应速度的要求也越高。

2. 电平判决

ADC 采集到的是电压值,而 UART 解码需要的是逻辑 0 和逻辑 1,因此需要将模拟采样值转换为数字逻辑状态。

若分别采集 A、B 信号,可根据两者的电压关系或差分结果进行判决。为了避免噪声造成误判,建议设置高、低两个阈值,形成滞回判断。

复制代码
if (adc_value > THRESHOLD_HIGH)
{
    logic_level = 1;
}
else if (adc_value < THRESHOLD_LOW)
{
    logic_level = 0;
}
else
{
    logic_level = last_logic_level;
}

这种方式可以减少信号处于阈值附近时反复跳变的问题。

3. 起始位判断

UART 数据帧以起始位开始。软件需要先检测总线从空闲状态切换到起始位的过程。

如果起始位检测不准确,后续数据位采样时刻都会发生偏移,导致整帧数据解析错误。因此,检测到起始位后,不能立即作为第 0 位数据进行采样,而是等待电平从空闲位到起始位,再等待约 0.5 个 bit 时间检验是否真的为起始位后,再采样第一个数据位

4. 数据位采样与时序控制

UART 数据按照低位在前的顺序发送,即 bit0、bit1、bit2......bit7。

软件在检测到起始位后,以一个 bit 时间为间隔依次采集 8 次,并组合成一个字节。

复制代码
uint8_t SoftUart_ReadByte(void)
{
    uint8_t data = 0;
    uint8_t i;

    // 已检测到起始位,等待至第 0 位数据中心
    Delay_1_5Bit();

    for (i = 0; i < 8; i++)
    {
        if (Read_AdcLogicLevel() == 1)
        {
            data |= (1 << i);
        }

        Delay_1Bit();
    }

    return data;
}

实际工程中,建议使用定时器中断、ADC 定时触发或 DMA 等方式提高时序稳定性,避免单纯使用软件延时导致误差累积。

5. 停止位判断

读取完 8 位数据后,还需要判断停止位。

停止位正常应保持为逻辑 0。若停止位判断失败,则说明当前帧可能存在干扰、采样时序偏差或通信参数不一致等问题,可将该字节标记为帧错误并丢弃。

复制代码
while(1)
{
    int ret = ADC_Read();
    if(ret == 0)
    {
        break;
    }
}

6. 协议数据的组合

完成单字节接收后,还需要根据具体协议进行数据组合。

例如,若通信协议采用固定帧头、固定长度或 CRC 校验,可将接收字节依次存入缓存区,再根据协议规则判断一帧数据是否完整。

复制代码
rx_buffer[rx_index++] = rx_byte;

if (rx_index >= expected_length)
{
    // 判断帧头、长度、校验等
    Protocol_Parse(rx_buffer, rx_index);
    rx_index = 0;
}

在串口调试助手中,建议以十六进制方式显示数据,便于与发送端协议逐字节对比。

六、方案特点

本方案的优点:

  • 不依赖 RS485 收发器的 RO 引脚进行数据接收;

  • 直接观察和采集 RS485 A/B 总线侧信号;

  • 可以学习 ADC 高速采样、UART 时序和协议解析;

  • 适用于低波特率实验、通信信号分析及特殊场景验证;

  • 可在解析数据的同时扩展总线状态监测功能。

本方案的局限性:

  • 对 ADC 采样速率和定时精度要求较高;

  • 波特率提高后,软件解析难度会明显增加;

  • 总线噪声、阈值选择和采样偏差都可能造成误码;

  • 相比硬件 UART 接收,CPU 占用更高、稳定性更依赖软件;

  • A/B 总线接入 ADC 前应做好限流、分压或钳位保护,避免异常电压损坏 ADC 引脚。

七、总结

本实验通过直接采集 USB 转 RS485 模块 A、B 接口的总线信号,利用单片机 ADC 完成电平采样,并在软件中实现 UART 起始位检测、数据位读取、停止位判断和协议组合。

最终,单片机能够将解析出的协议数据通过 UART 输出到串口调试助手,并以与发送端一致的格式显示。

该实验说明:在采样率和时序精度满足要求的前提下,ADC 不仅可以采集模拟量,也能够用于低速 RS485 通信信号的采集和软件解析。虽然实际产品通常仍优先采用 RS485 收发器配合硬件 UART 的方案,但 ADC 软解码方式对于学习通信原理、分析总线波形和验证协议解析流程具有一定参考价值。

补充:

方法一:利用AB进行ADC转换后的数据进行差值,根据差值判断逻辑0和1

局限,分压电阻不够时,电压大于3300mv,差值为0,导致数据不准确

方法二:利用单口判断逻辑1或逻辑0,当为逻辑1时差值比较的,A口的电压值就比较高,相反A口的逻辑值就比较小,这样的方法比较准确和快速

缺点:需要中间值来判断电平状态

必须通过协议解析提取数据,因为uarttx发送完数据后回回到默认电平状态,一般是高电平,所以在空闲时间回出现大量的逻辑1

相关推荐
WWJA王文举10 小时前
RS485通信超时全面排查:终端电阻、A/B线、DE方向控制、串口参数和Modbus一次讲透
stm32·通信协议·rs485
Industio_触觉智能23 天前
RK3576开发板UART驱动实战教程(下),基于触觉智能开发板演示
嵌入式硬件·硬件架构·串口·uart·智能硬件·rs232·rs485
Cry丶2 个月前
NB-IoT 表计协议开发复盘:如何建立从 HEX 报文到业务闭环的验证链路
物联网·mqtt·协议解析·nb-iot·hex报文·嵌入式联调·工程复盘
Strugglingler3 个月前
【Linux PL011驱动支持RS485】
linux·uart·rs485·pl011
小懒懒️3 个月前
嵌入式常见通信协议——RS232,RS485
uart·rs232·rs485
奔跑吧 android4 个月前
【BT-SIG】【Core_v6.2】【Vol 3 Host】【Part G: GATT】【2.Profile overview】
ble·bluetooth·协议解析·gatt·bt-sig解析·core_v6.2
疆鸿智能研发小助手4 个月前
PROFIBUS转RS485赋能触摸屏,制药产线合规零死角
工业自动化·rs485·工业通讯·协议转换网关·profibus·hmi触摸屏
深念Y4 个月前
蓝牙功放板改AUX输出,从差分信号到高转低的探索
蓝牙·电子·变压器·diy·魔改·aux·差分信号
天涯铭5 个月前
深入浅出:RS485偏置电阻设计
rs485