cancel
Showing results for 
Search instead for 
Did you mean: 

On STM32G473, why would the ADC readings be lower than the calculation says they should be?

JKarn.2
Associate

We are running the STM32G473 micro and are using an ADC channel to read the various bus voltages (3.3v, 5v, and 24v) as well as motor currents. All the ADC readings are lower than they should be, but not by the same percentage.

I am pasting some sample code that reads the 3.3v bus. Based on the circuit we are using, the math says we should be reading 408 counts, but we are reading only 349. Any thoughts on why this is, or how to correct it?

Here is the sample code:

tUINT16 Voltage3_3Reading;

tVOID main(tVOID)

{

HAL_IsrInstallHandler(ADC1_2_IRQn, AdcIrqHandler, ISR_PRIORITY_MEDIUM);

ConfigureAdc();

  ConfigureFor3_3vBus();

}

static tVOID ConfigureFor3_3vBus(tVOID)

{

  LL_ADC_REG_StopConversion(ADC2);

  LL_ADC_Disable(ADC2);

  LL_ADC_REG_SetTriggerSource(ADC2, LL_ADC_REG_TRIG_SOFTWARE);

  LL_ADC_SetChannelSamplingTime(ADC2, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_640CYCLES_5);

  LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_12);

   

  // Start the conversion

  LL_ADC_Enable(ADC2);

  // Wait for enable to be active

  tTIMER enabledTimer;

  LIB_TimerStart(&enabledTimer, 3);  // Arbitrary enabled timeout value of 3ms

  while (!LL_ADC_IsEnabled(ADC2))

  {

    ASSERT_OR_BREAK(LIB_TimerCheck(&enabledTimer) == TIMER_RUNNING);

  }

  // Start converting

  LL_ADC_REG_StartConversion(ADC2);

}

static tVOID ConfigureAdc(tVOID)

{

  // Make sure it is disabled to change ADC settings.

  LL_ADC_Disable(ADC2);

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12);

  LL_ADC_DeInit(ADC2);

  LL_ADC_CommonInitTypeDef adcCommonInitStruct;

  LL_ADC_CommonStructInit(&adcCommonInitStruct);

  adcCommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;

  adcCommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;

  adcCommonInitStruct.MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;

  adcCommonInitStruct.MultiTwoSamplingDelay = LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES;

  LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC2), &adcCommonInitStruct);

  // Configure ADC settings.

  LL_ADC_InitTypeDef adcInitStructure;

  LL_ADC_StructInit(&adcInitStructure);

  adcInitStructure.Resolution     = LL_ADC_RESOLUTION_12B;

  adcInitStructure.DataAlignment   = LL_ADC_DATA_ALIGN_RIGHT;

  adcInitStructure.LowPowerMode    = LL_ADC_LP_MODE_NONE;

  LL_ADC_Init(ADC2, &adcInitStructure);

  LL_ADC_REG_InitTypeDef adcRegInitStructure;

  LL_ADC_REG_StructInit(&adcRegInitStructure);

  adcRegInitStructure.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;

  adcRegInitStructure.ContinuousMode = LL_ADC_REG_CONV_SINGLE;

  adcRegInitStructure.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;

  LL_ADC_REG_Init(ADC2, &adcRegInitStructure);

  LL_ADC_DisableDeepPowerDown(ADC2);

  LL_ADC_EnableInternalRegulator(ADC2);

  LL_ADC_REG_SetOverrun(ADC2, LL_ADC_REG_OVR_DATA_OVERWRITTEN);

  // Calibrate ADCs

  tTIMER adcCalTimer;

  LL_ADC_StartCalibration(ADC2, LL_ADC_SINGLE_ENDED);

  LIB_TimerStart(&adcCalTimer, 5);  // Arbitrary calibration timeout value of 5ms

  while (LL_ADC_IsCalibrationOnGoing(ADC2) == 1)

  {

    ASSERT_OR_BREAK(LIB_TimerCheck(&adcCalTimer) == TIMER_RUNNING);

  }

  LL_ADC_EnableIT_EOC(ADC2);

}

static tVOID AdcIrqHandler(tVOID)

{

  if (LL_ADC_IsActiveFlag_EOC(ADC2) == TRUE)

  {

    LL_ADC_REG_StopConversion(ADC2);

    LL_ADC_Disable(ADC2);

     

    // Retrieve the data (this also clears EOC flag)

    Voltage3_3Reading = LL_ADC_REG_ReadConversionData12(ADC2);

  }

}

3 REPLIES 3
TDK
Guru

Some combination of:

  • Wrong reference voltage.
  • Unstable reference voltage.
  • Voltages aren't actually what you think they are.
  • Impedance is too high.
  • ADC is damaged.

My first two things to debug would be to ground a pin and verify that it reports 0 counts, then short a pin directly to 3.3V (assuming that's your reference) and see that it reports 4095 counts (or whatever the max is for your conversion resolution).

If you feel a post has answered your question, please click "Accept as Solution".

Also read the 'G4-specific ADC appnote.

JW

JKarn.2
Associate

Thank you all for the suggestions.

The issue was resolved by adding a 20us delay after LL_ADC_EnableInternalRegulator().