HAL_UART_Transmit_IT重复发送数据求助:PC经Arduino与STM32F407通信异常
解决STM32单次请求下HAL_UART_Transmit_IT重复发送480字节的问题
我帮你梳理下当前遇到的核心问题:PC发送一次'r'请求后,STM32会触发两次480字节的UART中断发送。结合你贴的代码,我分析了几个关键问题点,并给出具体的修复方案。
问题根源分析
从代码来看,主要有两个容易导致重复发送的隐患:
EXTI中断触发模式与标志位清除遗漏
你通过Arduino拉高GPIO触发STM32的EXTI11中断,但如果STM32的EXTI配置为电平触发(而非边沿触发),只要引脚保持高电平,中断会持续触发;另外你的中断处理函数里注释了"IRQ handling stuff",大概率遗漏了中断标志位的清除,导致中断被重复响应。Arduino端触发信号持续时间过长
Arduino触发STM32后没有及时拉低GPIO,持续的高电平会让STM32的EXTI不断检测到触发条件,进而重复置位should_send_data标志。
具体修复步骤
1. 修正STM32的EXTI中断配置与处理
首先在STM32CubeMX里把EXTI11配置为上升沿触发(仅在引脚从低到高跳变时触发一次中断),然后完善中断处理函数:
void EXTI15_10_IRQHandler(void) { // 确认是目标引脚的中断请求 if (__HAL_GPIO_EXTI_GET_IT(data_req_IRQ_Pin) != RESET) { // 仅在未发送数据时置位发送标志 if (is_sending_data == FALSE) { should_send_data = TRUE; } // 必须清除EXTI中断标志,否则会重复进入中断 __HAL_GPIO_EXTI_CLEAR_IT(data_req_IRQ_Pin); } // 调用HAL库的EXTI通用处理函数(CubeMX生成的标准流程) HAL_GPIO_EXTI_IRQHandler(data_req_IRQ_Pin); }
2. 优化Arduino端的触发信号逻辑
把持续高电平改成短脉冲,确保只触发一次STM32的EXTI中断:
if (Serial.available()) { char cmd = Serial.read(); if (cmd == 'r') { // PC请求STM32数据 // 发送10微秒的高电平脉冲,触发STM32上升沿中断 digitalWrite(4, HIGH); delayMicroseconds(10); digitalWrite(4, LOW); // 清空串口缓存,避免残留字符干扰后续请求 while (Serial.available()) Serial.read(); } }
3. 加固STM32主循环的发送判断
在主循环里合并条件判断,避免发送过程中被重复触发:
while (1) { // 仅在需要发送且未在发送状态时执行 if (should_send_data == TRUE && is_sending_data == FALSE) { HAL_GPIO_WritePin(LD5_GPIO_Port, LD5_Pin, GPIO_PIN_RESET); HAL_UART_Transmit_IT(&huart3, matrice, 480); is_sending_data = TRUE; should_send_data = FALSE; } // matrice采集逻辑... }
额外调试建议
- 可以在STM32的EXTI中断函数和
HAL_UART_TxCpltCallback里添加LED闪烁(比如翻转LD5),直观判断中断触发次数和发送完成次数; - 用串口助手监控Arduino发给PC的数据,确认是STM32重复发送,还是Arduino端
Serial.println(buff)的缓存或格式问题导致的重复显示。
内容的提问来源于stack exchange,提问作者Samuel Martel




