AnsweredAssumed Answered

How to use the stm32f4xx ADC in dual regular simultaneous mode

Question asked by georgiev.zdravko on May 31, 2016
Latest reply on Jun 1, 2016 by FTITI.Walid
The task is to measure three phase power. ADC1 measures voltage, ADC2 measures current. Here is the adc configuration routine:

static void ADC_Config(void)
{
  ADC_InitTypeDef       ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;
  DMA_InitTypeDef       DMA_InitStructure;
  GPIO_InitTypeDef      GPIO_InitStructure;
     NVIC_InitTypeDef                NVIC_InitStructure;
     EXTI_InitTypeDef                EXTI_InitStructure;
 
  /* Enable ADCx, DMA and GPIO clocks ****************************************/ 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
  RCC_AHB1PeriphClockCmd(ADCx1_CHANNEL_GPIO_CLK, ENABLE); 
     RCC_AHB1PeriphClockCmd(ADCx2_CHANNEL_GPIO_CLK, ENABLE);       
  RCC_APB2PeriphClockCmd(ADCx1_CLK, ENABLE);
     RCC_APB2PeriphClockCmd(ADCx2_CLK, ENABLE);
  
     /* Enable the DMA2 Stream0 Global Interrupt (to handle the Transfer Complete Interrupt TCIF) */
     NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
     
     
     EXTI_InitStructure.EXTI_Line = EXTI_Line0;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure); 
     
     /* Modify the WAKEUP_BUTTON_EXTI_IRQn Interrupt Preemption Priority */
     NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = SW_VRMS_IRQ_PRIOR;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);


  /* DMA2 Stream0 channel15 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_CHANNELx1;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_DR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADCxConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = DMA_BUFFER_SIZE;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  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(DMA_STREAMx1, &DMA_InitStructure);
  DMA_Cmd(DMA_STREAMx1, ENABLE);


  /* Configure ADC1 Channel15 pin as analog input ******************************/
  GPIO_InitStructure.GPIO_Pin = ADCx1_GPIO_PIN_1_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(ADCx1_GPIO_PORT_1_2, &GPIO_InitStructure);
     
     GPIO_InitStructure.GPIO_Pin = ADCx1_GPIO_PIN_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(ADCx1_GPIO_PORT_3, &GPIO_InitStructure);
     
     /* Configure ADC2 Channel15 pin as analog input ******************************/
      
     GPIO_InitStructure.GPIO_Pin = ADCx2_GPIO_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
  GPIO_Init(ADCx2_GPIO_PORT, &GPIO_InitStructure);


  /* ADC Common Init **********************************************************/
  ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
//      ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_12Cycles;
  ADC_CommonInit(&ADC_CommonInitStructure);


  /* ADC1 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_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = N_CONV;
  ADC_Init(ADCx1, &ADC_InitStructure);
     
//      ADC_TempSensorVrefintCmd(ENABLE);
     /* ADC1 regular channel15 configuration **************************************/
  ADC_RegularChannelConfig(ADCx1, ADC1_CHANNEL_1, 1, ADC_SampleTime_480Cycles);
     ADC_RegularChannelConfig(ADCx1, ADC1_CHANNEL_2, 2, ADC_SampleTime_480Cycles);
      ADC_RegularChannelConfig(ADCx1, ADC1_CHANNEL_3, 3, ADC_SampleTime_480Cycles);
     /* ADC2 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_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfConversion = N_CONV;
  ADC_Init(ADCx2, &ADC_InitStructure);
     
     /* ADC1 regular channel15 configuration **************************************/
  ADC_RegularChannelConfig(ADCx2, ADC2_CHANNEL_1, 1, ADC_SampleTime_480Cycles);
     ADC_RegularChannelConfig(ADCx2, ADC2_CHANNEL_2, 2, ADC_SampleTime_480Cycles);
     ADC_RegularChannelConfig(ADCx2, ADC2_CHANNEL_3, 3, ADC_SampleTime_480Cycles);
     
//      ADC_TempSensorVrefintCmd(ENABLE);
//  /* Enable DMA request after last transfer (Single-ADC mode) */
//   ADC_DMARequestAfterLastTransferCmd(ADCx1, ENABLE);


/* Enable DMA request after last transfer (Multi-ADC mode) */
  ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE);


     //   /* Enable ADC1 DMA */
//   ADC_DMACmd(ADCx1, ENABLE);
  /* Enable ADC1 */
  ADC_Cmd(ADCx1, ENABLE);
     /* Enable ADC2 */
  ADC_Cmd(ADCx2, ENABLE);
     
     DMA_ITConfig(DMA_STREAMx1,DMA_IT_TC,ENABLE);
}

When I N_CONV=1 and I connect the first phase only, then it's working nice. Then if I connect the second or third phase with N_CONV=1, but ADC2_CHANNEL_1 changed to _2 or _3 on first place and all other commented, then it's working fine. The N_CONV=3 version is however not working i.e. the measured values are all wrong. Are the configuration done correctly?

Outcomes