The puzzle
You need an interrupt exactly every millisecond. The timer’s clock is 84 MHz, its registers are 16 bits wide, and the datasheet offers two of them, PSC and ARR. There are thousands of combinations, and the obvious guess of 84 000 does not even fit. How do you get from a clock to exactly the period you want?
STEP 1
Prescaler, counter, auto-reload
A general-purpose timer is a counter with two dividers in front of its output:
- The prescaler divides the timer’s input clock: the counter advances once every PSC + 1 input cycles.
- The counter counts 0, 1, …, ARR and then returns to 0: ARR + 1 states per period.
- At each return to 0 the timer raises an update event: an interrupt, a DMA request, a trigger for another block.
Each input clock cycle advances the prescaler; every PSC + 1 cycles the counter advances by one; when the counter has reached ARR, the next tick returns it to 0 and raises an update event. Small numbers so that each step is visible.
The “+1”s trip everyone once: a register value of 0 divides by 1, and a counter that counts 0…999 has 1000 states. ST’s own examples write it as PSC = f_clk/f_counter − 1 and ARR = f_counter/f_update − 1.
STEP 2
Choosing the two values
The product (PSC + 1)(ARR + 1) must equal f_clk/f_update, and each factor must fit its register. For 1 kHz from 84 MHz the product is 84 000, too big for a 16-bit ARR alone, so it has to be split:
↑ This step uses the figure at the top of the page.
Many splits work; they differ in resolution. The counter advances in steps of (PSC + 1)/f_clk, and a compare or PWM on this timer can only place an edge on one of the ARR + 1 steps (lessons 4 and 6). A small prescaler and a large ARR give fine steps; a large prescaler gives a longer maximum period with coarse steps. When the ratio has no exact factorisation within the register widths, the rate is only approximate, and sometimes a different timer clock gives an exact one. Some timers have 32-bit counters (TIM2 and TIM5 on the STM32F4), which remove most of the need to prescale.
STEP 3
Know the timer’s real clock
A timer’s input clock is not always the CPU clock or even the bus clock. In ST’s STM32F4 example, the timer clock is twice the APB1 bus clock because the APB1 prescaler is not 1. On the RP2040, PWM slices count at clk_sys divided by their own 8.4 fractional divider. Read the clock tree (lesson 1) before trusting any formula.
STEP 4
Changing the period while running
Writing a new ARR in the middle of a period could leave the counter already above the new value; on an up-counting timer it then counts on to its maximum before wrapping (check your reference manual for the exact behaviour). Timers avoid this with shadow registers: with preload enabled, the value you write goes into a buffer and is copied into the active register at the next update event. On the STM32F4 this is optional for ARR (ARPE; ST’s own PWM example leaves it disabled) and always the case for the prescaler; the RP2040’s PWM wrap value is always double-buffered. With preload, changes take effect at a period boundary, never mid-period.
STEP 5
Worked example: a 1 ms tick at 84 MHz
Option A: a 1 MHz counter.
Update rate 84 MHz / (84 × 1000) = 1 kHz exactly, with the counter value reading directly in microseconds.
Option B: maximum resolution. PSC = 1, ARR = 41 999: 84 MHz / (2 × 42 000) = 1 kHz exactly, with 42 000 steps per period, 23.8 ns each. Option A is easier to read, option B places compare edges 42 times more finely.
MYTHS AND FACTS
Common misconceptions
PSC = 84 divides by 84
It divides by 85; the register holds the divisor minus one.
The timer runs at the CPU clock
It runs at its own clock from the tree, which may be a bus clock, a multiple of it, or divided.
Any rate is possible
Only f_clk divided by a product of two integers within the register ranges.
A new ARR always takes effect immediately
Without preload it does; with preload (and always on the RP2040’s PWM) it waits for the next update event.
Check yourself
Answer in your head, then open the card.
A timer clock of 16 MHz, PSC = 15, ARR = 49 999. What is the update rate?
16 MHz / (16 × 50 000) = 20 Hz.
Give PSC and ARR for 50 Hz from 84 MHz with a 1 µs counter step.
PSC = 83 (1 MHz counter), ARR = 1 MHz / 50 Hz − 1 = 19 999.
Why does a 16-bit timer at 84 MHz need a prescaler for a 1 Hz rate?
84 000 000 counts do not fit in 65 536; the prescaler must supply a factor of at least 84 000 000 / 65 536 ≈ 1282, for example PSC = 1399 and ARR = 59 999.
On a 16-bit up-counting timer, firmware writes ARR = 100 while the counter reads 500, with preload disabled. What happens?
The counter is already past the new top, so it counts on to its maximum (65 535) and wraps before the new period applies: one very long period (on a 32-bit timer, up to 2³² − 1). With preload the new value would load at the next update instead.
Sources (3)
- STMicroelectronics, STM32CubeF4, Projects/STM324xG_EVAL/Examples/TIM/TIM_PWMOutput/Src/main.c — “TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1), since APB1 prescaler is different from 1”; “Prescaler = (TIM3CLK / TIM3 counter clock) - 1”; “ARR = (TIM3 counter clock / TIM3 output clock) - 1”
- STMicroelectronics, stm32f4xx-hal-driver, Inc/stm32f4xx_hal_tim.h, and cmsis-device-f4 stm32f407xx.h — TIM_Base_InitTypeDef: Prescaler 0x0000–0xFFFF; Period “loaded into the active Auto-Reload Register at the next update event”, 0x0000–0xFFFF; AutoReloadPreload; stm32f407xx.h IS_TIM_32B_COUNTER_INSTANCE: TIM2 and TIM5 have 32-bit counters
- Raspberry Pi Ltd, pico-sdk 1.5.1, hardware_pwm/pwm.h and hardware_regs/pwm.h — each slice counts at clk_sys / DIV (an 8.4 fractional divider) up to TOP, a 16-bit wrap value, then wraps to 0; “The counter wrap value is double-buffered in hardware … a write … does not take effect until after the next time the PWM slice wraps”