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

STM32 ADC1扫描模式DMA循环模式下程序滞留在回调的问题

问题分析与解决方案

你的问题核心是DMA循环模式配合DMAContinuousRequests = ENABLE时,ADC转换完成中断会被持续触发,如果回调函数处理不当或中断优先级配置不合理,会导致主循环(while(1))完全被抢占,无法获得执行机会。以下是具体解决方法:

1. 优化回调函数,避免阻塞

回调函数必须轻量化,仅完成必要的标记操作,把数据处理逻辑放到主循环中。示例如下:

首先定义一个转换完成标志:

static uint8_t adc_conv_done = 0;

修改回调函数:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1)
    {
        adc_conv_done = 1; // 仅置位标志,快速退出回调
    }
}

在主循环中处理数据:

while(1)
{
    if (adc_conv_done)
    {
        // 在这里处理adc_buffer中的数据,比如:
        // uint16_t ch1_val = adc_buffer[0];
        // uint16_t ch2_val = adc_buffer[1];
        // uint16_t ch3_val = adc_buffer[2];
        
        adc_conv_done = 0; // 清除标志,等待下一次转换完成
    }
    // 主循环的其他任务
}

2. 调整中断优先级配置

检查NVIC中ADC和DMA的中断优先级,避免其优先级过高导致完全抢占主循环。确保:

  • ADC/DMA的中断抢占优先级不要设置得过高,在裸机环境中,过高的优先级会让中断持续占用CPU,主循环无法执行。
  • 可以通过STM32CubeMX的「NVIC Configuration」页面,降低ADC和DMA通道的抢占优先级数值(数值越大,优先级越低)。

3. 按需调整DMA与ADC的循环配置

如果不需要持续不间断的转换,可以修改配置:

  • 将hadc1.Init.DMAContinuousRequests设为DISABLE,这样单次扫描完成后不会自动发起下一次转换,需要在回调中手动重启:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1)
    {
        adc_conv_done = 1;
        HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, 3); // 手动重启下一次转换
    }
}

这种方式可以控制转换触发频率,减少中断触发次数,给主循环留出更多执行时间。

4. 排查回调内的阻塞代码

检查当前回调函数中是否存在while()循环、延时函数等阻塞操作,这类代码会直接导致回调无法退出,彻底卡住程序。确保回调函数内无任何阻塞逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 21:36:16