【嵌入式软件】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计数器)。

相关推荐
Deitymoon1 小时前
STM32——串口中断接收
stm32·单片机·嵌入式硬件
charlie1145141913 小时前
嵌入式C++实践开发第21篇(单片机实践):按钮输入 —— 硬件原理、消抖与HAL API
开发语言·c++·单片机
一起搞IT吧3 小时前
Android性能系列专题理论之十一:block IO问题分析思路
android·嵌入式硬件·智能手机·性能优化
余生皆假期-3 小时前
YuanHub 源码分析【一】FlashDB 初始化与项目应用
笔记·单片机·嵌入式硬件
Deitymoon3 小时前
STM32——串口通信发送数据
stm32·单片机·嵌入式硬件
玩转单片机与嵌入式3 小时前
嵌入式AI场景:哪些应用场景不适合将AI模型部署到单片机(MCU)中?
人工智能·单片机·嵌入式硬件
czwxkn4 小时前
8STM32(stdl)低功耗模式
stm32·单片机·嵌入式硬件
czwxkn4 小时前
9STM32(stdl)看门狗
stm32·单片机·嵌入式硬件
coward915 小时前
Linux 内核 KGDB 以及内核驱动单串口调试笔记:telnet + agent-proxy + gdb-multiarch 实践
linux·单片机·嵌入式硬件
刻BITTER5 小时前
VirtualBox 安装Armbian x86 虚拟机
linux·嵌入式硬件