How to Implement Software Timer in Embedded C Easily
To implement a
software timer in embedded C, use a hardware timer interrupt to increment a counter variable periodically. Check this counter in your main program to trigger actions after a set time interval.Syntax
A software timer typically uses a volatile counter variable updated inside a hardware timer interrupt service routine (ISR). The main program checks this counter to perform timed actions.
Key parts:
volatile uint32_t timer_counter;- counter updated by ISRISR()- interrupt routine increments the counterif (timer_counter >= target)- check if timer expired
c
volatile uint32_t timer_counter = 0; // Timer interrupt service routine void Timer_ISR(void) { timer_counter++; } // Main loop int main(void) { while(1) { if (timer_counter >= TARGET_VALUE) { // Timer expired, do something timer_counter = 0; // reset timer } } }
Example
This example shows a software timer that toggles an LED every 1 second using a hardware timer interrupt that fires every 10 ms.
c
#include <stdint.h> #include <stdbool.h> #include <stdio.h> volatile uint32_t timer_counter = 0; // Simulated hardware register for LED (1 = ON, 0 = OFF) uint8_t LED = 0; // Simulated Timer ISR called every 10 ms void Timer_ISR(void) { timer_counter++; } void delay_ms(int ms) { for (int i = 0; i < ms; i++) { Timer_ISR(); // simulate timer interrupt } } int main(void) { while (1) { delay_ms(10); // simulate 10 ms timer tick if (timer_counter >= 100) { // 100 * 10ms = 1 second LED = !LED; // toggle LED timer_counter = 0; // reset timer if (LED) { // LED ON // In real embedded, set GPIO high // Here we print printf("LED ON\n"); } else { // LED OFF printf("LED OFF\n"); } } } return 0; }
Output
LED ON
LED OFF
LED ON
LED OFF
LED ON
LED OFF
Common Pitfalls
Common mistakes when implementing software timers include:
- Not declaring the timer counter as
volatile, causing compiler optimizations to break timing. - Updating the timer counter outside the interrupt, leading to inaccurate timing.
- Not resetting the timer counter after the timer expires, causing repeated triggers.
- Using blocking delays instead of interrupts, which freezes the program.
c
/* Wrong: timer_counter not volatile, may cause wrong behavior */ uint32_t timer_counter = 0; void Timer_ISR(void) { timer_counter++; } /* Right: declare as volatile to prevent optimization issues */ volatile uint32_t timer_counter = 0; void Timer_ISR(void) { timer_counter++; }
Quick Reference
Tips for software timers in embedded C:
- Use hardware timer interrupts for accurate timing.
- Declare timer counters as
volatile. - Keep ISR code short and fast.
- Reset counters after timer events.
- Avoid blocking delays; use timers instead.
Key Takeaways
Use a hardware timer interrupt to increment a volatile counter for software timing.
Check the counter in your main loop to trigger timed actions and reset it afterward.
Always declare timer counters as volatile to avoid compiler optimization issues.
Keep interrupt service routines short to maintain system responsiveness.
Avoid blocking delays; rely on software timers for non-blocking timing.