Try  HackMD Logo HackMD

The Analog-to-Digital Converter (ADC) in STM32 microcontrollers requires calibration to ensure accurate measurements. Here's a detailed explanation of the calibration process:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

1. Why ADC Calibration is Necessary

  • Compensates for internal capacitor charge/discharge variations
  • Corrects offset and linearity errors
  • Improves measurement accuracy (typically ±1 LSB after calibration)
  • Required after power-up or long idle periods

2. Calibration Process Steps
2.1 Basic Calibration (All STM32 Series)

c
void ADC_Calibrate(ADC_HandleTypeDef* hadc) {
  // 1. Ensure ADC is disabled
  HAL_ADC_Stop(hadc);
  
  // 2. Start calibration
  HAL_ADCEx_Calibration_Start(hadc);
  
  // 3. Wait for completion
  while(HAL_ADCEx_Calibration_GetValue(hadc) != HAL_OK);
}

2.2 STM32H7 Specific Calibration
The H7 series has additional calibration registers:

c
void ADC_H7_Calibrate(ADC_HandleTypeDef* hadc) {
  // 1. Disable ADC
  ADC1->CR &= ~ADC_CR_ADEN;
  
  // 2. Calibrate single-ended mode
  ADC1->CR |= ADC_CR_ADCALLIN;
  ADC1->CR |= ADC_CR_ADCAL;
  while((ADC1->CR & ADC_CR_ADCAL) != 0);
  
  // 3. For differential mode (if used)
  ADC1->CR |= ADC_CR_ADCALDIF;
  ADC1->CR |= ADC_CR_ADCAL;
  while((ADC1->CR & ADC_CR_ADCAL) != 0);
}

3. Important Considerations
3.1 Timing Requirements

  • Must be performed when ADC is disabled

  • Takes ~10-100 clock cycles depending on STM32 family

  • Should be done:

    • After power-up
    • After temperature changes >10°C
    • Periodically in critical applications

3.2 Multi-ADC Systems
For STM32 devices with multiple ADCs:

  1. Calibrate each ADC separately
  2. Maintain consistent timing between calibrations
  3. Use same reference voltage for all ADCs

3.3 Voltage Reference

  • Calibration assumes stable reference voltage
  • For VREFINT (internal reference):
c
// Enable internal reference buffer (STM32H7)
HAL_SYSCFG_VREFBUF_VoltageScalingConfig(SYSCFG_VREFBUF_VOLTAGE_SCALE0);
HAL_SYSCFG_EnableVREFBUF();

4. Post-Calibration Verification

c
uint32_t Verify_Calibration() {
  // Read known voltage (e.g., internal reference)
  HAL_ADC_Start(&hadc);
  HAL_ADC_PollForConversion(&hadc, 10);
  uint32_t adcValue = HAL_ADC_GetValue(&hadc);
  
  // Compare with expected value
  const uint32_t expected = 1234; // Device-specific
  return (abs(adcValue - expected) <= 2); // Within 2 LSB
}

5. Advanced Techniques
5.1 Background Calibration (STM32L4/L5)

c
// Enable background calibration
ADC1->CFGR |= ADC_CFGR_CONT;
ADC1->CR |= ADC_CR_ADCAL;

5.2 Temperature Compensation

c
// Read temperature sensor (TS_CAL1/2 values from flash)
float Get_Temperature() {
  uint16_t *TS_CAL1 = (uint16_t*)0x1FFF75A8;
  uint16_t *TS_CAL2 = (uint16_t*)0x1FFF75CA;
  
  HAL_ADC_Start(&hadc_temp);
  uint32_t temp_raw = HAL_ADC_GetValue(&hadc_temp);
  
  return ((temp_raw - TS_CAL1) * (85.0 - 30.0)) / 
         (TS_CAL2 - TS_CAL1) + 30.0;
}

6. Troubleshooting

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

7. Recommended Practice

  1. Calibrate at startup
  2. Store calibration factors in flash/EEPROM
  3. Implement periodic recalibration in mission-critical apps
  4. Use hardware averaging (STM32G4/H7) for better noise immunity

For specific STM32 families (F4, G0, U5, etc.), check the reference manual for family-specific calibration procedures. The process is similar but may have minor register differences.