Skip to main content
CSmit.4
Associate II
March 28, 2023
Solved

What is the required timing between ADC initialization and calibration on the STM32G0B1?

  • March 28, 2023
  • 2 replies
  • 1764 views

We are using the STM32G0B1CC and have noticed that if we call HAL_ADCEx_Calibration_Start() too soon after calling HAL_ADC_Init() that the CALFACT register comes back as 0. If we insert a substantial delay, say 20 ms between the 2 calls, CALFACT is populated with a reasonable value, and later conversions are considerably more accurate. HAL_ADCEx_Calibration_Start() in all cases returns HAL_OK. I'm trying to understand why the need for the delay:

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_12B;

 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_160CYCLES_5;  

 hadc1.Init.OversamplingMode = DISABLE;

 hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;

 if (HAL_ADC_Init(&hadc1) != HAL_OK)

 {

  Error_Handler();

 }

 HAL_Delay(20);  

  

 HAL_ADC_Stop(&hadc1);

 HAL_ADCEx_Calibration_Start(&hadc1);

This topic has been closed for replies.
Best answer by CSmit.4

Thank you Romain. I tried your suggestions, but the problem persisted. I then finally realized the issue was a power sequencing one. The signal that provides the ADC reference voltage was asserted AFTER the ADC calibration was being performed.

2 replies

RomainR.
ST Employee
March 29, 2023

Hello @CSmit.4 (Community Member)

Remove HAL_ADC_Stop(&hadc1) because the HAL_ADCEx_Calibration_Start() disable ADC.

Make sure ADC clock frequency is:

fADC <= 35MHz for Range 1.

fADC <= 16MHz for Range 2.

Also, I suggest you either to try the following example:

STM32Cube\Repository\STM32Cube_FW_G0_V1.6.1\Projects\NUCLEO-G0B1RE\Examples\ADC\ADC_MultiChannelSingleConversion

Or to apply the check below at the end of your MX_ADC1_Init() :

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_12B;
	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_160CYCLES_5; 
	hadc1.Init.OversamplingMode = DISABLE;
	hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
 
	if (HAL_ADC_Init(&hadc1) != HAL_OK)
	{
		Error_Handler();
	}
 
	if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK)
	{
		Error_Handler();
	} 
}

Best regards,

Romain,

In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'

CSmit.4
CSmit.4AuthorBest answer
Associate II
March 29, 2023

Thank you Romain. I tried your suggestions, but the problem persisted. I then finally realized the issue was a power sequencing one. The signal that provides the ADC reference voltage was asserted AFTER the ADC calibration was being performed.