cancel
Showing results for 
Search instead for 
Did you mean: 

ADC DMA Configuration On STM32F303

epalaima
Associate II
Posted on August 08, 2016 at 18:34

I am trying to set up DMA access for the ADC channels on the STM32F303 Discovery. I have done this successfully on the STM32F4, and have been trying to transfer it over, but unfortunately the names of a lot of things in the libraries are named differently on the two chips, which makes this task somewhat difficult. The main thing I seem to be missing is the following function, which is present in the F4 libraries but not those of the F303:

ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

My code compiles on the F303, but my DMA memory address always returns 0 in the debugger, regardless of the voltage on the ADC. Is the problem the missing function, and if so what would be the equivalent on the F303? Here is my code, please let me know if you see any problems:

&sharpdefine ADC3_DR_ADDRESS     ((uint32_t)&ADC3->DR)

__IO uint16_t ADC3ConvertedValue = 0;

__IO uint16_t ADC3ManualConvo = 0;

__IO uint16_t calibration_value = 0;

__IO uint32_t TimingDelay = 0;

static void ADC3_DMAInit(void);

void Delay(__IO uint32_t nTime);

int main(void)

{

  /*!< At this stage the microcontroller clock setting is already configured, 

       this is done through SystemInit() function which is called from startup

       file (startup_stm32f30x.s) before to branch to application main.

       To reconfigure the default setting of SystemInit() function, refer to

       system_stm32f30x.c file

     */

  

  ADC3_DMAInit();

  ADC_StartConversion(ADC3);

  while (1)

  {

//tried manual conversion, also returns 0

// while(ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET);

 //ADC3ManualConvo = ADC_GetConversionValue(ADC3);

  }

}

static void ADC3_DMAInit(void){

 DMA_InitTypeDef   DMA_InitStructure;

 ADC_InitTypeDef       ADC_InitStructure;

 ADC_CommonInitTypeDef ADC_CommonInitStructure;

 GPIO_InitTypeDef      GPIO_InitStructure;

 // Enable DMA2, GPIOC and ADC34 clock

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC34, ENABLE);

 DMA_DeInit(DMA2_Channel5);

 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC3_DR_ADDRESS;

 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC3ConvertedValue;

 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

 DMA_InitStructure.DMA_BufferSize = 1;

 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

 DMA_InitStructure.DMA_Priority = DMA_Priority_High;

 //DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

 DMA_Init(DMA2_Channel5, &DMA_InitStructure);

 // Enable DMA2 Channel3

 DMA_Cmd(DMA2_Channel5, ENABLE);

 // Enable GPIO Pins

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

 GPIO_Init(GPIOB, &GPIO_InitStructure);

 ADC_StructInit(&ADC_InitStructure);

 ADC_VoltageRegulatorCmd(ADC3, ENABLE);

 Delay(10);

 ADC_SelectCalibrationMode(ADC3, ADC_CalibrationMode_Single);

 ADC_StartCalibration(ADC3);

 while(ADC_GetCalibrationStatus(ADC3) != RESET );

 calibration_value = ADC_GetCalibrationValue(ADC3);

 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

 ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;

 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

 ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;

 ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;

 ADC_CommonInit(ADC3, &ADC_CommonInitStructure);

 ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;

 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

 ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;

 ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;

 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

 ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;

 ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;

 ADC_InitStructure.ADC_NbrOfRegChannel = 1;

 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

 ADC_Init(ADC3, &ADC_InitStructure);

 /* ADC1 regular channel7 configuration */

 ADC_RegularChannelConfig(ADC3, ADC_Channel_1, 1, ADC_SampleTime_7Cycles5);

 //ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

 //ADC3->CR2 |= (uint32_t)ADC_CR2_DDS;

 /* Enable ADC1 */

 ADC_Cmd(ADC3, ENABLE);

}

void Delay(__IO uint32_t nTime)

{

  TimingDelay = nTime;

  while(TimingDelay != 0);

}

#adc #stm32f303 #dma
4 REPLIES 4
Posted on August 08, 2016 at 19:08

Based on previous examples posted, I'd say this would be how to get it done after the ADC_Init(), and ADC_RegularChannelConfig() stuff.

