STM32F4 DMA不控制ADC通道



我正在尝试设置我的STM32F407-DISCOVERY板,以使用DMA控制器从ADC1读取多个ADC频道。我可以轻松地一次不使用DMA读取模拟值一个,但是一旦我启用DMA,ADC1->DR始终为0,并且adc_vals填充了零。此外,它挂在while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));上。

编辑:将会出现DMA_GetCmdStatus正在返回禁用。有什么想法吗?

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

//setup adc1: in1,2,3,8,9,15
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); //adc1 on the apb2 peripheral bus
ADC_InitTypeDef adc;
ADC_DeInit(); //set adc to default state
adc.ADC_DataAlign = ADC_DataAlign_Right;
adc.ADC_Resolution = ADC_Resolution_12b;//12 bit = 4096
adc.ADC_ContinuousConvMode = ENABLE;
adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
adc.ADC_NbrOfConversion = NUM_ADC;
adc.ADC_ScanConvMode = ENABLE;
ADC_Init(ADC1,&adc);

ADC_DMACmd(ADC1, ENABLE); //enable adc for dma.  When this line is removed, I see data on ADC1->DR

ADC_Cmd(ADC1,ENABLE);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_144Cycles);//1:1710, 0
//ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_144Cycles);//2:1710, 0
//ADC_RegularChannelConfig(ADC1,ADC_Channel_3,3,ADC_SampleTime_144Cycles);//3:1710, 0
ADC_RegularChannelConfig(ADC1,ADC_Channel_8,4,ADC_SampleTime_144Cycles);//8:3520
ADC_RegularChannelConfig(ADC1,ADC_Channel_9,5,ADC_SampleTime_144Cycles);//9:1000
//ADC_RegularChannelConfig(ADC1,ADC_Channel_15,6,ADC_SampleTime_144Cycles);//15:3920

//DMA for multiple adc channels:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); //dma1 clock enable
DMA_InitTypeDef dma;
DMA_DeInit(DMA2_Stream0); //reset DMA2 stream 0 to default values
dma.DMA_Channel = DMA_Channel_0;
dma.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
dma.DMA_Memory0BaseAddr = (uint32_t)&adc_vals[0];
dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
dma.DMA_BufferSize = NUM_ADC;
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_Disable;
dma.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &dma);
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE); //Enable DMA Stream Half / Transfer Complete interrupt
DMA_Cmd(DMA2_Stream0, ENABLE); //DMA2_Stream0 enable
//dma transfer complete interrupt:
NVIC_InitTypeDef nvic;
//Enable DMA1 channel IRQ Channel
nvic.NVIC_IRQChannel = DMA2_Stream0_IRQn;
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
ADC_SoftwareStartConv(ADC1);//Start the adc conversion

至少您可以尝试:

  • DMA_PeripheralInc更改为启用
  • 组转换后使用ADC_DMARequestAfterLastTransferCmd(ADC, Enable);进行DMA请求。
  • init ADC_CommonInitTypeDef
  • init 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,使MID 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;
}

最新更新