Question
How to use the stm32f4xx ADC in dual regular simultaneous mode
Posted on May 31, 2016 at 16:38
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?