Tutorial — Practice 5: Timers and interrupts
What you will build
Use Timer0 and interrupts for precise delays without blocking the main loop.
-
1 Configure Timer0 for periodic overflow
Internal timer mode, prescaler for desired delay (e.g. 1:256). Preload TMR0H:TMR0L so overflow occurs every X ms. Calculate the value using Topic 8 formulas.Tip: Review: /en/timers/timer0/
-
2 Enable Timer0 interrupt
Enable TMR0IE (INTCON), PEIE, and GIE. In the Timer0 ISR: reload TMR0, clear TMR0IF, and toggle an LED—this verifies the delay works without blocking main.BSF INTCON, TMR0IE BSF INTCON, PEIE BSF INTCON, GIE -
3 Write the ISR with context save
On entry: save WREG, STATUS (and BSR if using banks). Do the work (toggle LED, counter, etc.). Restore in reverse order and RETFIE. Never call routines that clobber context without saving it.Tip: Guide: /en/interrupciones/
-
4 Add external interrupt (pushbutton)
Use INT0 (RB0) or RBIE (RB4–RB7). In the external ISR: debounce, change a state (e.g. blink direction). The main loop must not poll the button—only slow tasks or idle work. -
5 Main loop without blocking
Main can be nearly empty (`GOTO $`) or run low-priority tasks. All precise timing belongs in ISRs. Verify in Proteus that the LED blinks at a stable interval while the button responds.
Supporting theory
Section titled “Supporting theory”Review Timer 0, Timer 1 and 2, and Interrupts before writing your ISR.
What your code should do
Section titled “What your code should do”- Configure Timer0 (or Timer1) for a known delay.
- Enable GIE and the timer interrupt flag.
- Write an ISR that saves and restores context (
WREG,STATUS, bank). - Handle a pushbutton with INT0 or RB4–RB7 without polling in the main loop.