
Fig. 1 PIC1684A interrupt map.
Programming PIC16F84A-PIC16F628A Interrupts Tutorial
The Microchip PIC series of microcontrollers have several sources of hardware interrupts. These are RISC microcontrollers with 35 instructions. To configure interrupts or other hardware functions are setup by configuring various bits in selected registers, in particular here the INTCOM register. While I use the PIC16F84A as an example, this works exactly the same in the PIC16F628A, etc. Also see PIC16F628A interrupt map.
Here I'll start with hardware interrupts, which add incredible power to these low-cost devices. Fig. 1 illustrates the interrupt control structure in a PIC16F84A. By setting and clearing selected bits in the INTCON register we enable a specific device or any combination of them. In this series I'm interested in the PORTB pullups great for detecting switch closings, and TMR0 excellent is for setting up time delays. This is a general discussion of hardware interrupts.

Fig. 2
To enable any interrupt the SET bit 7 to 1 in the interrupt control register. (BSF INTCON, 7) Then it's a matter of selecting which specific interrupt we want. SET bit 5 for the timer 0 (TMR0) overflow. To determine if an overflow occurred with TMR0 check bit 2 for an overflow condition if SET or 1. This is often referred to as a "flag" bit for testing. Once SET no further interrupts can occur until the bit is cleared to 0. (BCF INTCON, 2)
To enable the interrupt function on PORTB internal pullups SET bit 3 (BSF INTCON, 3) to 1. This will generate an interrupt if any HIGH-LOW or LOW-HIGH transition occurs on PORTB PB4-PB7. Testing the state of bit 0 if 1 shows the interrupt occurred. No further interrupts can occur until bit 0 is cleared to 0. (BCF INTCON, 0)
Great, we have the interrupts programmed and ready to go what's next? When an interrupt occurs the program counter executing the main program saves the PC in the STACK a FIFO buffer used for temporary storage then jumps to what is called an interrupt service routine.
ORG 0 ; reset vector GOTO setup ORG 0x04 ; interrupt vector ; do whatever RETFIE ; return from interrupt setup ; program the hardware GOTO loop loop ; main program GOTO loop
If one has done Arduino programming the above should be somewhat familiar. This is what really goes on "under the hood" of microcontrollers. It differs between them but all have "vectors" that point to particular memory locations during resets and interrupts.
#define LED 9 volatile byte state = LOW; void toggle() { state = !state; } void setup() { pinMode(LED, OUTPUT); attachInterrupt(0, toggle, RISING); } void loop() { digitalWrite(LED, state); }
Above is the Arduino version but in C++.

Fig. 3 PIC16F84A Memory Map.
ORG 0x004 ; interrupt vector location movwf w_temp ; save W register contents movf STATUS, w ; move status register into W movwf status_temp ; save STATUS register ; isr code can go here or be located ;as a call subroutine elsewhere MOVLW 0x01 ; PORTB bit to change CALL toggle CALL DELAY_100mS BCF INTCON, RBIF ; CLR IRQ flag movf status_temp,w ; retrieve STATUS register movwf STATUS ; restore STATUS register swapf w_temp,f swapf w_temp,w ; restore W register retfie ; return from interrupt
Above is a sample ISR routine called when a switch was pressed on say PB7. The program counter after being saved on the STACK jumps to location 0x04 and executes the code that follows until it encounter a "RETFIE" command then retrieves the original PC and resumes execution of whatever code it was processing at the time of the interrupt. Note: this code illustrates saving the W and STATUS registers on entering the ISR then restoring before the "RETFIE" command. I'd highly advise doing that.
This ISR simply called a separate subroutine after loading 0x01 into the W register that simply inverted the state on a LED at PORTB PB0. It then called subroutine DELAY_100mS, then set to 0 in this case INTCON bit 0 interrupt flag, restored the original W and STATUS values.
That completes this basic introduction to the PIC16F84A interrupts. I use that part because it's easier to illustrate, but everything here applies to other PICs that simply have more interrupt devices to choose from. I'll be looking direct examples of what we just discussed elsewhere.
- Programming PIC16F84A-PIC16F628A Interrupts by Example
- PIC16F84A-PIC16F628A Pull Up Resistors with Interrupts
- Programming PIC16F84A-PIC16f628a Timers by Example
- Programming PIC16F84A-PIC16F628A TMR0 Interrupts
- Programming PIC16F84A Software Delay Routines by Example
- YouTube videos:
- PIC16F84A-628A Hardware Time Delays
- PIC16F84A-628A Timer Interrupt Delays
- PIC16F84A-628A Pullups and Interrupts
- PIC16F84A-628A Hardware Interrupts Tutorial

- Microchip PIC related videos:
- How to Use K150 PIC Programmer
- Microchip PIC16F628A Basic H-Bridge Motor Control
- Microchip PIC16F628A Counts BCD on 8 LEDs
- PIC16F84A Operates H-Bridge Motor Control
- PIC16F84A Operates MOSFET H-Bridge
- Using Velleman K8048 PIC Development Board
- Microchip PIC16F84A H-Bridge Motor Control
- Microchip PIC16F628A Basic H-Bridge Motor Control
- PICAXE Operates H-Bridge Motor Controller
- PICAXE Micorcontroller Controls Motor Speed - Direction
- PICAXE Projects
- Arduino Port Registers Revisited
- Digispark ATtiny85 with MCP23016 GPIO Expander
- Safely Build Program a H-Bridge
- Build H-Bridge Motor Control Without Fireworks
- MOSFET H-Bridge for Arduino 2
- Web Master
- Gen. Electronics
- YouTube Channel
- Arduino Projects
- Raspberry Pi & Linux
- PIC18F2550 in C
- PIC16F628A Assembly
- PICAXE Projects
Web site Copyright Lewis Loflin, All rights reserved.
If using this material on another site, please provide a link back to my site.