Skip to content

Tutorial — Practice 5: Timers and interrupts

What you will build

Use Timer0 and interrupts for precise delays without blocking the main loop.

  1. 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. 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. 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. 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. 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.

Review Timer 0, Timer 1 and 2, and Interrupts before writing your ISR.

  1. Configure Timer0 (or Timer1) for a known delay.
  2. Enable GIE and the timer interrupt flag.
  3. Write an ISR that saves and restores context (WREG, STATUS, bank).
  4. Handle a pushbutton with INT0 or RB4–RB7 without polling in the main loop.

Tutorial hub · Exercises