2021-09-24 01:33 PM
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);
}
}
2021-09-24 04:31 PM
Some combination of:
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).
2021-09-24 08:10 PM
Also read the 'G4-specific ADC appnote.
JW
2021-09-28 09:41 AM
Thank you all for the suggestions.
The issue was resolved by adding a 20us delay after LL_ADC_EnableInternalRegulator().