cancel
Showing results for 
Search instead for 
Did you mean: 

Random behaviour while using ADC on STM32f030cc

aatif shaikh
Associate III

Hello.

I'm using STM32f030CC in which we have to use 2 ADC channels.

Following is the Initialization part.

  ADC_InitTypeDef stADC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB , ENABLE);
	
	
	 /********************* GPIO INITIALIZATION***************/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure); 
  /********************* ADC1 INITIALIZATION***************/
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  /*ADC Deinit*/
  ADC_DeInit(ADC1);
 
  /*ADC Structure Initialization*/
  ADC_StructInit(&stADC_InitStructure);
 
  stADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  stADC_InitStructure.ADC_ContinuousConvMode = DISABLE;;
	stADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  stADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	stADC_InitStructure.ADC_ScanDirection=ADC_ScanDirection_Upward;
  ADC_Init(ADC1, &stADC_InitStructure);
 
  
  /* Enable the ADC peripheral */
  ADC_Cmd(ADC1, ENABLE);    
	
  
  /* Wait the ADRDY flag */
  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); 
  //while(ADC_GetCalibrationStatus(ADC1) == SET);

Now in the phantom loop we're continuously sampling the ADC channels sequentially as follows.

if(uiSamplingCount <= NO_OF_SAMPLES)
{
    val1 = fnA();
    val2 = fnB();
  uiSamplingCount++;
}
else
{ 
    uiSamplingCount=0;
   /* Averaging the values along with calibration */
    /* Print the values */
}

Definition for the above functions are as follows:

void fnA(void)
{
  /* Configure channel   */
  ADC_ChannelConfig(ADC1, ADC_Channel_9, ADC_SampleTime_55_5Cycles);
 
  /* Start the conversion   */
  ADC_StartOfConversion(ADC1);
 
  /* Wait until conversion completion   */
  while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
 
  /* Get the conversion value   */
  return ADC_GetConversionValue(ADC1);
}
void fnB(void)
{
  /* Configure channel   */
  ADC_ChannelConfig(ADC1, ADC_Channel_8, ADC_SampleTime_55_5Cycles);
 
  /* Start the conversion   */
  ADC_StartOfConversion(ADC1);
 
  /* Wait until conversion completion   */
  while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
 
  /* Get the conversion value   */
  return ADC_GetConversionValue(ADC1);
}

Now the issue is we're getting offset values when we use the above sequence.

Second test case:

We're reading only individual channel value and printing the same.

Output is proper.

Third test case:

fnB() is executed first and then fnA() ie Channel 8 first and then Channel 9.

In this case after 5 to 6 loops it stats giving proper values.

Fourth test case:

At a time we're either taking 1000 samples from Channel 8 or 1000 samples from Channel 9 with a delay of 4 secs in between them.

My question is, Is there a dependency between the channels we're using ?

Is there an issue of some settling time in ADC so some error in the sequence that we're missing?

Regards,

Aatif.

@Community member​ 

@Community member​ 

@Community member​ 

@Pavel A.​ 

@henry.dick​ 

8 REPLIES 8
AvaTar
Lead

I don't understand why you initialize the ADC each time before taking a sample. This is waste of time and code space.

Ideally, you configure two channels at once including the calibration, and then trigger + read in a loop.

> My question is, Is there a dependency between the channels we're using ?

This depends.

The sampling time must correlate to the ADC input circuitry. In other words, the input must be able to fully charge/discharge the S&H capacitor in the configured sample time. Otherwise, you will experience a "bleeding" effect, i.e. channel values depend on the value (S&H charge) of the previous channel.

So, if there is any dependency, it is in your interface hardware and/or ADC configuration.

Can we please stop with this habit of calling out forum members in initial posts.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
droid nk
Associate II

@Community member​ I guess this is done maybe because of the fact that the reply rate on ST's forum is less compared to other forums. Maybe. :)

droid nk
Associate II

@Community member​ 

>I don't understand why you initialize the ADC each time before taking a sample.

I guess the initialization is done only once. By initialization did you mean this:

ADC_ChannelConfig(ADC1, ADC_Channel_9, ADC_SampleTime_55_5Cycles);

If providing support paid better I might care more?

I review things here, it's not necessary to flag posts

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

I have really trouble finding posts I viewed and participated hours or days ago.

The sorting criteria of the forum's "Latest" list is somehow a mystery, and there is no personalized view.

Up to now, I would not say the forum platform changed for the better.

> I guess the initialization is done only once. By initialization did you mean this: ...

Even if you call the fnA() and fnB() function only once, one of them is basically redundant.

You can configure the two pins and two channels at once.

aatif shaikh
Associate III

Hello.

But if we don't write ADC_ChannelConfig(ADC1, ADC_Channel_8, ADC_SampleTime_55_5Cycles); and

ADC_ChannelConfig(ADC1, ADC_Channel_9, ADC_SampleTime_55_5Cycles); every time how can we known the return value after conversion is of which channel?

Regards,

Aatif.

AvaTar
Lead

I highly suggest to read the (whole) ADC section of the Reference Manual. It will answer your questions.