---
# System prepended metadata

title: 'STM32 ADC Calibration Process: A Complete Guide'
tags: [stm32]

---

The Analog-to-Digital Converter (ADC) in [STM32](https://www.ampheo.com/search/STM32) [microcontrollers](https://www.ampheo.com/c/microcontrollers) requires calibration to ensure accurate measurements. Here's a detailed explanation of the calibration process:
![https___dev-to-uploads.s3.amazonaws.com_uploads_articles_tvxhbiameueelr7afapn](https://hackmd.io/_uploads/BkHAeAxwll.png)

**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](https://www.onzuu.com/search/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](https://www.ampheo.com/search/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**
![企业微信截图_20250725173359](https://hackmd.io/_uploads/rJ39y0gPel.png)

**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](https://www.ampheo.com/search/STM32G4)/H7) for better noise immunity

For specific [STM32](https://www.ampheoelec.de/search/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.