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

STM32F411 ADC+DMA扫描连续模式仅执行一次转换问题求助

问题分析与解决方案

你的代码中导致ADC仅执行一次序列转换的核心问题有两处,以下是具体分析和修复方案:

1. 未启用ADC的DMA连续请求模式

当DMA工作在循环模式(DMA_SxCR_CIRC)时,必须配置ADC的DDS位(DMA Disable Selection),否则当DMA第一次完成4次传输后,ADC会停止产生DMA请求,导致后续转换无法触发DMA传输。

需要在ADC配置中添加:

ADC1->CR2 |= ADC_CR2_DDS;  // 开启DMA连续请求,即使NDTR归零仍持续产生请求

2. 缺失ADC校准步骤(可选但推荐)

STM32 ADC上电后执行校准可以提升转换精度,避免因未校准导致的异常行为,建议在开启ADC前添加校准流程:

ADC1->CR2 |= ADC_CR2_ADON;       // 第一次开启ADC,准备校准
while(!(ADC1->SR & ADC_SR_ADRDY)); // 等待ADC就绪
ADC1->CR2 |= ADC_CR2_CAL;        // 启动校准
while(ADC1->CR2 & ADC_CR2_CAL);  // 等待校准完成

3. 明确DMA通道选择(可选但更稳妥)

虽然复位后DMA2 Stream0默认选择Channel 0(对应ADC1请求),但明确配置通道可以避免潜在的配置冲突:

DMA2_Stream0->CR &= ~DMA_SxCR_CHSEL_Msk; // 清除通道选择位
DMA2_Stream0->CR |= 0 << DMA_SxCR_CHSEL_Pos; // 选择Channel 0(ADC1请求)

修改后的完整代码

#include "stm32f411xe.h"
int16_t adc_ch[4];

int main()
{
    // Enabling peripheral clocks
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
    RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;  // Enable DMA2 clock  

    // Pin A0-A3 as analog inputs
    GPIOA->MODER |= GPIO_MODER_MODE0 | GPIO_MODER_MODE1 | GPIO_MODER_MODE2 | GPIO_MODER_MODE3;    

    // Configuring sequence for analog reading
    ADC1->SQR1 |= 3 << 20;                    // Sequence length: 4 channels
    ADC1->SQR3 |= 0 << 0;                     // A0 first
    ADC1->SQR3 |= 1 << 5;                     // A1 second
    ADC1->SQR3 |= 2 << 10;                    // A2 third
    ADC1->SQR3 |= 3 << 15;                    // A3 fourth

    // Setting ADC1 
    ADC1->CR1 |= ADC_CR1_SCAN;          // Enable scanning mode 
    ADC1->CR2 |= ADC_CR2_DMA;           // Enable DMA mode
    ADC1->CR2 |= ADC_CR2_DDS;           // Enable continuous DMA requests

    // ADC calibration (recommended)
    ADC1->CR2 |= ADC_CR2_ADON;
    while(!(ADC1->SR & ADC_SR_ADRDY));
    ADC1->CR2 |= ADC_CR2_CAL;
    while(ADC1->CR2 & ADC_CR2_CAL);

    // Setting DMA channel
    DMA2_Stream0->PAR  = (uint32_t)(&(ADC1->DR));           // DMA source address (ADC DR)
    DMA2_Stream0->M0AR = (uint32_t)(&(adc_ch[0]));          // DMA destination address (array)
    DMA2_Stream0->NDTR = 4;                                 // Number of data items to transfer

    DMA2_Stream0->CR &= ~DMA_SxCR_CHSEL_Msk;
    DMA2_Stream0->CR |= 0 << DMA_SxCR_CHSEL_Pos;            // Select Channel 0 (ADC1)
    DMA2_Stream0->CR |= DMA_SxCR_CIRC                       // Enable circular mode
                      | DMA_SxCR_MINC                       // Enable memory address increment
                      | DMA_SxCR_PSIZE_0                    // Peripheral data size: 16 bits
                      | DMA_SxCR_MSIZE_0;                   // Memory data size: 16 bits
    DMA2_Stream0->CR |= DMA_SxCR_EN;                        // Enable DMA stream

    // Start continuous ADC conversion
    ADC1->CR2 |= ADC_CR2_CONT;
    ADC1->CR2 |= ADC_CR2_ADON;
    ADC1->CR2 |= ADC_CR2_SWSTART;

    while(1)
    {
        // 可在此添加调试代码,比如读取adc_ch数组的值验证转换状态
    }
}

验证说明

修改后,DMA会在循环模式下持续将ADC转换结果传输到adc_ch数组,配合ADC的连续转换模式(ADC_CR2_CONT),实现4个通道的连续扫描读取。你可以在while(1)循环中添加调试代码,观察adc_ch数组的值是否持续更新,确认功能正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:17:07