...
/* Configures the ADC DMA */
ADC_DMAConfig(ADC3, ADC_DMAMode_Circular);
/* Enable the ADC DMA */
ADC_DMACmd(ADC3, ENABLE);
/* Enable ADC */
ADC_Cmd(ADC3, ENABLE);
/* wait for ADC ADRDY */
while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_RDY));
/* Enable the DMA channel */
DMA_Cmd(DMA2_Channel5, ENABLE);
/* Start ADC Software Conversion */
ADC_StartConversion(ADC3);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
epalaima
Associate II
Posted on August 08, 2016 at 19:58

Hey I tried changing my function as you described. ADC is still not working with DMA access. I noticed when debugging that my program was getting stuck in the while(ADC_GetCalibrationStatus(ADC3) != RESET ) and the while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_RDY)) loops. I tried commenting them out and the program run, but no conversion took place. 

Does the fact that those while statements are looping forever give any hint as to what might be going on? Or is there something I am still doing wrong in my function?

static void ADC3_DMAInit(void){

 DMA_InitTypeDef   DMA_InitStructure;

 ADC_InitTypeDef       ADC_InitStructure;

 ADC_CommonInitTypeDef ADC_CommonInitStructure;

 GPIO_InitTypeDef      GPIO_InitStructure;

 // Enable DMA2, GPIOC and ADC34 clock

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC34, ENABLE);

 DMA_DeInit(DMA2_Channel5);

 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC3_DR_ADDRESS;

 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC3ConvertedValue;

 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

 DMA_InitStructure.DMA_BufferSize = 1;

 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

 DMA_InitStructure.DMA_Priority = DMA_Priority_High;

 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

 DMA_Init(DMA2_Channel5, &DMA_InitStructure);

 // Enable DMA2 Channel3

 //DMA_Cmd(DMA2_Channel5, ENABLE);

 // Enable GPIO Pins

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

 GPIO_Init(GPIOB, &GPIO_InitStructure);

 ADC_StructInit(&ADC_InitStructure);

 /*

 ADC_VoltageRegulatorCmd(ADC3, ENABLE);

 Delay(10);

 ADC_SelectCalibrationMode(ADC3, ADC_CalibrationMode_Single);

 ADC_StartCalibration(ADC3);

 while(ADC_GetCalibrationStatus(ADC3) != RESET );

 calibration_value = ADC_GetCalibrationValue(ADC3);*/

 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

 ADC_CommonInitStructure.ADC_Clock = ADC_Clock_AsynClkMode;

 ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;

 ADC_CommonInitStructure.ADC_DMAMode = ADC_DMAMode_OneShot;

 ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;

 ADC_CommonInit(ADC3, &ADC_CommonInitStructure);

 ADC_InitStructure.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable;

 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

 ADC_InitStructure.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0;

 ADC_InitStructure.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None;

 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

 ADC_InitStructure.ADC_OverrunMode = ADC_OverrunMode_Disable;

 ADC_InitStructure.ADC_AutoInjMode = ADC_AutoInjec_Disable;

 ADC_InitStructure.ADC_NbrOfRegChannel = 1;

 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

 ADC_Init(ADC3, &ADC_InitStructure);

 /* ADC1 regular channel7 configuration */

 ADC_RegularChannelConfig(ADC3, ADC_Channel_1, 1, ADC_SampleTime_7Cycles5);

 //ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

 //ADC3->CR2 |= (uint32_t)ADC_CR2_DDS;

 /* Enable ADC3 */

 ADC_DMAConfig(ADC3, ADC_DMAMode_Circular);

 ADC_DMACmd(ADC3, ENABLE);

 ADC_Cmd(ADC3, ENABLE);

 //while(!ADC_GetFlagStatus(ADC3, ADC_FLAG_RDY));

 DMA_Cmd(DMA2_Channel5, ENABLE);

 ADC_StartConversion(ADC3);

}

Posted on August 08, 2016 at 20:29

I'm not actively using F3 parts, does it slave off ADC12 or require other clocks to be enabled?

/* Configure the ADC clocks */
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1);
RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div1);
/* Enable ADC1/2/3/4 clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12 | RCC_AHBPeriph_ADC34, ENABLE);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
epalaima
Associate II
Posted on August 08, 2016 at 20:39

Yes, that was it, now that I added in the clock config function, it works. Thanks!

RCC_ADCCLKConfig(RCC_ADC34PLLCLK_Div1);