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

STM32G491CET6 ADC中断与HAL_Delay运行死循环问题咨询

STM32G491CET6 ADC中断、HAL_Delay死循环故障排查

故障现象

  • 配置ADC中断触发采样时,程序陷入无限死循环
  • 调用HAL_Delay()函数时,程序同样触发死循环
  • 同逻辑代码在STM32F103平台可正常运行,当前工程TIM1 PWM输出功能正常

核心复现代码如下:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */

   HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

  if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
   {
     /* Configuration Error */
     Error_Handler();
   }
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
       HAL_ADC_Start_IT (&hadc1);
       HAL_Delay(100);
  }
  /* USER CODE END 3 */
}


void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
  HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
}

故障根因

两类死循环故障本质是STM32G4系列与F1系列的HAL库、NVIC规则差异导致的,PWM功能不受影响是因为TIM1 PWM输出由硬件自动完成,不需要CPU或中断参与。

1. SysTick中断被阻塞,HAL_Delay()死锁

HAL_Delay()的实现逻辑是轮询全局变量uwTick直到计数值达到目标延时,这个变量只能在SysTick中断服务函数中递增:

  • STM32F1默认NVIC优先级分组为2位抢占优先级、2位子优先级,HAL库默认配置的SysTick优先级可正常响应
  • STM32G4如果未手动配置优先级分组,或者将ADC等外设中断的抢占优先级设置为高于/等于SysTick优先级,当ADC中断持续触发时,SysTick中断无法抢占执行,uwTick无法递增,HAL_Delay()会永远卡在轮询逻辑中。

2. ADC中断链路缺失,CPU反复进入中断死循环

从F1移植代码到G4时很容易遗漏中断服务函数对接:

  • 如果工程中没有实现ADC1_2_IRQHandler()中断服务函数,或者函数内没有调用HAL_ADC_IRQHandler(&hadc1),ADC转换完成的中断标志位永远不会被清除
  • 中断标志未清除时,CPU退出中断后会立刻再次进入ADC中断服务,永远无法回到主循环执行后续逻辑,表现为死循环。

3. ADC启动逻辑存在隐患

当前代码在while循环中无判断重复调用HAL_ADC_Start_IT(),如果上一次ADC转换未完成就重复调用启动接口,会导致HAL库ADC状态机异常,触发错误处理死循环。

解决方法

  • 配置正确的NVIC优先级分组,保证SysTick中断可响应
    在HAL_Init()调用之后、系统时钟配置之前,添加优先级配置代码,对齐F1系列常用的优先级逻辑,确保SysTick不会被外设中断阻塞:

    HAL_Init();
    /* 设置4位抢占优先级、0位子优先级 */
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
    /* 配置SysTick为1ms中断,抢占优先级设为最高级0 */
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
    

    ADC1中断的抢占优先级设置为1及以下即可,不要高于SysTick的0级。

  • 补全ADC中断服务链路
    打开工程的stm32g4xx_it.c文件,确认存在ADC1/2中断服务函数,且内部正确调用HAL库中断处理入口:

    void ADC1_2_IRQHandler(void)
    {
      HAL_ADC_IRQHandler(&hadc1);
    }
    

    同时确认ADC初始化函数中已经开启ADC全局中断、配置了对应NVIC通道(CubeMX中勾选ADC全局中断会自动生成该段代码):

    HAL_NVIC_SetPriority(ADC1_2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);
    
  • 优化ADC启动逻辑
    增加采样完成标志位,避免重复调用ADC启动接口导致状态机异常:

    /* 主循环前定义标志位 */
    uint8_t adc_conv_flag = 0;
    
    while (1)
    {
      if(adc_conv_flag)
      {
        adc_conv_flag = 0;
        HAL_Delay(100);
        HAL_ADC_Start_IT(&hadc1);
      }
    }
    
    /* 回调函数中增加实例判断、置位标志 */
    void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
      if(hadc->Instance == ADC1)
      {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
        adc_conv_flag = 1;
      }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:48:16