cancel
Showing results for 
Search instead for 
Did you mean: 

ADC channel 12 less accurate than the other ?

jean
Senior

Hello,

Since two year, I am experiencing an issue with the ADC_CHANNEL_12 (pin PC12) of my STM32F767. I suspect it's a hardware issue coming from the MCU.

  • a stable offset is added (randomly change each time I reboot the STM)

  • this read value (via DMA) is way less accurate than the other inputs (I also use 3 other ADC pins that are working great), look like a lot of noise is disturbing the ADC (read value randomly change +2/-2% between the "real" voltage value)

I use a proper custom PCB circuit, no noise / EMI should be added. Again, the 3 other ADC input pins (PC3, PA0, PA1) are very accurate. Also tested with an oscilloscope, the signals are very clean.

What I've tried:

  • changing ADC_RESOLUTION_12B to ADC_RESOLUTION_10B = it fixes the offset problem!
  • reducing ADC_SAMPLETIME = some values are improving a bit the accuracy problem (in fact, changing the ADC_SAMPLETIME of the other ADC inputs also change the accuracy of the PC12 ADC !)
  • Using ADC2 instead of ADC1 = does not change anything
  • Using the tips of the STM32F7 errata sheet (setting the bit SYSCFG_PMC_ADC2DC2) = does not change anything
  • Every other ADC configurations does not change anything

Maybe some of you came across this issue?

Thanks a lot for your help!

Cheers,

8 REPLIES 8
jean
Senior
void Adc::Init() 
{
	ADC_ChannelConfTypeDef sConfig;
 
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  hadc2.Init.Resolution = ADC_RESOLUTION_10B; // 10B = PC2 is not offseted anymore
  hadc2.Init.ScanConvMode = ENABLE;
  hadc2.Init.ContinuousConvMode = ENABLE;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.DataAlign = ADC_DATAALIGN_LEFT;
  hadc2.Init.NbrOfConversion = 2;
  hadc2.Init.DMAContinuousRequests = ENABLE;
  hadc2.Init.EOCSelection = DISABLE;
  HAL_ADC_Init(&hadc2);
 
  sConfig.Channel = ADC_CHANNEL_12; // PC2
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  sConfig.Offset = 0;
  HAL_ADC_ConfigChannel(&hadc2, &sConfig);
 
  sConfig.Channel = ADC_CHANNEL_13; // PC3
  sConfig.Rank = 2;
  sConfig.SamplingTime = ADC_SAMPLETIME_144CYCLES;
  HAL_ADC_ConfigChannel(&hadc2, &sConfig);
 
  if(HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&DMAvalues[0], 2) != HAL_OK) __DEBUG_BKPT();
 
 
 
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_LEFT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = DISABLE;
  HAL_ADC_Init(&hadc1);
 
  sConfig.Channel = ADC_CHANNEL_0; // PA0
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  sConfig.Offset = 0;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
 
  sConfig.Channel = ADC_CHANNEL_1; // PA1
  sConfig.Rank = 2;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
 
  if(HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&DMAvalues[2], 2) != HAL_OK) __DEBUG_BKPT();
 
  /* reduce the ADC noise ? STM32F7 errata sheet */
  //SET_BIT(PWR->CR1, PWR_CR1_ADCDC1_Pos);
  SET_BIT(SYSCFG->PMC, SYSCFG_PMC_ADC1DC2);
  SET_BIT(SYSCFG->PMC, SYSCFG_PMC_ADC2DC2);
}

Write a minimal program which does nothing just reads this one ADC channel, to memory, and observe the result with debugger.

JW

ingwmeier
Senior

you could try to change Ranks of ADC_CHANNEL_12 and ADC_CHANNEL_13 to check if anything changes..

Another thing: did you test with HAL_ADCEx_Calibration_Start if this changes anything?

jean
Senior

Hi, thanks a lot for your help!

  1. a minimal program (just the ADC values monitored with debug) = same result
  2. changing the ranks does not change anything, ADC_CHANNEL_12 (PC2) is still not accurate
  3. I also update all the HAL librairies to the most recent one, no changes
Uwe Bonnes
Principal II

Does this happen on different layouts? If you didn't test with a totally different layout:

What signal run near to PC12? Maybe there is excessive noise . Or s there perhaps any signal > VDDIO on a TTa pin?

Perhaps try to reproduce on a Nucleo or Disco board.

jean
Senior

No, indeed the next step is to test it on a new PCB, will do it in the following months!

There is no noisy or high-speed signals next to PC12 ...

Or s there perhaps any signal > VDDIO on a TTa pin?

A TTa pin is a pin that can be declared as an analog input (connected to ADC) ?

If yes, is that possible that having for example a +5V on a TTa pin (even if this pin is not declared as an analog input) can influence the ADC_CHANNEL_12 ?

> having for example a +5V on a TTa pin 

That's definitively a no-no which may damage the part, not just influence the ADC readings.

Cut the offending signal and retry with the ADC.

JW

jean
Senior

Thanks for this tip, didn't really aware of that! After double checking my design, no pins of my STM is connected to something more that 3.3V, so I guess that's not the problem.

The next step is to test ADC_CHANNEL_12 on a new design, or a demo board. But the fact that I was able to remove the ADC "random offset" of PC2 by changing ADC_RESOLUTION_12B to ADC_RESOLUTION_10B still seems like a STM32 issue for me 🙂