cancel
Showing results for 
Search instead for 
Did you mean: 

read multiple ADC channels of same ADC without DMA

aatif shaikh
Associate III

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++ );
 
}

6 REPLIES 6

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
Up vote any posts that you find helpful, it shows what's working..
Uwe Bonnes
Principal II

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

can you please provide an example or share a link?

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
Up vote any posts that you find helpful, it shows what's working..

.

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++ );
}