Electronics Design AU
STM32

How Do You Configure the STM32 ADC?

Last updated 5 July 2026 · 9 min read

Direct Answer

The STM32 ADC is configured around channels, conversion modes, and sampling time. Channels are grouped into a Regular sequence (the normal, general-purpose conversion group) and an optional Injected sequence (a higher-priority group that can interrupt a running regular conversion, typically used for control-loop feedback that can't wait). Conversion mode is set independently: Single converts once and stops; Continuous restarts automatically after each conversion; Scan mode converts a sequence of multiple channels in one pass. Sampling time (set per channel) must be long enough for the ADC's internal sample-and-hold capacitor to fully charge from the source impedance — too short a sampling time is the most common cause of noisy or inaccurate readings, not a hardware fault. Internal channels (VREFINT, VBAT, and the internal temperature sensor) share the same ADC hardware and are enabled the same way as external pins. Most STM32 ADCs also support hardware oversampling and require a one-time self-calibration (HAL_ADCEx_Calibration_Start()) before first use to compensate for internal offset.

Detailed Explanation

The STM32 ADC is one of the most heavily used peripherals in embedded product designs — reading sensors, battery voltage, potentiometers, and analog feedback signals — but its configuration surface (channel groups, conversion modes, sampling time, calibration, oversampling) is easy to get partially wrong in a way that still compiles and still produces numbers, just noisy or inaccurate ones. This page covers how to configure the ADC correctly; for what an ADC fundamentally is and how resolution, sampling rate, and quantisation work in general, see what is an ADC? For streaming ADC results via DMA rather than polling or interrupt-per-sample, see STM32 HAL DMA configuration, which covers the Circular-mode ADC pattern in detail.

Regular vs Injected Channel Groups

STM32 ADCs organise channels into two independent conversion groups:

  • Regular group — the general-purpose conversion sequence. Most applications use only this group. A Regular sequence can contain up to 16 channels (device-dependent), converted in the configured order, either once (Single mode), continuously (Continuous mode), or triggered by an external event (timer, GPIO).
  • Injected group — a separate, higher-priority sequence of up to 4 channels that can interrupt an in-progress Regular conversion, complete its own sequence, and then return control to the Regular group. Injected conversions exist for timing-critical measurements — most commonly, sampling motor phase current at a precise point in a PWM cycle for a current control loop, where the sampling instant itself must be synchronised to the PWM timer rather than left to whenever the Regular sequence happens to get to that channel.

If nothing in the application has a hard timing requirement like this, use only the Regular group — it's simpler to reason about and sufficient for the vast majority of sensor-reading and monitoring applications.

Conversion Modes: Single, Continuous, and Scan

Three settings, configured independently, determine how conversions proceed:

  • Single conversion mode — the ADC converts once when triggered (software or hardware trigger) and stops. Used for on-demand, infrequent readings (a button-press-triggered battery check, for example).
  • Continuous conversion mode — after completing a conversion, the ADC automatically starts the next one without a new trigger. Used for streaming acquisition, typically paired with DMA (see below) so the CPU doesn't have to service every conversion.
  • Scan mode — converts a sequence of multiple channels in a single pass (one trigger converts channel 1, then channel 2, then channel 3, and so on through the configured Regular sequence), rather than needing a separate trigger per channel. Scan mode combines with Continuous mode to continuously cycle through a fixed set of channels — the standard configuration for reading several sensors on one ADC.

Sampling Time: The Most Common Source of Bad Readings

Sampling time is a per-channel setting specifying how many ADC clock cycles the sample-and-hold circuit is given to charge from the input signal before the conversion itself begins. It is the setting most responsible for real-world ADC accuracy problems, because CubeMX's default (the shortest available sampling time on most families) is tuned for a low-impedance source, not a typical few-kΩ sensor or potentiometer source.

The minimum required sampling time is a function of source impedance and the ADC's internal sample-and-hold capacitor:

t_SMPL(min) ≥ (R_source + R_ADC) × C_ADC × ln(2^(N+1))

Where R_ADC and C_ADC are the ADC's internal input resistance and sampling capacitance (typically a few kΩ and a few pF — check the specific STM32 series' datasheet electrical characteristics table), and N is the resolution in bits. A higher source impedance requires a longer sampling time; a source buffered through a low-impedance op-amp output can safely use the shortest sampling time setting.

