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
| Step | Description |
|---|---|
| Set Timer Mode | Configure timer control register for mode and clock source |
| Load Timer Count | Set timer count register with preload value for desired delay |
| Enable Interrupt | Turn on timer overflow interrupt if asynchronous handling needed |
| Start Timer | Enable timer counting by setting start bit |
| Handle Interrupt | Write 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.