Search Knowledge

© 2026 LIBREUNI PROJECT

C Programming Mastery / AVR Microcontroller Interfacing

AVR Register Programming: Timers & CTC

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., 6553565535 for a 16-bit timer) before resetting. To run a periodic task at a faster frequency, software must manually reset TCNT1 inside 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 resets TCNT1 to 0 in 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.

PrescalerCS12CS11CS10TCCR1B Register Setting
No Clock (Stopped)000Timer stopped
1 (None)001(1 << CS10)
8010(1 << CS11)
64011(1 << CS11) | (1 << CS10)
256100(1 << CS12)
1024101(1 << CS12) | (1 << CS10)

CTC Threshold Calculation

To trigger a compare match interrupt at frequency fintf_{int}, calculate OCR1A using:

OCR1A=fCPUPrescaler×fint1OCR1A = \frac{f_{CPU}}{Prescaler \times f_{int}} - 1

Rule for LED Toggling: If the ISR toggles a pin to blink a LED at frequency fLEDf_{LED}, the interrupt must trigger twice per cycle (fint=2×fLEDf_{int} = 2 \times f_{LED}):

OCR1A=fCPU2×Prescaler×fLED1OCR1A = \frac{f_{CPU}}{2 \times Prescaler \times f_{LED}} - 1

Example: 100Hz (10ms) Interrupt Setup

We choose a prescaler of 64:

OCR1A=16,000,00064×1001=16,000,00064001=25001=2499OCR1A = \frac{16,000,000}{64 \times 100} - 1 = \frac{16,000,000}{6400} - 1 = 2500 - 1 = 2499

#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).