Symptoms of too-short sampling time are typically inconsistent, bouncing readings on a stable DC input — not a fixed offset — because the sample-and-hold capacitor doesn't fully settle before conversion, and the result is partly the current signal and partly a residue of the previous conversion. For a fully worked numeric example of this calculation, including how a shared-rail VDDA and PCB layout compound the same symptom, see the forum discussion STM32 ADC readings bouncing ±50 LSB — CubeMX default sampling time the culprit? The same root cause and fix apply to Nordic's SAADC peripheral under the name "acquisition time" rather than "sampling time" — see how do you configure the nRF52 SAADC? if you're working across both platforms.

Internal Channels: VREFINT, VBAT, and Temperature Sensor

Most STM32 ADCs expose three internal signals through the same channel-selection mechanism used for external pins:

  • VREFINT — an internal, factory-calibrated reference voltage. Because its calibrated value is stored at a fixed address in system memory, reading VREFINT alongside an external channel lets firmware calculate the actual VDDA supply voltage even when VDDA isn't tightly regulated — useful for battery-powered designs where the analog supply sags with battery voltage.
  • VBAT — a scaled-down measurement of the VBAT backup domain supply (typically divided by a fixed internal ratio, commonly 3, since VBAT can exceed the ADC's normal input range). Used to monitor a coin-cell backup battery's health without a dedicated external divider.
  • Internal temperature sensor — a low-accuracy (typically several degrees Celsius) on-die temperature sensor, useful for coarse thermal monitoring or temperature-compensating other internal measurements, but not a substitute for a dedicated external temperature sensor where measurement accuracy matters — see how to interface a digital temperature sensor for accurate external alternatives.

These internal channels must be explicitly enabled (an internal switch connects them to the ADC input mux, and each draws a small additional current while active) — in CubeMX this is a checkbox per channel in the ADC configuration; in raw HAL/register terms it's a bit in the ADC common control register (ADC_CCR).

Calibration

STM32 ADCs have a small, chip-to-chip-variable internal offset and gain error. HAL_ADCEx_Calibration_Start() runs a built-in self-calibration sequence that measures this offset and stores a correction factor applied to subsequent conversions. Calibration should run once at startup, after the ADC clock is stable and before starting any conversions — running it while conversions are in progress, or skipping it, leaves an avoidable (if usually small) DC offset in every reading.

Oversampling

Many STM32 series (G0, G4, L4+, H7, and others) include hardware oversampling: the ADC averages a configurable number of samples (commonly 2× to 1024×, family-dependent) and right-shifts the accumulated result, trading conversion rate for effective resolution and noise reduction without any firmware averaging loop. Oversampling is a genuine noise-reduction tool, but it doesn't compensate for a fundamentally undersized sampling time or a poorly decoupled analog supply — fix those first, then use oversampling to improve on an already-correct baseline. See the forum discussion above for a worked example of the improvement oversampling provides once the underlying sampling-time and decoupling issues are fixed.

Streaming ADC Results with DMA

For Continuous+Scan mode acquisition of one or more channels at a sustained rate, pair the ADC with Circular-mode DMA so results are written directly into a memory buffer without CPU intervention per sample. See STM32 HAL DMA configuration for the specific HAL_ADC_Start_DMA() pattern, buffer sizing, and the STM32H7/F7 D-cache coherency requirement that applies to any DMA-filled buffer on those series.

Design Considerations

  • Match sampling time to actual source impedance, not the CubeMX default. Calculate the minimum sampling time from the real source impedance (potentiometer resistance, sensor output impedance, or the value after any series resistor) rather than accepting the shortest available setting. A higher-impedance source needs meaningfully more sampling time; buffering the source through an op-amp voltage follower first allows the shortest sampling time setting regardless of the original source impedance.
  • Decouple VDDA independently from VDD, with a bulk ceramic (commonly around 1 µF) plus a smaller ceramic (commonly 10–100 nF) placed close to the VDDA pin. A shared, undecoupled analog supply lets digital switching noise couple directly into every conversion.
  • Add a series resistor before any ADC input filter capacitor, not just a capacitor to ground alone — a capacitor without a preceding series resistor doesn't form a low-pass filter against noise on the input trace; it only changes the effective source impedance the ADC sees. See sensor signal conditioning basics for the general anti-aliasing filter design approach.
  • Use Injected channels only when there's a genuine hard-timing requirement. Reaching for Injected conversions by default adds configuration complexity (interrupt priority interactions with the Regular sequence) that most applications don't need — reserve them for control-loop feedback that must be sampled at a precise point relative to a PWM or timer event.
  • Run calibration once at startup, before the first conversion, not on every wake from a low-power mode unless the specific low-power mode's datasheet entry says the calibration value is lost — check the applicable STM32 low-power modes entry for whether ADC calibration state survives the mode used.
  • STM32 firmware built around correct ADC configuration — sampling time matched to source impedance, proper analog supply decoupling, and DMA-based acquisition — avoids the class of noisy-reading field issues that are expensive to diagnose after a product has shipped. Zeus Design's embedded firmware team builds STM32 signal-acquisition firmware with this level of attention from the start.

Common Mistakes

  • Accepting CubeMX's default (minimum) sampling time without calculating whether it's adequate for the actual source impedance. This is the single most common cause of unexplained ADC noise on STM32 designs — see the Design Considerations above and the linked forum thread for a fully worked example.
  • Leaving VDDA on the same undecoupled net as the digital supply. Digital switching noise (GPIO toggles, oscillator activity, any nearby switching regulator) couples directly into the ADC reference and every conversion result.
  • Forgetting to enable the internal channel switch for VREFINT, VBAT, or the temperature sensor and then getting a fixed, implausible reading (often 0 or full-scale) rather than a "not connected" error — these channels are silent about being disabled; verify the enable bit or CubeMX checkbox explicitly.
  • Skipping ADC self-calibration, leaving a small but entirely avoidable DC offset in every reading — a single HAL call at startup removes this error class for free.
  • Using Continuous mode without DMA at a high conversion rate, forcing the CPU to service a conversion-complete interrupt for every single sample. Once the application needs a sustained multi-kHz or higher sample rate, Circular-mode DMA removes this overhead entirely — see STM32 HAL DMA configuration.

Frequently Asked Questions

What is the difference between the STM32 ADC's Regular and Injected channel groups?
The Regular group is the general-purpose conversion sequence — most applications use only this group. The Injected group is a separate, higher-priority sequence that can interrupt a Regular conversion already in progress, complete its own (typically short) sequence, and then let the Regular sequence resume. Injected channels exist for cases where a specific measurement genuinely cannot wait for the Regular sequence to finish — for example, sampling motor current at a precise point in a PWM cycle for a control loop, where jitter in the sampling instant would degrade control performance. If nothing in the application requires that hard timing guarantee, the Regular group alone is simpler and sufficient.
Why does my STM32 need ADC calibration, and when should I run it?
STM32 ADCs have a small internal offset and gain error that varies chip-to-chip and can shift with temperature and supply voltage. HAL_ADCEx_Calibration_Start() runs a built-in self-calibration routine that measures and compensates for this offset before conversions begin. Run calibration once at startup, after the ADC clock and voltage reference are stable and before starting any conversions — calibrating while conversions are running, or skipping it, leaves a small but avoidable DC offset error in every reading.
Do VREFINT, VBAT, and the internal temperature sensor need special configuration?
They're read through the same ADC hardware and channel-configuration mechanism as an external pin, but must be explicitly enabled first — typically via a bit in the ADC common control register (ADC_CCR, exposed in HAL as ADC_CHANNEL_VREFINT / ADC_CHANNEL_VBAT / ADC_CHANNEL_TEMPSENSOR with a corresponding enable flag) because they draw a small amount of extra current when active and aren't needed by most applications. VREFINT is particularly useful for calculating actual VDDA when VDDA isn't tightly regulated, since the internal reference voltage is factory-calibrated and stored in a fixed memory location on most STM32 parts.

References

Related Questions

Related Forum Discussions