cancel
Showing results for 
Search instead for 
Did you mean: 

STM32C092 ADC channel 0 affecting reading of channel 1

Noni95
Associate

Post edited by ST moderator to be inline with the community rules especially with the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code

In STM32C092 board, when I configured in ioc file for ADC, with scan conversion mode and:
- enable analog channel 0 only, it is able to measure the analog channel 0 correctly.
- enable analog channel 1 only, it is unable to measure the analog channel 1 correctly.
- enable analog channels 0 & 1, it is able to measure the analog channel 0 correctly but channel 1 is mirroring the value of channel 0, instead of giving an independent value on changing voltages.

I tried:
- ranking ADC sequence manually, since in ioc file, it doesn't give options for ranking.
- verified the GPIO settings for analog function.
- increased sampling time for channel 1.
- gave sampling time for channel0 as 1.5 cycles and for channel1 as 160.5 cycles.


Am I doing something wrong here?

The IOC default code generation is as below:

static void MX_ADC1_Init(void)

{

ADC_ChannelConfTypeDef sConfig = {0};



hadc1.Instance = ADC1;

hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;

hadc1.Init.Resolution = ADC_RESOLUTION_10B;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.ScanConvMode = ADC_SCAN_SEQ_FIXED;

hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

hadc1.Init.LowPowerAutoWait = DISABLE;

hadc1.Init.LowPowerAutoPowerOff = DISABLE;

hadc1.Init.ContinuousConvMode = DISABLE;

hadc1.Init.NbrOfConversion = 1;

hadc1.Init.DiscontinuousConvMode = DISABLE;

hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

hadc1.Init.DMAContinuousRequests = DISABLE;

hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;

hadc1.Init.OversamplingMode = DISABLE;

hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;

if (HAL_ADC_Init(&hadc1) != HAL_OK)

{

Error_Handler();

}



sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

{

Error_Handler();

}



sConfig.Channel = ADC_CHANNEL_1;

if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

{

Error_Handler();

}

}

 

In this code I changed the number of conversions to 2 manually (since in ioc, provision wasn't there)

and also tried making different functions to set rank and start reading adc each time.

4 REPLIES 4
waclawek.jan
Super User

> enable analog channel 1 only, it is unable to measure the analog channel 1 correctly.

How "unable"?

What are the signal sources? Isn't channel 1 source's impedance too high?

> hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_1CYCLE_5;

Try increasing substantially.

JW

- Unable in the sense it reads value like 0.00118... 
- So, the circuit is like below:

Noni95_0-1760432241311.png

If I increase WALL_IN voltage (connected to analog channel 0) to a value say 12V or decrease the value to 8V, the VCC_3V3 (connected to the analog channel 1) should not be affected. But in my case, it is increasing to 3.2V or decreasing to 2.8V corresponding to the WALL_IN voltage change. I checked in the hardware at pin 8, it remains 3.3V irrespective of WALL_IN voltage levels, but in software, it is mirroring the WALL_IN voltage (raw adc value is same for both channel 0 and channel 1). 

- I gave one channel a sampling time of 1.5 and another as 160.5, but still no changes in the behavior.

 

The ADC is not designed for high impedance signal sources. Read the following application note: AN2834 

What can help is capacitors on the outputs the voltage dividers to buffer the signal voltage while the sampling capacitor is charged. And increase the sampling time significantly. If it fully charges each time the individual measurements are more accurate and cross talk should be lower too.

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.
Saket_Om
ST Employee

Hello @Noni95 

When configuring the ADC to read multiple channels, it’s essential to set the NbrOfConversion parameter to match the number of channels you intend to scan (for example, set it to 2 if you are using channels 0 and 1). Additionally, each channel must be assigned a unique rank in the conversion sequence—this is done by setting the Rank field in the ADC_ChannelConfTypeDef structure to 1 for the first channel, 2 for the second.

Please refer to the snipped code below:

hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DiscontinuousConvMode = ENABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
  hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
  hadc1.Init.OversamplingMode = DISABLE;
  hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_VREFINT;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = ADC_REGULAR_RANK_3;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

 Also, you can refer to the example ADC_MultiChannelSingleConversion in STM32CubeC0 package.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om