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

STM32使用DMA时ADC转换始终无法完成问题求助

STM32F429 ADC_FLAG_EOC始终未置位问题分析与解决

核心问题定位

你的代码存在两个关键问题,其中ADC时钟超限是导致转换完全无法进行的根本原因,其次是对ADC_FLAG_EOC触发逻辑的理解偏差。

1. ADC时钟配置错误(致命问题)

STM32F4系列的ADC模块时钟上限为36MHz,而你的配置中:

ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

STM32F429的APB2总线时钟默认是90MHz(当AHB为180MHz时),经过2分频后ADC时钟为45MHz,远超36MHz的最大允许值,直接导致ADC硬件无法正常工作,自然不会产生转换完成标志。

修正方案:
将预分频改为ADC_Prescaler_Div4或更高,确保ADC时钟≤36MHz:

ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; // 90MHz /4 =22.5MHz,符合要求

2. ADC_FLAG_EOC触发逻辑误解

在你启用了扫描模式(ADC_ScanConvMode = ENABLE)且未配置ADC_EOCSelection的情况下,STM32F4的ADC默认仅在整个序列转换完成后才置位ADC_FLAG_EOC,而非每个通道转换完成都置位。

你的TIM中断代码中两次等待ADC_FLAG_EOC并尝试读取ADC_GetValue(0)、ADC_GetValue(1)是错误的:

  • ADC_GetValue函数不需要参数,它直接返回ADC_DR寄存器的值
  • 读取DR寄存器会自动清除ADC_FLAG_EOC标志,第一次读取后标志被清除,第二次等待会直接卡死

修正方案:
如果需要每个通道转换完成都触发EOC,添加如下配置:

ADC_InitStructure.ADC_EOCSelection = ADC_EOCSelection_Single;

如果使用扫描模式+DMA,无需手动轮询EOC,DMA会自动搬运每个通道的转换结果;若关闭DMA,单次序列转换完成后读取一次DR即可获取最后一个通道的结果(或通过DMA方式获取所有通道数据)。

3. 其他辅助排查点

  • 采样时间过短:ADC_SampleTime_3Cycles是最短采样时间,对于部分模拟输入可能不足,建议先改用ADC_SampleTime_15Cycles测试
  • GPIO配置确认:确保PA7(通道7)、PC3(通道13)确实配置为模拟输入,无其他外设占用引脚
  • 连续转换模式逻辑:启用连续转换后,ADC会自动循环转换,无需在TIM中断中重复启动,若需要定时采样,应改用单次转换模式,每次中断启动一次转换

简化测试代码

以下是修正后的单通道测试代码,可快速验证ADC是否正常工作:

void GPIO_ADC_Config() {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void ADC_Config(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 1;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 1, ADC_SampleTime_15Cycles);
    ADC_Cmd(ADC1, ENABLE);
}

// 在主循环或TIM中断中测试
void Test_ADC() {
    ADC_SoftwareStartConv(ADC1);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    uint16_t adc_value = ADC_GetConversionValue(ADC1);
    // 处理adc_value
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:13:23