Skip to main content
aatif shaikh
Associate III
November 27, 2018
Question

read multiple ADC channels of same ADC without DMA

  • November 27, 2018
  • 6 replies
  • 1676 views

hello!

I want to read multiple ADC channels of the same ADC without using DMA. But I'm continuously facing some unknown issues (on ADC3 channel 12 &13's value randomly switching). So If any previously done example codes available for STM32f20X using the Standard library, please share the link.

also if anyone can help me with my code's rectification would be a great help. 

note: I'm reading totally 4 ADC channels, 2 on ADC1 and ADC2 and 2 channels on ADC3 so channels on ADC1 and ADC2 giving me proper values but channels on ADC3 randomly switching (in 4th printf sometimes channel 3rd's value is printing and in 3rd printf vice versa )

here is my code:

float 			fval;
uint16_t 		ret;
ADC_InitTypeDef 			 stADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef 		 stGPIO_InitStructure;
		
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB 
| RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD 	
| RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF
| RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH 
| RCC_AHB1Periph_GPIOI , ENABLE);
		
		
/********************* ADC1 INITIALIZATION***************/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC , ENABLE);
		
/*ADC Deinit*/
ADC_DeInit();
		
/*ADC Structure Initialization*/
ADC_StructInit(&stADC_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);
 
/* ADC1 Init****************************************************************/
stADC_InitStructure.ADC_Resolution 		= ADC_Resolution_12b;
stADC_InitStructure.ADC_ScanConvMode 	= DISABLE;
stADC_InitStructure.ADC_ContinuousConvMode 	= ENABLE;
stADC_InitStructure.ADC_ExternalTrigConvEdge 	= ADC_ExternalTrigConvEdge_None;
stADC_InitStructure.ADC_ExternalTrigConv 		= ADC_ExternalTrigConv_T1_CC1; 
stADC_InitStructure.ADC_DataAlign 			= ADC_DataAlign_Right;
stADC_InitStructure.ADC_NbrOfConversion 		= 1;
ADC_Init(ADC1, &stADC_InitStructure);
ADC_Init(ADC2, &stADC_InitStructure);
		
 
/*Enable the ADC*/
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
 
/* Configure channel */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
		
/* Configure channel */
ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 1, ADC_SampleTime_3Cycles);
	
	
stGPIO_InitStructure.GPIO_Pin		= GPIO_Pin_0 	 ;
stGPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz	;
stGPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP		;
stGPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AN	 ;
stGPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL	;
GPIO_Init(GPIOC, &stGPIO_InitStructure);
 
		
stGPIO_InitStructure.GPIO_Pin		= GPIO_Pin_1 			;
stGPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz	;
stGPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP		;
stGPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AN		;
stGPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL	;
GPIO_Init(GPIOC, &stGPIO_InitStructure);
 
/* ADC Common Init **********************************************************/
ADC_CommonInitStructure.ADC_Mode 				= ADC_DualMode_RegSimult;
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);
 
/* ADC1 Init ****************************************************************/
stADC_InitStructure.ADC_Resolution 			= ADC_Resolution_12b;
stADC_InitStructure.ADC_ScanConvMode 		= ENABLE;
stADC_InitStructure.ADC_ContinuousConvMode 	= ENABLE;
stADC_InitStructure.ADC_ExternalTrigConvEdge 	= ADC_ExternalTrigConvEdge_None;
stADC_InitStructure.ADC_ExternalTrigConv 		= ADC_ExternalTrigConv_T1_CC1; 
stADC_InitStructure.ADC_DataAlign 			= ADC_DataAlign_Right;
stADC_InitStructure.ADC_NbrOfConversion 	 = 2; 
ADC_Init(ADC3, &stADC_InitStructure);
 
/*Enable the ADC*/	
ADC_Cmd(ADC3, ENABLE);	
				
/* Configure channel */
ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 1, ADC_SampleTime_3Cycles);	
		
/* Configure channel */
ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 2, ADC_SampleTime_3Cycles);
 
