0
0
Power-electronicsHow-ToBeginner · 3 min read

How to Create Delay Using Timer in Embedded C

To create a delay using a timer in Embedded C, configure a hardware timer to count up to a specific value that matches the desired delay, then wait for the timer overflow or interrupt. This method is more accurate than simple loops and uses the microcontroller's timer registers and interrupts.
📐

Syntax

Creating a delay with a timer involves these steps:

  • Initialize the timer registers with a prescaler and count value.
  • Start the timer.
  • Wait for the timer overflow flag or interrupt.
  • Stop and reset the timer.

Each microcontroller has specific registers, but the general pattern is similar.

c
void Timer_Delay_Init(void) {
    // Set timer prescaler and mode
    TCCR0A = 0x00; // Normal mode
    TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler 64
    TCNT0 = 0; // Reset timer count
    TIFR0 |= (1 << TOV0); // Clear overflow flag
}

void Timer_Delay_ms(unsigned int ms) {
    while(ms--) {
        TCNT0 = 0; // Reset timer
        while((TIFR0 & (1 << TOV0)) == 0); // Wait for overflow
        TIFR0 |= (1 << TOV0); // Clear overflow flag
    }
}
💻

Example

This example shows how to create a 1-second delay using Timer0 on an AVR microcontroller running at 16 MHz clock. It uses a prescaler of 64 and counts timer overflows to reach 1 second.

c
#include <avr/io.h>
#include <util/delay.h>

void Timer0_Init(void) {
    TCCR0A = 0x00; // Normal mode
    TCCR0B = (1 << CS01) | (1 << CS00); // Prescaler 64
    TCNT0 = 0; // Reset timer count
    TIFR0 |= (1 << TOV0); // Clear overflow flag
}

void Delay_1s(void) {
    unsigned int count = 61; // Number of overflows for ~1s delay
    while(count--) {
        TCNT0 = 0; // Reset timer
        while((TIFR0 & (1 << TOV0)) == 0); // Wait for overflow
        TIFR0 |= (1 << TOV0); // Clear overflow flag
    }
}

int main(void) {
    DDRB |= (1 << PB0); // Set PB0 as output
    Timer0_Init();
    while(1) {
        PORTB ^= (1 << PB0); // Toggle LED
        Delay_1s();
    }
    return 0;
}
Output
LED connected to PB0 toggles ON and OFF every 1 second
⚠️

Common Pitfalls

  • Using busy-wait loops: Simple loops waste CPU cycles and are inaccurate due to compiler optimizations.
  • Incorrect prescaler or count values: Wrong timer settings cause wrong delay lengths.
  • Not clearing overflow flags: Overflow flags must be cleared to detect next overflow correctly.
  • Ignoring timer resolution: Timer counts depend on clock and prescaler; calculate delays carefully.
c
/* Wrong: Busy wait loop for delay (inaccurate) */
void delay_wrong(void) {
    for (volatile unsigned long i = 0; i < 1000000; i++);
}

/* Right: Using timer overflow flag and clearing it */
void delay_right(void) {
    TCNT0 = 0;
    while((TIFR0 & (1 << TOV0)) == 0);
    TIFR0 |= (1 << TOV0);
}
📊

Quick Reference

Timer delay creation steps:

  • Set timer mode (normal, CTC, etc.)
  • Choose prescaler to slow timer clock
  • Calculate count for desired delay
  • Start timer and wait for overflow flag
  • Clear overflow flag after delay
  • Stop or reset timer if needed

Key Takeaways

Use hardware timers for accurate delays instead of simple loops.
Configure timer prescaler and count based on your clock frequency.
Always clear the timer overflow flag after it triggers.
Calculate timer counts carefully to match the desired delay.
Busy-wait loops waste CPU and are not precise for delays.