Microcontroller STM32F4 DMA不';t控制ADC通道

Microcontroller STM32F4 DMA不';t控制ADC通道,microcontroller,stm32,stm32f4discovery,stm32f4,Microcontroller,Stm32,Stm32f4discovery,Stm32f4,我正在尝试设置我的STM32F407发现板,以便使用DMA控制器从ADC1读取多个ADC通道。我可以轻松地一次读取一个模拟值而不使用DMA,但只要我为ADC启用DMA,ADC1->DR始终为0,并且ADC\u vals用零填充。此外,它在(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC))时挂起 编辑:显示DMA\u GetCmdStatus正在返回禁用状态。有什么想法吗 有没有办法启动ADC或我缺少的东西 //设置adc1:in1,2,3,8,9,15 RCC_APB

我正在尝试设置我的STM32F407发现板,以便使用DMA控制器从ADC1读取多个ADC通道。我可以轻松地一次读取一个模拟值而不使用DMA,但只要我为ADC启用DMA,
ADC1->DR
始终为0,并且
ADC\u vals
用零填充。此外,它在(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC))时挂起

编辑:显示
DMA\u GetCmdStatus
正在返回禁用状态。有什么想法吗

有没有办法启动ADC或我缺少的东西

//设置adc1:in1,2,3,8,9,15
RCC_APB2PeriphLockCmd(RCC_APB2Periph_ADC1,启用)//apb2外围总线上的adc1
ADC_InitTypeDef ADC;
ADC_DeInit()//将adc设置为默认状态
adc.adc\u DataAlign=adc\u DataAlign\u Right;
adc.adc_分辨率=adc_分辨率_12b//12位=4096
adc.adc_ContinuousConvMode=启用;
adc.adc_ExternalTrigConv=adc_ExternalTrigConv_T1_CC1;
adc.adc_externaltrigconverge=adc_externaltrigconverge_None;
adc.adc_nbrofversion=NUM_adc;
adc.adc_ScanConvMode=启用;
ADC_Init(ADC1和ADC);
ADC\U DMACmd(ADC1,启用)//为dma启用adc。当这行被删除时,我在ADC1->DR上看到数据
ADC_Cmd(ADC1,启用);
ADC_RegularChannelConfig(ADC1、ADC_Channel_1,1、ADC_SampleTime_144周期)//1:1710, 0
//ADC_RegularChannelConfig(ADC1、ADC_Channel_2,2、ADC_SampleTime_144周期)//2:1710, 0
//ADC_RegularChannelConfig(ADC1、ADC_Channel_3,3、ADC_采样时间_144个周期)//3:1710, 0
ADC_RegularChannelConfig(ADC1,ADC_通道8,4,ADC_采样时间144个周期)//8:3520
ADC_RegularChannelConfig(ADC1、ADC_Channel_9,5、ADC_SampleTime_144周期)//9:1000
//ADC_RegularChannelConfig(ADC1、ADC_Channel_15,6、ADC_SampleTime_144周期)//15:3920
//多个adc通道的DMA:
RCC_AHB1PeriphLockCmd(RCC_AHB1Periph_DMA1,启用)//dma1时钟使能
DMA_InitTypeDef DMA;
DMA_脱硝(DMA2_-0)//将DMA2流0重置为默认值
dma.dma_Channel=dma_Channel_0;
dma.dma_peripheraldbaseaddr=(uint32_t)和(ADC1->DR);
dma.dma_Memory0BaseAddr=(uint32_t)和adc_vals[0];
dma.dma_DIR=dma_DIR_外设存储器;
dma.dma_BufferSize=NUM_ADC;
dma.dma_PeripheralInc=dma_PeripheralInc_Disable;
dma.dma_MemoryInc=dma_MemoryInc_Enable;
dma.dma_peripheraldasize=dma_peripheraldasize_半字;
dma.dma_MemoryDataSize=dma_MemoryDataSize_半字;
dma.dma_Mode=dma_Mode_循环;
dma.dma_Priority=dma_Priority_High;
dma.dma_FIFOMode=dma_FIFOMode_Disable;
dma.dma_FIFOThreshold=dma_FIFOThreshold_半满;
dma.dma_MemoryBurst=dma_MemoryBurst_Single;
dma.dma_PeripheralBurst=dma_PeripheralBurst_Single;
DMA_Init(DMA2_流0和DMA);
DMA_UITConfig(DMA2 U Stream0,DMA IT| DMA| DMA IT_uHT,ENABLE)//启用DMA流半/传输完成中断
DMA_Cmd(DMA2_Stream0,启用)//DMA2_Stream0启用
//dma传输完成中断:
NVIC_InitTypeDef NVIC;
//启用DMA1通道IRQ通道
nvic.nvic_IRQChannel=DMA2_Stream0_IRQn;
nvic.nvic_IRQChannelPreemptionPriority=0;
nvic.nvic_IRQChannelSubPriority=0;
nvic.nvic_IRQChannelCmd=启用;
NVIC_Init(&NVIC);
ADC_软件STARTCONV(ADC1)//启动adc转换
至少您可以尝试:

  • 更改DMA_外围设备公司
