Hardware Timers
Microcontrollers use physical hardware timers to track time independently of the CPU. A timer is essentially a register (such as TCNT1) that increments automatically on every clock cycle. When the counter reaches its maximum limit, it overflows, resets to 0, and triggers an interrupt.
Normal Mode vs. CTC Mode
- Normal Mode: The timer counts up to its maximum capacity (e.g., for a 16-bit timer) before resetting. To run a periodic task at a faster frequency, software must manually reset
TCNT1inside the ISR. This manual reset introduces latency (drifts) due to the CPU cycles spent entering the ISR, leading to inaccurate timing. - CTC Mode (Clear Timer on Compare match): The timer counts up to a custom limit register (
OCR1A). Upon matching, the hardware automatically resetsTCNT1to0in the same clock cycle and fires the compare match interrupt. This eliminates software latency drift.
Timer 1 (16-bit) Registers
To configure Timer 1 on the ATmega2560 in CTC mode, we interact with several registers:
TCNT1: The raw 16-bit counter value.OCR1A(Output Compare Register A): Holds the target match count.TCCR1B(Timer/Counter Control Register B): Configures the mode (WGM bits) and prescaler (CS bits).TIMSK1(Timer Interrupt Mask Register): Enables the compare match A interrupt (OCIE1A).TIMER1_COMPA_vect: The interrupt vector name for the compare match A ISR.
Prescaler Selection (TCCR1B CS Bits)
Since the CPU runs at 16 MHz, a 16-bit counter would match OCR1A too quickly at high frequencies. We use a prescaler (clock divisor) to slow down the timer.
| Prescaler | CS12 | CS11 | CS10 | TCCR1B Register Setting |
|---|---|---|---|---|
| No Clock (Stopped) | 0 | 0 | 0 | Timer stopped |
| 1 (None) | 0 | 0 | 1 | (1 << CS10) |
| 8 | 0 | 1 | 0 | (1 << CS11) |
| 64 | 0 | 1 | 1 | (1 << CS11) | (1 << CS10) |
| 256 | 1 | 0 | 0 | (1 << CS12) |
| 1024 | 1 | 0 | 1 | (1 << CS12) | (1 << CS10) |
CTC Threshold Calculation
To trigger a compare match interrupt at frequency , calculate OCR1A using:
Rule for LED Toggling: If the ISR toggles a pin to blink a LED at frequency , the interrupt must trigger twice per cycle ():
Example: 100Hz (10ms) Interrupt Setup
We choose a prescaler of 64:
#include <avr/io.h>
#include <avr/interrupt.h>
void timer1_init_100hz(void) {
TCCR1A = 0; // Clear control registers
TCCR1B = 0;
// Set CTC mode (WGM12 = 1 in TCCR1B)
TCCR1B |= (1 << WGM12);
// Set compare match value
OCR1A = 2499;
// Enable compare match A interrupt
TIMSK1 |= (1 << OCIE1A);
// Set prescaler to 64 (CS11=1, CS10=1) and start timer
TCCR1B |= (1 << CS11) | (1 << CS10);
sei(); // Enable global interrupts
}
ISR(TIMER1_COMPA_vect) {
// Executes automatically every 10ms
// Must be short and avoid blocking logic
}
Why is CTC mode preferred over Normal mode with manual register reloads for executing periodic scheduler tasks?
Configure Prescaler CS Bits
// Configure Timer 1 for prescaler 256 in TCCR1B TCCR1B |= (1 << ); // CS12 is set, others clear
References & Further Reading
- Microchip Technology. ATmega2560 8-bit AVR Microcontroller Datasheet. Section 17 (16-bit Timer/Counter 1).
- VIA University College: Embedded Software 1 (ESW1) Lecture Notes - Section 8 (Timers & CTC Mode).