You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32两路UART双向转发故障:HAL接收回调中数据未发至另一UART

两路UART双向透传回调方案问题分析

核心问题点

  • 回调函数选型错误
    你使用的HAL_UART_RxHalfCpltCallback是HAL库UART DMA接收模式下的半传输完成回调,如果没有提前启动UART DMA接收(调用HAL_UART_Receive_DMA()),该回调本身不会被触发;即使启用了DMA,回调触发时硬件的RXNE标志位已经被HAL库自动清除,你再读USARTx->RDR也无法拿到正确数据。
  • 发送逻辑完全错位
    1. 寄存器操作错误:UART的RDR寄存器是只读的接收缓冲寄存器,你代码中往USART1->RDR、USART2->RDR写待发送数据的操作完全无效,发送数据必须写入TDR发送缓冲寄存器。
    2. 逻辑判断完全错误:你要从UART1转发数据到UART2时,应该判断UART2的TXE(发送缓冲为空)标志位,而不是判断UART1的RXNE标志位;UART2转UART1的逻辑里甚至错误判断了UART1的RXNE位,逻辑完全不成立。
  • TXE中断没有对应处理逻辑
    你在接收数据后只打开了对应UART的TXE中断,但TXE中断触发后会进入UART全局中断服务函数,不会进入你写的HAL_UART_RxHalfCpltCallback,你写的发送逻辑永远不会被执行,当然不会有数据发出。

回调方案修正思路

如果要用中断回调实现,正确的逻辑如下:

  1. 初始化完成后调用HAL_UART_Receive_IT(&huart1, &byte, 1)、HAL_UART_Receive_IT(&huart2, &byte2, 1)启动单字节中断接收。
  2. 重写HAL_UART_RxCpltCallback回调函数,每次收到1字节后直接把数据发到另一路UART,再重新启动下一次单字节接收即可,示例逻辑:
volatile uint8_t byte = 0;
volatile uint8_t byte2 = 0;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart1) {
        // 把UART1收到的byte发到UART2
        HAL_UART_Transmit(&huart2, &byte, 1, HAL_MAX_DELAY);
        // 重新启动UART1下一次接收
        HAL_UART_Receive_IT(&huart1, &byte, 1);
    } else if(huart == &huart2) {
        // 把UART2收到的byte2发到UART1
        HAL_UART_Transmit(&huart1, &byte2, 1, HAL_MAX_DELAY);
        // 重新启动UART2下一次接收
        HAL_UART_Receive_IT(&huart2, &byte2, 1);
    }
}

内容的提问来源于stack exchange,提问作者User6996

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 04:42:00