STM32两路UART双向转发故障:HAL接收回调中数据未发至另一UART
两路UART双向透传回调方案问题分析
核心问题点
- 回调函数选型错误
你使用的HAL_UART_RxHalfCpltCallback是HAL库UART DMA接收模式下的半传输完成回调,如果没有提前启动UART DMA接收(调用HAL_UART_Receive_DMA()),该回调本身不会被触发;即使启用了DMA,回调触发时硬件的RXNE标志位已经被HAL库自动清除,你再读USARTx->RDR也无法拿到正确数据。 - 发送逻辑完全错位
- 寄存器操作错误:UART的
RDR寄存器是只读的接收缓冲寄存器,你代码中往USART1->RDR、USART2->RDR写待发送数据的操作完全无效,发送数据必须写入TDR发送缓冲寄存器。 - 逻辑判断完全错误:你要从UART1转发数据到UART2时,应该判断UART2的TXE(发送缓冲为空)标志位,而不是判断UART1的RXNE标志位;UART2转UART1的逻辑里甚至错误判断了UART1的RXNE位,逻辑完全不成立。
- 寄存器操作错误:UART的
- TXE中断没有对应处理逻辑
你在接收数据后只打开了对应UART的TXE中断,但TXE中断触发后会进入UART全局中断服务函数,不会进入你写的HAL_UART_RxHalfCpltCallback,你写的发送逻辑永远不会被执行,当然不会有数据发出。
回调方案修正思路
如果要用中断回调实现,正确的逻辑如下:
- 初始化完成后调用
HAL_UART_Receive_IT(&huart1, &byte, 1)、HAL_UART_Receive_IT(&huart2, &byte2, 1)启动单字节中断接收。 - 重写
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
相关产品推荐
相关产品推荐

