0
0
Power-electronicsHow-ToBeginner · 4 min read

How to Use Timer in Embedded C: Simple Guide and Example

In Embedded C, you use a timer by configuring the timer registers of your microcontroller to count clock pulses and trigger interrupts or flags. You set the timer mode, preload value, and enable interrupts to measure time or create delays using timer registers and interrupt service routines.
📐

Syntax

Using a timer in Embedded C involves configuring specific hardware registers of the microcontroller. Typically, you:

  • Set the timer control register to select the timer mode and clock source.
  • Load the timer count register with a start value.
  • Enable timer interrupts if you want to handle timer events asynchronously.
  • Start the timer by setting the enable bit.

Each microcontroller has its own register names and bits, but the general pattern is similar.

c
/* Example syntax for a generic 8-bit timer */
TIMER_CONTROL_REGISTER = MODE | CLOCK_SOURCE;  // Set mode and clock
TIMER_COUNT_REGISTER = PRELOAD_VALUE;           // Load start count
ENABLE_TIMER_INTERRUPT();                        // Enable interrupt if needed
START_TIMER();                                   // Start the timer
💻

Example

This example shows how to configure Timer0 on an 8-bit microcontroller (like PIC or AVR) to generate an interrupt every 1 millisecond. The timer counts up from a preload value to overflow and triggers an interrupt.

c
#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned int ms_count = 0;

ISR(TIMER0_OVF_vect) {
    TCNT0 = 6; // Reload timer for 1ms delay (assuming 16MHz clock, prescaler 64)
    ms_count++;
}

int main(void) {
    cli(); // Disable global interrupts
    TCNT0 = 6; // Preload timer
    TCCR0A = 0x00; // Normal mode
    TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler 64
    TIMSK0 = (1 << TOIE0); // Enable Timer0 overflow interrupt
    sei(); // Enable global interrupts

    while (1) {
        if (ms_count >= 1000) { // 1000 ms passed
            // Do something every 1 second
            ms_count = 0;
        }
    }
    return 0;
}
⚠️

Common Pitfalls

Common mistakes when using timers in Embedded C include:

  • Not setting the correct clock prescaler, causing wrong timing.
  • Forgetting to reload the timer count in the interrupt, which stops periodic interrupts.
  • Not enabling global interrupts with sei() or equivalent.
  • Using blocking delays inside interrupts, which can freeze the system.
  • Ignoring the microcontroller datasheet details for timer registers.
c
/* Wrong: Not reloading timer count in ISR */
ISR(TIMER0_OVF_vect) {
    ms_count++;
}

/* Right: Reload timer count to maintain timing */
ISR(TIMER0_OVF_vect) {
    TCNT0 = 6; // Reload for 1ms
    ms_count++;
}
📊

Quick Reference

StepDescription
Set Timer ModeConfigure timer control register for mode and clock source
Load Timer CountSet timer count register with preload value for desired delay
Enable InterruptTurn on timer overflow interrupt if asynchronous handling needed
Start TimerEnable timer counting by setting start bit
Handle InterruptWrite ISR to reload timer and perform actions on overflow

Key Takeaways

Configure timer registers carefully according to your microcontroller datasheet.
Always reload the timer count inside the interrupt to keep timing consistent.
Enable global interrupts to allow timer interrupts to work.
Avoid long or blocking code inside timer interrupt routines.
Use timer interrupts for precise timing instead of delay loops.