PWM Output: Timer Configuration, Resolution
Learn PWM timer configuration: calculate prescaler and ARR values, understand resolution trade-offs, and update duty cycle without glitches.

Contents & prerequisites
Prerequisites
PWM Fundamentals on Microcontroller Timers
What is PWM and why timers generate it
Pulse-width modulation encodes an analog-equivalent value — a motor speed, an LED brightness, an audio sample — as the duty cycle of a fixed-frequency digital square wave. The average voltage seen by a downstream filter or load is proportional to the fraction of time the signal spends high. Timers generate PWM because they already contain the two pieces of hardware the job needs: a free-running counter clocked from a known source, and comparison logic that can flip an output pin the instant the counter matches a programmed value. No CPU cycles are spent toggling the pin; the silicon does it autonomously, cycle after cycle, while the core is free to do other work.
Duty cycle, frequency, and period relationship
Every PWM channel is built from three numbers: the timer clock frequency, a reload value that sets the period, and a compare value that sets the on-time within that period. Frequency is the inverse of period. Duty cycle is the ratio of compare value to reload value. Change the reload value and you change frequency; change the compare value and you change duty cycle without touching frequency. Mixing these two actions up — adjusting the reload register to "tune the brightness" — is a common source of confusion for engineers new to timer PWM.
PWM modes: edge-aligned vs. center-aligned
In edge-aligned mode, the counter runs in one direction (typically up) and the output edge of interest always lands at the same end of the period. This is the simplest mode and is adequate for most LED, fan, and simple motor-driver applications. Center-aligned mode runs the counter up and then back down, so the pulse is centered in the period. This matters in power electronics — particularly multi-phase motor control and bridge topologies — because center alignment reduces the number of simultaneous edge transitions across channels, lowering EMI and reducing current ripple when multiple PWM outputs drive a single power stage. If your application is audio or simple on/off power control, edge-aligned is simpler and sufficient; if you're driving an H-bridge or managing switching losses in a converter, check whether your timer supports center-aligned counting before committing to a topology.
Timer Peripheral Block Selection
Timer types: general-purpose, advanced, basic timers
Most MCU families expose three tiers of timer. Basic timers are little more than a counter with an interrupt on overflow — no compare channels, no PWM output, often used only to trigger a DAC or ADC at a fixed rate. General-purpose timers add multiple capture/compare channels and can drive PWM outputs directly. Advanced-control timers add complementary outputs, programmable dead-time insertion, and break inputs for fault shutdown — features aimed squarely at motor control and switching power supplies. Picking the wrong tier means discovering mid-project that your timer has no complementary output pair and no dead-time unit, forcing a board respin.
Clock source and prescaler selection
Each timer is fed from a clock tree node — often the APB bus clock, sometimes multiplied by an internal factor before reaching the timer. That raw clock is almost always too fast to use directly as the counting rate for a useful PWM period, so a prescaler divides it down. The prescaler is a free divider: it does not cost you resolution the way a large reload value interacts with it, but it does set the granularity of every subsequent calculation. Check the reference manual for your specific part to confirm what multiplier, if any, sits between the bus clock and the timer input — this value is not something to assume from memory.
Matching timer capabilities to PWM requirements
Before writing a line of code, write down four numbers: desired PWM frequency, desired resolution in bits (or duty-cycle steps), number of channels needed, and whether complementary/dead-time output is required. These four numbers determine which timer peripheral you can use and, as shown below, whether your clock tree can even support the combination.
Resolution: Bit-Depth and Frequency Trade-offs
ARR (auto-reload register) and resolution bits
The auto-reload register (ARR) sets the counter's top value before it wraps or reverses. The number of distinct duty-cycle steps available equals ARR + 1. If ARR = 999, you have 1000 steps — just under 10 bits of resolution. The CCR value that controls on-time can range from 0 to ARR, giving you exactly that many discrete duty-cycle positions.
Maximum achievable frequency vs. step granularity
PWM frequency = timer_clock / (prescaler + 1) / (ARR + 1). For a fixed timer clock, raising frequency forces ARR down, and a smaller ARR means fewer duty-cycle steps. This is the central trade-off of PWM configuration: frequency and resolution are purchased from the same budget — the timer clock rate — and you cannot have an arbitrarily high value of both.
Calculating effective resolution from clock and prescaler
Worked example: timer clock after the prescaler is 10 MHz, and the target PWM frequency is 20 kHz.
ARR + 1 = timer_clock / f_pwm = 10,000,000 / 20,000 = 500
ARR = 499
That gives 500 steps, or about 8.97 bits of resolution (log2(500) ≈ 8.97). If the application needs true 10-bit resolution (1024 steps) at 20 kHz, the required timer clock becomes:
timer_clock = f_pwm * steps = 20,000 * 1024 = 20.48 MHz
So you'd select a prescaler that gets the timer input as close to 20.48 MHz as the source clock allows, then fine-tune ARR to hit the exact frequency, accepting a small resolution error if the division isn't exact.
Resolution loss at extreme frequencies
This arithmetic explains a symptom many engineers hit without understanding why: raising PWM frequency to get past audible range or to shrink an output filter causes duty-cycle steps to become visibly coarse — an LED dimmer that was smooth at 1 kHz becomes steppy at 100 kHz, because ARR dropped from the thousands into the tens. The fix is either a faster timer clock (different prescaler, different clock tree tap, or a timer fed from a PLL output) or accepting fewer effective bits at high frequency.
Configuring Capture/Compare Registers
CCR (capture/compare register) for duty cycle control
The CCR holds the compare value; hardware compares it against the live counter every clock tick and toggles the output pin at the match (and again at reload, in edge-aligned mode). Duty cycle = CCR / (ARR + 1).
Output polarity configuration
Most timer PWM channels let you invert the output polarity in hardware — pin goes low at the compare match instead of high. This saves an external inverter stage and matters when driving active-low gate drivers or N-channel low-side switches where the "off" state must be the power-up default.
Dead-time insertion for complementary PWM outputs
Advanced timers generate a complementary pair of outputs (high-side/low-side) from a single compare value, with a programmable dead-time gap inserted between the two edges so both switches are never on simultaneously. Dead time is specified in timer clock cycles, not percent, so its actual duration in nanoseconds depends on your prescaler — recalculate it whenever you change the clock configuration.
Register Setup and Code Implementation
Prescaler and ARR calculation workflow
The repeatable workflow: fix timer input clock → choose target frequency → compute ARR → check resulting resolution against requirements → adjust prescaler if resolution is insufficient → compute CCR from desired duty cycle.
CCR value computation from desired duty cycle
CCR = (uint16_t)((duty_percent / 100.0f) * (ARR + 1));
Guard against duty_percent reaching exactly 100% if your hardware's compare-at-ARR behavior differs from compare-below-ARR — check the timer's edge behavior at the boundary in the reference manual.
Enabling timer outputs and overflow interrupts
Bringing a channel up requires, at minimum, configuring the channel's output mode, enabling the channel output enable bit, enabling the timer counter itself, and — if a hardware output enable pin exists on advanced timers — asserting the main output enable separately from the channel enable. An overflow (update) interrupt is optional but useful for synchronizing duty-cycle changes, discussed next.
Runtime duty cycle updates and frequency changes
Writing directly to CCR while the timer is running is safe on most architectures because of shadow register buffering: the write lands in a buffer, and hardware transfers it into the active compare register only at the next update event (overflow or counter reset), never mid-period. This is what prevents a torn or glitched pulse when you change duty cycle on the fly. Frequency changes via ARR benefit from the same shadow mechanism if the timer's auto-reload preload is enabled — confirm this bit is set, otherwise an ARR write can take effect immediately and produce one truncated or stretched period.
Register access at this level is usually done through vendor header structs rather than raw address arithmetic; see Register-Level Peripheral Access via CMSIS for the mechanics, and Bit-Field Struct for Register Mapping for how the CCR and ARR fields map onto memory-mapped struct members instead of magic offsets.
Practical Considerations: Stability and Tuning
Jitter sources and mitigation
Jitter in PWM timing usually traces to one of three causes: an unstable or drifting clock source feeding the timer, interrupt-driven CCR updates that land inconsistently relative to the update event, or a shared timer clock being gated by another peripheral's power state. Updating CCR directly in a tight loop without regard to the update event, rather than relying on the shadow buffer, is a frequent self-inflicted cause.
Output glitch prevention during reconfigurations
Never disable and re-enable the channel output to change polarity or mode while the timer is free-running and driving a load — the pin can float or glitch during the transition. Stop the timer, reconfigure, then restart synchronized to a known edge, or use the hardware's break/main-output-enable feature if available to force a safe idle state during reconfiguration.
PWM frequency selection for power electronics and audio
Power converters typically run tens to a few hundred kHz, bounded above by switching losses in the power device and below by inductor/capacitor size. Audio PWM (as a crude DAC) needs to sit above 20 kHz to leave the audible band, which — per the resolution math above — often forces a trade against bit depth unless the timer clock is pushed high via a PLL.
Debugging resolution and timing issues
An oscilloscope or logic analyzer on the actual pin is non-negotiable before trusting any PWM calculation. Confirm measured frequency and the smallest observable duty-cycle step against your computed ARR and CCR values; a mismatch usually means the assumed timer clock (after prescaler and any internal multiplier) was wrong.
Common Pitfalls and Best Practices
Prescaler underflow and aliasing effects
Writing a prescaler value one off from intent — forgetting that the register typically holds divisor-minus-one — silently doubles or halves your frequency. Always verify against the reference manual's formula for your specific timer family rather than assuming a convention carried over from a different vendor.
Shadow register behavior and update timing
Not every timer enables preload (shadow buffering) by default. If ARR or CCR preload is disabled, writes take effect immediately on the next counter tick rather than at the update event, which can produce a single malformed pulse during a live frequency or duty-cycle change. Enable preload explicitly whenever runtime updates are expected.
Clock tree dependencies and disabled peripherals
A timer with its clock gate disabled in the RCC/clock-control block will accept register writes silently and do nothing — a classic first-bring-up failure that looks like a dead pin but is actually a missing clock enable. Confirm the peripheral clock enable bit before debugging anything downstream.
Testing PWM accuracy on real hardware
Simulation and datasheet arithmetic get you close; only a scope measurement confirms the actual prescaler, ARR, and CCR values produce the frequency and duty cycle the math predicted, across the voltage and temperature range the product will see. Keep the configuration code centralized — using Static, Inline, and Extern Linkage to scope timer-setup helpers to the module that owns the peripheral — so that recalculating these values after a clock-tree change touches one place, not every call site.
Learning
Sign in to track your progress.
Evidence
Public projects engineers linked to PWM Output: Timer Configuration, Resolution.
No engineer has linked a project to this topic yet. Built something that proves it? Add the project and tag it with embedded-firmware-pwm-output-timer-configuration-resolution — it then shows here and on your public profile.
