2017-03-09 113 views
0

我试图设置我的STM32F407-Discovery板以使用DMA控制器从ADC1读取多个ADC通道。我可以在不使用DMA的情况下轻松读取模拟值,但只要为ADC启用DMA,ADC1->DR始终为0,并且adc_vals填充了零。此外,它挂在while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));STM32F4 DMA不控制ADC通道

编辑:它会出现DMA_GetCmdStatus正在返回DISABLED。有任何想法吗?

有没有办法启动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 
+0

那么,我的问题的一部分,是没有成立之前的广告。现在,我可以读取ADC1-> DR中的一个adc值,但它在那里冻结,并且在adc_vals中仍然为零[i] – ethan

回答

0

至少你可以试试:

  • 变化DMA_PeripheralInc启用组转换后的DMA请求
  • 使用ADC_DMARequestAfterLastTransferCmd(ADC, Enable);
  • 初始化ADC_CommonInitTypeDef
  • 初始化GPIO,如果不是

所有配置前,而且使ADC很奇怪。

我认为最好的方法是从标准外设库复制粘贴“ADC_DualModeRegulSimu”示例。它包含精美的代码,完全符合您的需求。

+0

谢谢!这个例子非常有帮助! – ethan

0

有一些错误。这是我的工作代码给其他人有同样的麻烦:

//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);