ABC of Electronics cosycom.com
PIC BASICS · LESSON 12

Interrupts in Depth

An interrupt lets hardware — a timer, a pin change, incoming serial data — pause your program and demand immediate attention, then hand control right back.

An interrupt is a signal from a peripheral that says, in effect, "stop what you're doing and deal with me right now." When it fires, the CPU automatically saves its current place in your main program, jumps to a special function called an interrupt service routine (ISR), runs it, and then returns exactly to where it left off — as if nothing happened, except that a little time has passed and, usually, some shared variable has changed.

Interrupts exist because polling — repeatedly checking "has this happened yet?" in a loop — wastes CPU time and can miss brief events entirely if the main loop happens to be busy elsewhere when the event occurs. A pin-change interrupt, for example, is guaranteed to be noticed the instant the pin changes, regardless of what the main loop was doing.

Common interrupt sources on a PIC
SourceFires when…
Timer overflowA timer register rolls over to zero
Pin changeA configured input pin changes state
UART receiveA new byte has arrived over serial
ADC conversion doneAn analog-to-digital reading has finished

Writing an ISR comes with one important rule: keep it short. Because the main program is completely paused while the ISR runs, a slow or complicated ISR delays everything else the chip should be doing. The typical pattern is for the ISR to do the bare minimum — read a value, set a flag, clear the interrupt condition — and let the main loop, checking that flag, do the heavier work at its own pace.

main.c — a minimal timer interrupt
volatile unsigned char tick_flag = 0;

void __interrupt() ISR(void) {
    if (TMR0IF) {
        TMR0IF = 0;      // clear the interrupt flag
        tick_flag = 1;   // tell main loop: a tick happened
    }
}

void main(void) {
    TRISB0 = 0;
    T0CON  = 0b10000111;
    TMR0IE = 1;          // enable Timer0 interrupt
    GIE    = 1;          // enable interrupts globally

    while(1) {
        if (tick_flag) {
            tick_flag = 0;
            LATB0 = ~LATB0;
        }
    }
}
KEY TAKEAWAY
A variable shared between an ISR and the main loop should be declared volatile — this tells the compiler its value can change unexpectedly, so it must always be re-read from memory rather than assumed unchanged.