【嵌入式软件】STM32 UART转485通信问题

1.背景

在原来的文章中,已经测试了RS485的电路

【嵌入式】RS485通信+硬件

经过多次测试,没有问题。

但是在通信的过程中,偶尔会发生错误。

2.问题集合

2.1通信错位问题

2.1.1 问题描述

最近某台设备采用的MODBUS协议,返回的数据格式应该是

复制代码
1 3 4 ef 8e 0 f ee ac

但是实际收到的数据是:

复制代码
ee 1 3 4 ef 8e 0 f ee

上面的数据出现了数据错位

2.1.2 解决方法

1)首先要保证uart的rx引脚配置为上拉,不要外接下拉电阻;因为uart的通信起始位 是低电平开始,可能会导致数据判断错误;

2)rs485为半双工通信,在数据发送结束后,需要等待一段时间后再去接收数据;

这是因为,虽然uart已经发送完成了,但是485驱动器还需要切换电平,硬件缓冲区可能已清空,但驱动器可能还需要一点时间将最后一个位完全驱动到总线上。立即切换可能导致最后一个位被截断。这个延迟通常需要至少 1 个字符的传输时间(例如,对于 115200bps,1 个字符 10 位:10 / 115200 ≈ 87us)。更保守的做法是等待 2-3 个字符时间。可以使用简单的 for循环延时或定时器实现。

3)程序处理框架

复制代码
HAL_StatusTypeDef RS485_SendData(uint8_t *pData, uint16_t Size, uint32_t Timeout) {
    HAL_StatusTypeDef status;

    RS485_DIR_TX(); // 切换到发送模式

    status = HAL_UART_Transmit(&huart1, pData, Size, Timeout); // 阻塞发送

    if (status == HAL_OK) {
        // 等待发送寄存器真正空 (TC 标志)
        while (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET) {}

        // 关键延迟:等待最后一个位完全发出 (至少 1 个字符时间)
        // 这里使用简单的循环延时,实际应用中建议使用定时器或计算精确时间
        volatile uint32_t delay = SystemCoreClock / 1000000 * 100; // 大约 100us 延时 (根据你的波特率调整!)
        while (delay--);
    }

    RS485_DIR_RX(); // 切换回接收模式 (无论发送成功与否)

    return status;
}

// 接收数据函数 (与普通 UART 接收一样)
HAL_StatusTypeDef RS485_ReceiveData(uint8_t *pData, uint16_t Size, uint32_t Timeout) {
    return HAL_UART_Receive(&huart1, pData, Size, Timeout);
}

2.1.3 要点

1)切换时机是核心:​​ 过早切换回接收模式会截断自己发送的数据;过晚切换会错过总线上的响应或增加总线冲突风险。​发送完成后的延迟至关重要。

2)延迟计算:​​ 延迟时间需要根据你的波特率计算。例如

(1)波特率 9600bps:1 位时间 ≈ 104us,1 个字符 (10 位:1 起始 + 8 数据 + 1 停止) ≈ 1.04ms。延迟建议 > 1.04ms。

(2)波特率 115200bps:1 位时间 ≈ 8.68us,1 个字符 ≈ 86.8us。延迟建议 > 87us。

(3)使用 HAL_Delay()进行毫秒级延迟通常足够,但对于高波特率,需要更精确的微秒级延迟(如定时器或 DWT计数器)。

相关推荐
2401_853448231 小时前
ESP8266蓝牙模块
stm32·蓝牙模块·esp8266
许商2 小时前
【stm32】【printf】
java·前端·stm32
LaoZhangGong1233 小时前
以太网HTTP数据包格式分析
c语言·stm32·网络协议·http·tcp·arp
云山工作室3 小时前
用于电动汽车的永磁同步电机调速系统建模与仿真(论文+)
stm32·单片机·嵌入式硬件·毕业设计·毕设
yuan199974 小时前
AD7689 12位串行ADC驱动与应用
单片机·嵌入式硬件
磨十三4 小时前
MCU 时钟系统全解析:主时钟、PLL、分频与外设时钟门控
arm开发·单片机·嵌入式硬件
逐步前行5 小时前
Proteus 8.9(四)51单片机仿真
嵌入式硬件·51单片机·proteus
DIY机器人工房5 小时前
嵌入式面试题:纹波率怎么计算;Buck 电路电感值的标准计算式是什么?
stm32·嵌入式硬件·面试题·diy机器人工房
DIY机器人工房5 小时前
嵌入式面试题:电容滤波,低频高频谁来滤?放置顺序怎么定?
stm32·单片机·嵌入式硬件·diy机器人工房
学习路上_write5 小时前
嵌入式系统bringup指南:软硬件调试
c语言·单片机·嵌入式硬件