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.