You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

HAL_UART_Transmit_IT重复发送数据求助:PC经Arduino与STM32F407通信异常

解决STM32单次请求下HAL_UART_Transmit_IT重复发送480字节的问题

我帮你梳理下当前遇到的核心问题:PC发送一次'r'请求后,STM32会触发两次480字节的UART中断发送。结合你贴的代码,我分析了几个关键问题点,并给出具体的修复方案。

问题根源分析

从代码来看,主要有两个容易导致重复发送的隐患:

  1. EXTI中断触发模式与标志位清除遗漏
    你通过Arduino拉高GPIO触发STM32的EXTI11中断,但如果STM32的EXTI配置为电平触发(而非边沿触发),只要引脚保持高电平,中断会持续触发;另外你的中断处理函数里注释了"IRQ handling stuff",大概率遗漏了中断标志位的清除,导致中断被重复响应。

  2. 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

火山引擎 最新活动