stGPIO_InitStructure.GPIO_Pin		= GPIO_Pin_2 			;
stGPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz	;
stGPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP		;
stGPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AN		;
stGPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL	;
GPIO_Init(GPIOC, &stGPIO_InitStructure);
	
	
stGPIO_InitStructure.GPIO_Pin		= GPIO_Pin_3 			;
stGPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz	;
stGPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP		;
stGPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AN		;
stGPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL	;
GPIO_Init(GPIOC, &stGPIO_InitStructure);
	
	
	while(1)
	{
		
		/* Start the conversion */
		 ADC_SoftwareStartConv(ADC1);
		/* Wait until conversion completion */
		while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
		/* Get the conversion value */
		ret = ADC_GetConversionValue(ADC1);
		fval = (float)(ret * (ADCRESOLUTION));
		printf ("RET=%x\tPOT 1=%fV\n\r",ret,fval);
 
		/* Start the conversion */
		 ADC_SoftwareStartConv(ADC2);
		/* Wait until conversion completion */
		while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET);
		/* Get the conversion value */
		ret = ADC_GetConversionValue(ADC2);
		fval = (float)(ret * (ADCRESOLUTION));
		printf ("RET=%x\tPOT 2=%fV\n\r",ret,fval);
			
		/* Start the conversion */
		 ADC_SoftwareStartConv(ADC3); 
		/* Wait until conversion completion */
		while(ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET);
		/* Get the conversion value */
		ret = ADC_GetConversionValue(ADC3);
		fval = (float)(ret * (ADCRESOLUTION));
		printf ("RET=%x\tPOT 3=%fV\n\r",ret,fval);
		
		/* Start the conversion */
		 ADC_SoftwareStartConv(ADC3);
		/* Wait until conversion completion */
		while(ADC_GetFlagStatus(ADC3, ADC_FLAG_EOC) == RESET);
		/* Get the conversion value */
		ret = ADC_GetConversionValue(ADC3);
		fval = (float)(ret * (ADCRESOLUTION));
		printf ("RET=%x\tPOT 4=%fV\n\n\r",ret,fval);
 
		for(uint32_t holdsec = 0 ; holdsec <0x04FFFFF ; holdsec++ );
 
}

    This topic has been closed for replies.

    6 replies

    Tesla DeLorean
    Guru
    November 27, 2018

    Really not built to function that way.

    3 cycles is very short.

    Dual-Simult mode likely expects you to be reading the CDR not the DR, also not sure how well that plays with 1+2 and 3 on the side.

    Continuous mode is not compatible with starting individual conversions.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    aatif shaikh
    Associate III
    November 28, 2018

    I've already gone through tried "F2 SPL" examples and with the reference of "DualADC_RegSimu_DMAmode1" I've tried to implement 4 channels on same ADC, but my Array values (final value) keeps on shuffling. Also, I tried many possible things but couldn't come up with any right solution at the end.

    	#define ADCRESOLUTION			 3.3f/4095.0f
      __IO uint16_t ADCDualConvertedValue[4];
     
     
    	/*ADC Deinit*/
    	ADC_DeInit();
    	RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB 
    	| RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE
    	| RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH 
    	| RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_DMA2 , ENABLE);
    		
    		
    	/********************* ADC1 INITIALIZATION***************/
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
    	
    	
     DMA_InitTypeDef DMA_InitStructure;
     DMA_InitStructure.DMA_Channel 			= DMA_Channel_0; 
     DMA_InitStructure.DMA_Memory0BaseAddr 	= (uint32_t)&ADCDualConvertedValue;
     DMA_InitStructure.DMA_PeripheralBaseAddr 	= ((uint32_t)0x40012308); //CDR ADDRESS
     DMA_InitStructure.DMA_DIR 				= DMA_DIR_PeripheralToMemory;
     DMA_InitStructure.DMA_BufferSize 			= 4;
     DMA_InitStructure.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;
     DMA_InitStructure.DMA_MemoryInc 			= DMA_MemoryInc_Enable;
     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_Enable; 
     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);
     
     /* DMA2_Stream0 enable */
     DMA_Cmd(DMA2_Stream0, ENABLE);
     
    	GPIO_InitTypeDef 			stGPIO_InitStructure;
    	stGPIO_InitStructure.GPIO_Pin		= GPIO_Pin_0 	| GPIO_Pin_1 	| GPIO_Pin_2 	|GPIO_Pin_3		;
    	stGPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz	;
    	stGPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP		;
    	stGPIO_InitStructure.GPIO_Mode 		= GPIO_Mode_AN		;
    	stGPIO_InitStructure.GPIO_PuPd 		= GPIO_PuPd_NOPULL	;
    	GPIO_Init(GPIOC, &stGPIO_InitStructure);
     
     
    	ADC_CommonInitTypeDef ADC_CommonInitStructure;
    	ADC_CommonInitStructure.ADC_Mode 				= ADC_DualMode_RegSimult;
    	ADC_CommonInitStructure.ADC_Prescaler 			= ADC_Prescaler_Div2;
    	ADC_CommonInitStructure.ADC_DMAAccessMode 		= ADC_DMAAccessMode_1;
    	ADC_CommonInitStructure.ADC_TwoSamplingDelay 	= ADC_TwoSamplingDelay_5Cycles;
    	ADC_CommonInit(&ADC_CommonInitStructure);
     
     
    	ADC_InitTypeDef ADC_InitStructure;
    	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 		= 2;
    	ADC_Init(ADC1, &ADC_InitStructure);
    	ADC_Init(ADC2, &ADC_InitStructure);
    	ADC_Init(ADC3, &ADC_InitStructure);
     
    	/* Configure channel */
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
     
    	/* Configure channel */
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_3Cycles);
     
    	/* Configure channel */
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_3Cycles);	
    		
    	/* Configure channel */
    	ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_3Cycles);
     
    	/* 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);
     
    	/* Start ADC1 Software Conversion */
    	ADC_SoftwareStartConv(ADC1);
    	while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
     
    while(1)
    {
    		for(uint8_t ucrp = 0 ; ucrp < 4 ; ucrp++ )
    		printf("ADCDualConvertedValue[%d]=%f\n\r",ucrp,(float)(ADCDualConvertedValue[ucrp] * (ADCRESOLUTION)));
    		printf("\n\r");
    		for(uint32_t holdsec = 0 ; holdsec <0x04FFFFF ; holdsec++ );
    }

    Uwe Bonnes
    Chief
    November 28, 2018

    When starting conversions manually, use the standard and the injected channels. When conversion has finished, results are available in their appropriate registers.

    aatif shaikh
    Associate III
    November 28, 2018

    can you please provide an example or share a link?

    Tesla DeLorean
    Guru
    November 28, 2018

    Look under the F2 SPL Examples trees, of those for the F4 SPL which are trivially ported.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..