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.