Analog-to-Digital Conversion with STM32 Microcontrollers

Understanding ADC in Embedded Systems

Analog-to-Digital Converters (ADCs) serve as a critical interface between analog signals and digital systems. In STM32 microcontrollers like the STM32F103C8T6, the ADC module provides precise conversion of analog voltages into digital values, enabling digital processing of real-world signals.

  • 12-bit successive approximation ADC with 1μs conversion time
  • Input voltage range: 0-3V, output digital range: 0-4095
  • Supports 18 input channels (16 external + 2 internal)
  • Dual conversion units: Regular group and Injected group
  • Built-in analog watchdog for voltage range monitoring
  • STM32F103C8T6 offers ADC1 and ADC2 with 10 external channels

Core ADC Concepts

Key aspects of ADC operation include:

  • Successive approximation architecture for efficient conversion
  • Data alignment options (left or right) for flexible data handling
  • Conversion timing influanced by clock configuraton and sampling time
  • Calibration procedures to minimize internal capacitor errors

ADC Calibration

The STM32 ADC includes a built-in self-calibration feature that reduces errors from internal capacitor variasions. This process calculates correction codes for each capacitor, which are then applied to subsequent conversions. It is recommended to perform calibration after each power-up, with ADC disabled for at least two clock cycles before calibration begins.

Hardware Interface Implementation

Below is a refined implementation for initializing and using the ADC module in STM32F1 series microcontrollers:

#include "stm32f10x.h"

void AnalogConverter_Init(void) {
    // Clock configuration
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);  // 12MHz ADC clock

    // GPIO setup for analog input
    GPIO_InitTypeDef gpioConfig;
    gpioConfig.GPIO_Pin = GPIO_Pin_0;
    gpioConfig.GPIO_Mode = GPIO_Mode_AIN;
    gpioConfig.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpioConfig);

    // ADC configuration
    ADC_InitTypeDef adcConfig;
    adcConfig.ADC_Mode = ADC_Mode_Independent;
    adcConfig.ADC_DataAlign = ADC_DataAlign_Right;
    adcConfig.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    adcConfig.ADC_ContinuousConvMode = DISABLE;
    adcConfig.ADC_ScanConvMode = DISABLE;
    adcConfig.ADC_NbrOfChannel = 1;
    
    ADC_Init(ADC1, &adcConfig);

    // ADC calibration sequence
    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));

    // Channel configuration
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
}

uint16_t ReadAnalogValue(void) {
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}

Multi-channel ADC Implementation

For applications requiring multiple analog inputs, here's an enhanced implementation supporting dynamic channel selection:

void MultiChannelADC_Init(void) {
    // Clock configuration
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);

    // Configure multiple analog input pins
    GPIO_InitTypeDef gpioConfig;
    gpioConfig.GPIO_Mode = GPIO_Mode_AIN;
    gpioConfig.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    gpioConfig.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpioConfig);

    // ADC configuration
    ADC_InitTypeDef adcConfig;
    adcConfig.ADC_Mode = ADC_Mode_Independent;
    adcConfig.ADC_DataAlign = ADC_DataAlign_Right;
    adcConfig.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    adcConfig.ADC_ContinuousConvMode = DISABLE;
    adcConfig.ADC_ScanConvMode = DISABLE;
    adcConfig.ADC_NbrOfChannel = 1;
    
    ADC_Init(ADC1, &adcConfig);

    // Calibration
    ADC_Cmd(ADC1, ENABLE);
    ADC_ResetCalibration(ADC1);
    while (ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while (ADC_GetCalibrationStatus(ADC1));
}

uint16_t ConvertChannel(uint8_t channel) {
    ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_55Cycles5);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}

Tags: STM32 ADC Embedded Systems Analog-to-Digital Conversion Microcontroller Programming

Posted on Sun, 23 Aug 2026 16:09:41 +0000 by mwichmann4