以启用
  • 使用
    ADC\u DMARequestAfterLastTransferCmd(ADC,启用)
  • 初始化
    ADC\u CommonInitTypeDef
  • 初始化GPIO,如果不是
  • 此外,在所有配置之前启用ADC是很奇怪的


    在我看来,最好的方法是从标准外设库复制粘贴“ADC_DualModeRegulSimu”示例。它包含的代码非常漂亮,完全符合您的需要。

    出现了许多错误。以下是我为其他有同样问题的人编写的工作代码:

        //DMA for multiple adc channels:
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //ADC1 on APB2 peripheral bus
    
    DMA_InitTypeDef dma; //dma2/stream0/channel0
    dma.DMA_Channel = DMA_Channel_0; 
    dma.DMA_Memory0BaseAddr = (uint32_t)&adcVal;
    dma.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
    dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
    dma.DMA_BufferSize = 6;
    dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
    dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    dma.DMA_Mode = DMA_Mode_Circular;
    dma.DMA_Priority = DMA_Priority_High;
    dma.DMA_FIFOMode = DMA_FIFOMode_Enable;              
    dma.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream0, &dma);
    DMA_Cmd(DMA2_Stream0, ENABLE); //dMA2_Stream0 enable
    
    //analog inputs: PA1,2,3, PC5, PB0,1
    gpio.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    gpio.GPIO_Mode = GPIO_Mode_AN;
    gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &gpio);
    gpio.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOC, &gpio);
    gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_Init(GPIOB, &gpio);
    
    //ADC common init
    ADC_CommonInitTypeDef adcCommon;
    adcCommon.ADC_Mode = ADC_Mode_Independent;
    adcCommon.ADC_Prescaler = ADC_Prescaler_Div2;
    adcCommon.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    adcCommon.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&adcCommon);
    
    //setup adc1: in1,2,3,8,9,15
    ADC_InitTypeDef adc;
    ADC_DeInit(); //set adc to default state
    adc.ADC_DataAlign = ADC_DataAlign_Right; //mask 0b 00001111 11111111
    adc.ADC_Resolution = ADC_Resolution_12b;//12 bit = 4096
    adc.ADC_ContinuousConvMode = ENABLE; //continuous: constantly converting data - can always read register
    adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;//external trigger conversion (?)
    adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    adc.ADC_NbrOfConversion = 6;
    adc.ADC_ScanConvMode = ENABLE;//single/multichannel
    ADC_Init(ADC1,&adc);
    
    ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_56Cycles); ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_56Cycles);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_3,3,ADC_SampleTime_56Cycles);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_8,4,ADC_SampleTime_56Cycles);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_9,5,ADC_SampleTime_56Cycles);
    ADC_RegularChannelConfig(ADC1,ADC_Channel_15,6,ADC_SampleTime_56Cycles);
    
    
    ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); //single adc repeated
    
    ADC_DMACmd(ADC1, ENABLE);
    ADC_Cmd(ADC1,ENABLE);
    

    感谢代码ethan,使minor mod适合我的情况,并作为通用功能工作

    volatile uint16_t adcVal[6];
    
    void Setup_DMA_ADC( void )
    {
        GPIO_InitTypeDef gpio;
        //DMA for multiple adc channels:
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //ADC1 on APB2 peripheral bus
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
    
        DMA_InitTypeDef dma; //dma2/stream0/channel0
        dma.DMA_Channel = DMA_Channel_0;
        dma.DMA_Memory0BaseAddr = (uint32_t) &adcVal[0];
        dma.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
        dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
        dma.DMA_BufferSize = 6;
        dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
        dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        dma.DMA_Mode = DMA_Mode_Circular;
        dma.DMA_Priority = DMA_Priority_High;
        dma.DMA_FIFOMode = DMA_FIFOMode_Enable;
        dma.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
        dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
        dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
        DMA_Init(DMA2_Stream0, &dma);
        DMA_Cmd(DMA2_Stream0, ENABLE); //dMA2_Stream0 enable
    
        //analog inputs: PA1,2,3, PC5, PB0,1
        GPIO_StructInit(&gpio);
        gpio.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
        gpio.GPIO_Mode = GPIO_Mode_AN;
        gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOA, &gpio);
        gpio.GPIO_Pin = GPIO_Pin_5;
        GPIO_Init(GPIOC, &gpio);
        gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
        GPIO_Init(GPIOB, &gpio);
    
        //ADC common init
        ADC_CommonInitTypeDef adcCommon;
        adcCommon.ADC_Mode = ADC_Mode_Independent;
        adcCommon.ADC_Prescaler = ADC_Prescaler_Div2;
        adcCommon.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
        adcCommon.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
        ADC_CommonInit(&adcCommon);
    
        //setup adc1: in1,2,3,8,9,15
        ADC_InitTypeDef adc;
        ADC_DeInit(); //set adc to default state
        adc.ADC_DataAlign = ADC_DataAlign_Right; //mask 0b 00001111 11111111
        adc.ADC_Resolution = ADC_Resolution_12b;//12 bit = 4096
        adc.ADC_ContinuousConvMode = ENABLE; //continuous: constantly converting data - can always read register
        adc.ADC_ExternalTrigConv = DISABLE;//ADC_ExternalTrigConv_T1_CC1;//external trigger conversion (?)
        adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
        adc.ADC_NbrOfConversion = 6;
        adc.ADC_ScanConvMode = ENABLE;//single/multichannel
        ADC_Init(ADC1,&adc);
    
        ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_56Cycles);
        ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_56Cycles);
        ADC_RegularChannelConfig(ADC1,ADC_Channel_3,3,ADC_SampleTime_56Cycles);
        ADC_RegularChannelConfig(ADC1,ADC_Channel_8,4,ADC_SampleTime_56Cycles);
        ADC_RegularChannelConfig(ADC1,ADC_Channel_9,5,ADC_SampleTime_56Cycles);
        ADC_RegularChannelConfig(ADC1,ADC_Channel_15,6,ADC_SampleTime_56Cycles);
    
    
        ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); //single adc repeated
    
        ADC_DMACmd(ADC1, ENABLE);
        ADC_Cmd(ADC1,ENABLE);
        // Start ADC conversion
        ADC_SoftwareStartConv(ADC1);
        return;
    }
    

    我的部分问题是在adc之前没有设置dma。现在,我可以从ADC1->DR中准确读取一个adc值,但它在那里冻结,adc值仍然为零[I]您的主要问题是HAL。裸寄存器简单明了。我希望看到更复杂的配置:)。HAL-工作月数-登记-小时数。