cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 ADC With DMA Multi Channel Problem

haythem
Associate II
Posted on March 17, 2014 at 15:01

Hi, since some days I'm trying to create a code to operate the ADC with DMA for STM32F4 card, the problem is that my code does not work if I want to add a second chanel because it always displays the same values for both pins. 

Please who can help me solve my problem 

Here is my code:

#include ''stm32f4_discovery.h''

#include <stdio.h>

#define ADC3_DR_ADDRESS     ((uint32_t)0x4001224C)

/* You can monitor the converted value by adding the variable ''ADC3ConvertedValue'' 

   to the debugger watch window */

__IO uint16_t ADC3ConvertedValue = 0;

__IO uint32_t ADC3ConvertedVoltage = 0;

__IO uint32_t val[2]={0,0};

/**********************************/

  ADC_InitTypeDef       ADC_InitStructure;

  ADC_CommonInitTypeDef ADC_CommonInitStructure;

  DMA_InitTypeDef       DMA_InitStructure;

  GPIO_InitTypeDef      GPIO_InitStructure;

void ADC3_CH12_DMA_Config(void);

int main(void)

{

 

  /* ADC3 configuration *******************************************************/

  /*  - Enable peripheral clocks                                              */

  /*  - DMA2_Stream0 channel2 configuration                                   */

  /*  - Configure ADC Channel12 pin as analog input                           */

  /*  - Configure ADC3 Channel12                                              */

  ADC3_CH12_DMA_Config();

  /* Start ADC3 Software Conversion */ 

  ADC_SoftwareStartConv(ADC3);

;

  while (1)

  {

  /* convert the ADC value (from 0 to 0xFFF) to a voltage value (from 0V to 3.3V)*/

val[0]=ADC3ConvertedValue *5000/0xFFF;

val[1]=ADC3ConvertedValue*5000/0xFFF;

  }

}

void ADC3_CH12_DMA_Config(void)

{

  /* Enable ADC3, DMA2 and GPIO clocks ****************************************/

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

  /* DMA2 Stream0 channel0 configuration **************************************/

  DMA_InitStructure.DMA_Channel = DMA_Channel_2;  

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = 2;

  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_FIFOMode = DMA_FIFOMode_Disable;         

  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* Configure ADC3 Channel12 pin as analog input ******************************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 |GPIO_Pin_3 ;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADC Common Init **********************************************************/

  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Init ****************************************************************/

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = ENABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 2;

  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channel12 configuration *************************************/

  ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_3Cycles);

  ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 2, ADC_SampleTime_3Cycles);

 /* Enable DMA request after last transfer (Single-ADC mode) */

  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */

  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC3 */

  ADC_Cmd(ADC3, ENABLE);

}

6 REPLIES 6
raptorhal2
Lead
Posted on March 17, 2014 at 15:18

__IO uint16_t ADC3ConvertedValue = [0,0];

You also need to configure the second channel pin to analog.

Then access each array element for the two values instead of the ADC  value register.

The channel 13 pin is also used by another peripheral on the F4 Discovery board. There is a table in the F4 Discovery User manual which defines which pins are freely available for your use.

Cheers, Hal

haythem
Associate II
Posted on March 17, 2014 at 15:39

I replaced the pin3 by pin 1 and I change the chanel but when I wrote 

__IO Uint16_t ADC3ConvertedValue = [0,0], it displays an error .. \ main.c (8): error: # 29: expected year term

raptorhal2
Lead
Posted on March 17, 2014 at 17:51

Sorry, I gave you the wrong advice and bad coding. Point the DMA memory to:

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&val;

Then pick up the converted values there.

Cheers, Hal

haythem
Associate II
Posted on March 17, 2014 at 19:33

thank you for your help 

I did this but if it does not work

raptorhal2
Lead
Posted on March 17, 2014 at 20:38

Show the new code.

Cheers, Hal

stm322399
Senior
Posted on March 18, 2014 at 14:07

Claude,

DMA are very susceptible devices, the most probable cause for your problem is that DMA2_Stream0 is wrong state. Try this before DMA_Init():

DMA_DeInit(DMA2_Stream0);

Let ADC be handled the same way:

ADC_DeInit();

It's a bit strong where simply clearing ADC3->SR should suffice, but that way you are safer. By the way, when using the ST library you must take care either to initialize whole init structure or simply use the proper 'init' function:

DMA_StructInit(&DMA_InitStructure);
GPIO_StructInit(&GPIO_InitStructure);
ADC_StructInit(&ADC_InitStructure);

Remember that when an overflow occurs, the whole DMA+ADC must be reconfigured (according what says the RM). Et voilà !