AnsweredAssumed Answered

Problem reading out multiple ADCs by DMA

Question asked by Seeboerger.Patrick on Apr 9, 2016
Latest reply on Jun 20, 2016 by Clive One
Hallo all together,

I am trying to expand my source code which is working with 3 ADC Inputs by a 4th ADC Input, which is connected to port PC5 of the STM32F4 discovery board.

The actual Code which works looks like:

static void ADC_Config(void)
{
  GPIO_InitTypeDef        GPIO_InitStructure;
  DMA_InitTypeDef         DMA_InitStructure;
  ADC_InitTypeDef         ADC_InitStructure;
  ADC_CommonInitTypeDef   ADC_CommonInitStructure;
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
 
 
  /* Enable peripheral clocks *************************************************/
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 |  RCC_APB2Periph_ADC3 ,ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 
  // PA.05 ADC12_IN5    ADC1
  // PC.03 ADC123_IN13  ADC2
  // PF.06 ADC3_IN4     ADC3
 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
  /* DMA2 Stream0 channel0 configuration **************************************/
 // DMA_DeInit(DMA2_Stream0); // set DMA registers to default values
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  // select DMA_channel 0
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) ADC_CDR_ADDRESS; // Source address, as described in RM0090 on page 404 for multi adc mode
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADCTripleConvertedValue; // Destination address
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = 3;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  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);
 
 /* Enable DMA Stream Half / Transfer Complete interrupt */
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_HT, ENABLE);
 
  /* DMA2_Stream0 enable */
  DMA_Cmd(DMA2_Stream0, ENABLE);
 
 /* Time base configuration for 5 ms (200 Hz) */
  TIM_TimeBaseStructure.TIM_Prescaler = ((SystemCoreClock / 2) / 1000000) - 1;     // 1 MHz
  TIM_TimeBaseStructure.TIM_Period = (1000000 / 125000) - 1;              // 1 MHz to 125000 Hz
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
 
  /* TIM2 TRGO selection */
  TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);                // ADC_ExternalTrigConv_T2_TRGO
 
  /* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);
  /* ADC Common configuration *************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl;              //
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2; 
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInit(&ADC_CommonInitStructure);
  /* DMA mode 2 is used in interleaved mode in 12-bit resolutions *************/
  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
 
  /* ADC regular channel configuration ************************************/
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = 3;                    // Anzahl der Kanäle die über den Sequencer ausgelesen werden sollen
  ADC_Init(ADC1, &ADC_InitStructure);
  ADC_Init(ADC2, &ADC_InitStructure);                        // Mirror on ADC2
  ADC_Init(ADC3, &ADC_InitStructure);                        // Mirror on ADC3
 
  /* ADC1 regular channel 5 configuration */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_5,  1, ADC_SampleTime_84Cycles);    // PA5
 
  /* ADC2 regular channel 13 configuration */
  ADC_RegularChannelConfig(ADC2, ADC_Channel_13, 1, ADC_SampleTime_84Cycles);    // PC3
 
  /* ADC3 regular channel 4 configuration */
  ADC_RegularChannelConfig(ADC3, ADC_Channel_4,  1, ADC_SampleTime_84Cycles);    // PF6
 
 /* Enable DMA request after last transfer (multi-ADC mode) ******************/
  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);
 
  /* Enable ADC1 **************************************************************/
  ADC_Cmd(ADC1, ENABLE);
  /* Enable ADC2 **************************************************************/
  ADC_Cmd(ADC2, ENABLE);
  /* Enable ADC3 **************************************************************/
  ADC_Cmd(ADC3, ENABLE);
 
 
}

To implement the fourth channel PC5 I do the following changes:

Enlarge the Memory Array:
__IO uint32_t uhADCTripleConvertedValue[3]; changes to
__IO uint32_t uhADCTripleConvertedValue[4];

Configure port PC5 like the other ADC Inputs:

// PA.05 ADC12_IN5    ADC1
  // PC.03 ADC123_IN13  ADC2
 // PC.05 ADC12_IN15  ADC1
  // PF.06 ADC3_IN4     ADC3
 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOF, &GPIO_InitStructure);

Change the DMA Buffer Size:

DMA_InitStructure.DMA_BufferSize = 4;

Change the number of ADC conversions:

ADC_InitStructure.ADC_NbrOfConversion = 4;

and add the following ADC regular channel configuration:

/* ADC2 regular channel 13 configuration */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 1, ADC_SampleTime_84Cycles);    // PC5


After all these changes the displayed values of the ADCs vary and do not fit anymore.

Does anyboby of you know what I did wrong or what I forgot?

Thanks in advance!

Best regards,

Patrick 

Outcomes