STM32同一HAL_UART_RxCpltCallback获取多UART数据及中断异常问题
故障原因排查
- 核心逻辑错误:回调函数的入参
huart是本次触发接收完成中断的串口句柄,你现有代码的判断条件写死了huart2.Instance == USART2,该判断结果永远为真,不管是UART2还是UART3触发的回调,都会进入UART2的处理分支,永远不会执行UART3的分支逻辑。 - 直接后果:UART3第一次触发中断进入回调后,没有重新调用
HAL_UART_Receive_IT()开启下一次接收中断,因此后续UART3有数据到来也不会触发中断。 - 潜在隐患:需要确认两个串口的接收缓存为各自独立的变量,避免不同串口的数据互相覆盖。
正确实现方案
修改回调函数的判断条件,将入参huart的Instance成员和对应的串口外设基地址比较即可:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART2) // 判断传入句柄对应的外设为UART2 { gsm.RxData[gsm.RxDataCnt] = Uart_Rx_Buffer; gsm.RxDataCnt = (1 + gsm.RxDataCnt) % MAX_Buff_Size; HAL_UART_Receive_IT(&huart2, &Uart_Rx_Buffer, 1); } else if(huart->Instance == USART3) // 判断传入句柄对应的外设为UART3 { lidar.RxData[lidar.RxDataCnt] = uart3_RX_Data; lidar.RxDataCnt = (1 + lidar.RxDataCnt) % MAX_LIDAR_BUFFER; HAL_UART_Receive_IT(&huart3, &uart3_RX_Data, 1); if(lidar.RxDataCnt > MAX_COUNT_BUFFER) { lidar.received = true; } } }
额外注意事项
- 初始化阶段要分别对UART2、UART3调用一次
HAL_UART_Receive_IT()开启首次接收中断,回调才会被正常触发。 - 确保
Uart_Rx_Buffer和uart3_RX_Data是两个独立的变量,不要共用同一块内存。 - 如果有更高优先级的中断长时间占用CPU,可能会导致UART接收溢出,可根据实际需求添加溢出错误回调处理逻辑。
内容的提问来源于stack exchange,提问作者Pankaj Verma
相关产品推荐
相关产品推荐

