UNIT 08 · LESSON 2 OF 6

Counters, Prescalers, and Timer Periods

How do you get from a clock to exactly the period you want?

INTERACTIVEChoosing prescaler and auto-reload
The prescaler and auto-reload values that give the wanted timer ratef_clk84 MHzPSC1 → ticks at 42 MHzARR41 999 → 42 000 ticks per periodupdate rate1 kHzerrorexactf = 84 MHz / ((1 + 1) × (41 999 + 1)) = 1 kHzExact. A compare or PWM on this timer has 42 000 steps per period.
The prescaler and auto-reload values that give the wanted timer ratef_clk84 MHzPSC1 → ticks at 42 MHzARR41 999 → 42 000 ticks per periodupdate rate1 kHzerrorexactf = 84 MHz / ((1 + 1) × (41 999 + 1)) = 1 kHzExact. A compare or PWM on this timer has 42 000steps per period.

Try this

Timer input clock
Wanted update rate
Counter width
PSC 1, ARR 41999: 1 kHz (exact).

A timer divides its input clock twice: the prescaler turns f_clk into counter ticks at f_clk/(PSC + 1), and the counter wraps after ARR + 1 ticks, giving update events at f_clk/((PSC + 1)(ARR + 1)). The “+1”s are as in ST’s STM32F4 examples (Prescaler = TIMCLK/counter clock − 1, ARR = counter clock/output clock − 1). The search keeps ARR large, since ARR + 1 is also the resolution of a PWM or compare on this timer.

What you will be able to do
  • Compute a timer’s update rate from its input clock, prescaler and auto-reload value, including the +1 terms.
  • Choose prescaler and auto-reload values for a target rate and report the error.
  • Explain the trade-off between counter range and resolution when choosing the prescaler.
  • Find a timer’s actual input clock from the clock tree, including bus-prescaler effects.
  • Explain shadow (preload) registers and why a new period takes effect at the next update event.
Before you start
  • Clock trees and dividers (lesson 1).
  • Unsigned counters and wrap-around (unit 2, lesson 2).
Steps in this lesson
  1. Prescaler, counter, auto-reload
  2. Choosing the two values
  3. Know the timer’s real clock
  4. Changing the period while running
  5. Worked example: a 1 ms tick at 84 MHz
  6. Common misconceptions

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:

  1. The prescaler divides the timer’s input clock: the counter advances once every PSC + 1 input cycles.
  2. The counter counts 0, 1, …, ARR and then returns to 0: ARR + 1 states per period.
  3. At each return to 0 the timer raises an update event: an interrupt, a DMA request, a trigger for another block.
fupdate=fclk(PSC+1)(ARR+1)f_{\text{update}} = \frac{f_{\text{clk}}}{(\text{PSC} + 1)(\text{ARR} + 1)}
INTERACTIVEInside the counter
The counter value stepping at the prescaled rate and wrapping at ARRARR 50red: update eventsinput clock cycles(PSC + 1) × (ARR + 1) = 2 × 6 = 12 input cycles per update. A counter that counts0…ARR has ARR + 1 states, which is where the “+1” comes from.
The counter value stepping at the prescaled rate and wrapping at ARRARR 50red: update eventsinput clock cycles(PSC + 1) × (ARR + 1) = 2 × 6 = 12 input cycles perupdate. A counter that counts 0…ARR has ARR + 1states, which is where the “+1” comes from.
PSC 1, ARR 5: an update every 12 input cycles.

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.

PSC=84 MHz1 MHz−1=83,\text{PSC} = \frac{84\ \text{MHz}}{1\ \text{MHz}} - 1 = 83, ARR=1 MHz1 kHz−1=999\text{ARR} = \frac{1\ \text{MHz}}{1\ \text{kHz}} - 1 = 999

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)
  1. 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”
  2. 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
  3. 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”