How to Configure Timer Interrupt in Embedded C: Simple Guide
To configure a timer interrupt in embedded C, you need to initialize the timer registers, set the timer count value, enable the timer interrupt, and write an interrupt service routine (ISR) to handle the interrupt. Use
timer_init() to set the timer mode and prescaler, enable the interrupt with timer_interrupt_enable(), and define the ISR with the correct interrupt vector.Syntax
Configuring a timer interrupt typically involves these steps:
- Initialize Timer: Set timer mode and prescaler.
- Set Timer Count: Load the timer start value.
- Enable Interrupt: Turn on timer interrupt in interrupt control registers.
- Write ISR: Define the interrupt service routine to handle timer events.
embedded_c
void timer_init() { // Set timer mode (e.g., CTC mode) TCCR0A = (1 << WGM01); // Set prescaler to 64 TCCR0B = (1 << CS01) | (1 << CS00); // Set compare value for timer OCR0A = 249; } void timer_interrupt_enable() { // Enable timer compare interrupt TIMSK0 = (1 << OCIE0A); // Enable global interrupts sei(); } ISR(TIMER0_COMPA_vect) { // Code to run on timer interrupt }
Example
This example configures Timer0 on an AVR microcontroller to generate an interrupt every 1ms assuming a 16 MHz clock. The ISR toggles an LED connected to PORTB0.
embedded_c
#include <avr/io.h> #include <avr/interrupt.h> void timer_init() { TCCR0A = (1 << WGM01); // CTC mode TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler 64 OCR0A = 249; // Compare value for 1ms } void timer_interrupt_enable() { TIMSK0 = (1 << OCIE0A); // Enable compare interrupt sei(); // Enable global interrupts } ISR(TIMER0_COMPA_vect) { PORTB ^= (1 << PORTB0); // Toggle LED } int main(void) { DDRB |= (1 << DDB0); // Set PORTB0 as output timer_init(); timer_interrupt_enable(); while(1) { // Main loop does nothing, LED toggled in ISR } return 0; }
Output
LED on PORTB0 toggles every 1 millisecond
Common Pitfalls
Common mistakes when configuring timer interrupts include:
- Not enabling global interrupts with
sei(). - Forgetting to set the correct timer mode (e.g., CTC mode for compare match).
- Incorrect prescaler or compare value causing wrong timing.
- Not defining the ISR with the correct vector name.
- Modifying shared variables in ISR without
volatilekeyword or proper synchronization.
embedded_c
/* Wrong: Missing global interrupt enable */ void timer_interrupt_enable_wrong() { TIMSK0 = (1 << OCIE0A); // Interrupt enabled but no sei() } /* Right: Enable global interrupts */ void timer_interrupt_enable_right() { TIMSK0 = (1 << OCIE0A); sei(); // Must call this to enable interrupts globally }
Quick Reference
Timer Interrupt Setup Steps:
- Set timer mode (e.g., CTC) in control registers.
- Choose prescaler to scale clock speed.
- Load compare register with count value.
- Enable timer interrupt in interrupt mask register.
- Enable global interrupts with
sei(). - Write ISR with correct vector name.
Key Takeaways
Always enable global interrupts with sei() after enabling timer interrupts.
Set the timer mode and prescaler correctly to get accurate timing.
Define the ISR with the exact interrupt vector name for your timer.
Use volatile variables if shared between ISR and main code to avoid optimization issues.
Test timer interrupts with simple actions like toggling an LED to verify setup.