Timers: exact periods and measuring time
A timer is a counter that counts clock ticks. Periodic interrupts, measuring pulse width with input capture, and encoder mode.
Basic operation
Timer input clock → divided by PSC (prescaler) → CNT increases by 1 → when it reaches ARR it returns to 0 and raises an update event
Period = (PSC + 1) × (ARR + 1) / timer clock
A 1 kHz interrupt from a 100 MHz timer: PSC = 99 (1 MHz), ARR = 999 → 1 ms
Uses
| Mode | Purpose |
|---|---|
| Update interrupt | Exact control period (1 kHz speed loop) |
| Output compare / PWM | Motors, LED brightness |
| Input capture | Pulse width and frequency measurement (servo signals, ultrasonic sensors) |
| Encoder mode | Counts position automatically from A/B signals |
| Trigger output (TRGO) | Sets the ADC sampling instant |
Measuring time with input capture
At the instant a signal edge arrives, the CNT value is stored in CCR automatically. The difference between the CCR values at the rising and falling edges is the pulse width. Unlike measuring in software, there is no jitter.
How this differs from HAL_Delay
HAL_Delay waits on SysTick and ties up the CPU. Periodic work should run from a timer interrupt or an RTOS task, so that other things can happen at the same time.
A timer is a counter
Every clock tick raises the counter by 1. When it reaches the set value (ARR), it returns to 0 and raises an update event. The prescaler (PSC) divides the clock first, so the counter counts more slowly.
counter clock = timer clock / (PSC + 1)
event period = (PSC + 1) × (ARR + 1) / timer clock
3D labRun what you have read so far→Example: a 1 ms period
With a 72 MHz timer clock
PSC = 71 → 72 MHz / 72 = 1 MHz (1 count = 1 μs)
ARR = 999 → an event every 1000 counts = 1 ms
TIM2->PSC = 71;
TIM2->ARR = 999;
TIM2->DIER |= TIM_DIER_UIE; // enable the update interrupt
TIM2->CR1 |= TIM_CR1_CEN; // start
NVIC_EnableIRQ(TIM2_IRQn);
If you forget the + 1 and write 72 to PSC and 1000 to ARR, the period becomes about 1.5% longer. For communication timing or a control period, that error cannot be ignored.
In a picture: the counter and PWM
The same timer does four different jobs depending on its settings.
| Mode | What it does | Use |
|---|---|---|
| Basic timer | Interrupt at a fixed period | System tick, control loop |
| Output compare / PWM | Compares with the counter and drives a pin | Motors, LED brightness, servos |
| Input capture | Stores the counter value at the instant a pin changes | Frequency and pulse-width measurement, Hall sensors |
| Encoder mode | Counts up and down from A/B signals | Rotational position |
The limit of 16 bits
A 16-bit timer only counts to 65535. Counting in 1 μs units, it overflows at 65.5 ms. To measure longer times, increase PSC to make the unit larger, or count the upper digits separately in the overflow interrupt and join them. When taking the difference between two input-capture times, use unsigned subtraction such as (uint16_t)(now - prev); the result is correct even if one overflow happened in between.
Problems that come up in practice
- Timer clock is twice what you expected: on many MCUs only the timer clock doubles when the bus divider is not 1. If the period comes out at half, check the clock tree.
- Changing ARR takes effect immediately and breaks a pulse: with preload enabled, the change is applied all at once at the next update.
- Interrupt flag not cleared: the handler is called again the moment it returns, and the main loop stops.