Timers & Timer Interrupts
A hardware timer counts clock pulses entirely in the background, freeing your main loop from doing the counting itself — and it can interrupt your code the moment it's done.
The software delay from the blinking-LED lesson works, but it has a real cost: while the chip is "waiting," it can do absolutely nothing else — it's stuck inside an empty loop, unable to check a button, read a sensor, or respond to anything. A hardware timer solves this by counting in the background, using dedicated circuitry that runs independently of your main program.
A timer is, at its simplest, a register that automatically increments by one on every clock pulse (or every few pulses, depending on a configurable "prescaler" that slows the counting rate down). When that register overflows — rolls over from its maximum value back to zero — the chip can either continue silently or raise a flag that your code checks, or, more usefully, trigger an interrupt that pauses your main code and jumps to a dedicated handler function.
| Approach | How it works | Trade-off |
|---|---|---|
| Polling | Main loop repeatedly checks the timer's overflow flag | Simple, but still ties up the main loop somewhat |
| Interrupt | Timer overflow automatically calls a handler function | Main loop is fully free in between; needs more careful code |
The prescaler is what makes a timer useful across a wide range of time intervals despite counting at a fixed clock speed. A prescaler of 1:8, for example, means the timer only advances once for every eight clock pulses — effectively slowing the countdown by a factor of eight, which lets the same 8-bit or 16-bit counter register span a much longer real-world time before it overflows.
void main(void) {
TRISB0 = 0; // LED output
T0CON = 0b10000111; // enable Timer0, set prescaler
while(1) {
if (TMR0IF == 1) { // timer overflowed?
TMR0IF = 0; // clear the flag
LATB0 = ~LATB0; // toggle LED
}
// other work could go here, unaffected by the wait
}
}