Summary
Interrupts are events detected by the MCU which cause normal program flow to be preempted. Interrupts pause the current program and transfer control to a specified user-written firmware routine called the Interrupt Service Routine (ISR). The ISR processes the interrupt event, then resumes normal program flow.
This article shows how to enable and process interrupts on the PIC16F1xxx family of Enhanced Mid-Range PIC®.
Overview of Interrupt Process
1
Program MCU to react to interrupts
The MCU must be programmed to enable interrupts to occur. Setting the Global Interrupt Enable (GIE) and, in many cases, the Peripheral Interrupt Enable (PEIE), enables the MCU to receive interrupts. GIE and PEIE are located in the Interrupt Control (INTCON) special function register.
2
Enable interrupts from selected peripherals
Each peripheral on the MCU has an individual enable bit. A peripheral's individual interrupt enable bit must be set, in addition to GIE/PEIE, before the peripheral can generate an interrupt. The individual interrupt enable bits are located in INTCON, PIE1, PIE2, and PIE3.
3
Peripheral asserts an interrupt request
When a peripheral reaches a state where program intervention is needed, the peripheral sets an Interrupt Request Flag (xxIF). These interrupt flags are set regardless of the status of the GIE, PEIE, and individual interrupt enable bits. The interrupt flags are located in INTCON, PIR1, PIR2, and PIR3.
The interrupt request flags are latched high when set and must be cleared by the user-written ISR.
4
Interrupt occurs
When an interrupt request flag is set and the interrupt is properly enabled, the interrupt process begins:
- Global Interrupts are disabled by clearing GIE to 0.
- The current program context is saved to the shadow registers.
- The value of the Program Counter is stored on the return stack.
- Program control is transferred to the interrupt vector at address 04h.
5
ISR runs
The ISR is a function written by the user and placed at address 04h. The ISR does the following:
- Checks the interrupt-enabled peripherals for the source of the interrupt request.
- Performs the necessary peripheral tasks.
- Clears the appropriate interrupt request flag.
- Executes the Return From Interrupt instruction (RETFIE) as the final ISR instruction.
6
Control is returned to the Main program
When RETFIE is executed:
- Global Interrupts are enabled (GIE=1).
- The program context is restored from the Shadow registers.
- The return address from the stack is loaded into the Program Counter.
- Execution resumes from point at which it was interrupted.
Registers Used to Process Interrupts
Interrupt Control Register
INTCON register
GIE - Global Interrupt Enable
PEIE - Peripheral Interrupt Enable
TMR0IE - Timer0 Interrupt Enable
INTE - External Interrupt Enable
IOCIE - Interrupt on Change Enable
TMR0IF - Timer0 Interrupt flag
INTF - External Interrupt flag
IOCIF - Interrupt on Change flag
INTCON contains global and peripheral interrupt enable flags as well as the individual interrupt request flags and interrupt enable flags for three of the PIC16F1xxxx interrupts.
Interrupt Enable Registers
PIE1 register
TMR1GIE - Timer1 Gate Interrupt Enable
ADIE - Analog-to-Digital Converter (ADC) Interrupt Enable
RCIE - Universal Synchronous Asynchronous Receiver Tranmsitter (USART) Receive Interrupt Enable
TXIE - USART Transmit Interrupt Enable
SSPIE - Synchronous Serial Port (MSSP) Interrupt Enable
CCP1IE - CCP1 Interrupt Enable
TMR2IE - Timer2 Interrupt Enable
TMR1IE - Timer1 Interrupt Enable
PIE2 register
OSFIE - Oscillator Fail Interrupt Enable
C2IE - Comparator C2 Interrupt Enable
C1IE - Comparator C1 Interrupt Enable
EEIE - EEPROM Write Completion Interrupt Enable
BCLIE - MSSP Bus Collision Interrupt Enable
LCDIE - LCD Module Interrupt Enable
--- - Unimplemented, read as 0
CCP2IE - CCP2 Interrupt Enable
PIE3 register
--- - Unimplemented read as 0
CCP5IE - CCP5 Interrupt Enable
CCP4IE - CCP4 Interrupt Enable
CCP3IE - CCP3 Interrupt Enable
TMR6IE - Timer6 Interrupt Enable
--- - Unimplemented, read as 0
TMR4IE - Timer4 Interrupt Enable
--- - Unimplemented, read as 0
PIE1, PIE2, and PIE3 contain the individual interrupt enable flags for the MCU's peripherals.
Interrupt Request Registers
PIR1 register
TMR1GIF - Timer1 Gate Interrupt Flag
ADIF - ADC Interrupt Flag
RCIF - USART Receive Interrupt Flag
TXIF - USART Transmit Interrupt Flag
SSPIF - MSSP Interrupt Flag
CCP1IF - CCP1 Interrupt Flag
TMR2IF - Timer2 Interrupt Flag
TMR1IF - Timer1 Interrupt Flag
PIR2 register
OSFIF - Oscillator Fail Interrupt Flag
C2IF - Comparator C2 Interrupt Flag
C1IF - Comparator C1 Interrupt Flag
EEIF - EEPROM Write Completion Interrupt Flag
BCLIF - MSSP Bus Collision Interrupt Flag
LCDIF - LCD Module Interrupt Flag
--- - Unimplemented, read as 0
CCP2IF - CCP2 Interrupt Flag
PIR3 register
--- - Unimplemented, read as 0
CCP5IF - CCP5 Interrupt Flag
CCP4IF - CCP4 Interrupt Flag
CCP3IF - CCP3 Interrupt Flag
TMR6IF - Timer6 Interrupt Flag
--- - Unimplemented, read as 0
TMR4IF - Timer4 Interrupt Flag
--- - Unimplemented, read as 0
PIR1, PIR2, and PIR3 contain the individual interrupt request flags for the MCU's peripherals.
OPTION_REG
OPTION_REG
The INTEDG flag in OPTION_REG is used to set a rising or failing edge on the INT pin as the trigger for an INTE interrupt.
Enabling Interrupts
Core Interrupts
Three interrupt sources (Timer0, External Interrupt, and Interrupt on Change) have interrupt enable bits located in INTCON. These interrupts are referred to as core interrupts.
To enable one of the core interrupts, only the individual Interrupt Enable bit and GIE need to be set.
Clearing an Interrupt Request flag before setting the Interrupt Enable Flag prevents any pending interrupt requests from triggering an immediate interrupt.
Peripheral Interrupts
The PIC16F1xxx peripherals, capable of generating interrupt requests each, have their interrupt enable flags in one of the three PIE registers. To enable a peripheral interrupt, the individual interrupt flag, GIE, and PEIE must be all set.
Servicing an Interrupt
ISR
The ISR is a user-written program that performs the necessary tasks when an interrupt occurs. The user is responsible for writing the ISR and placing it at address 04h. The last instruction executed by the ISR must be the RETFIE instruction. ISRs can be written in either C or assembly language.
ISR in Assembly (left) and ISR in C (right)
Context Saving
The MCU's hardware will invoke the context saving mechanism when an interrupt occurs.
Verify Source of the Interrupt
There is one ISR which services all the interrupts for the application. The ISR needs to sequentially check the individual interrupt request flags to determine the source of the interrupt.
Clearing the Interrupt Request Flag
The Interrupt Request Flags are latched when set by the peripheral. They must be cleared by ISR. Failure of the ISR to reset a request flag will cause another interrupt to occur immediately after the ISR returns control to the main program.
Sample Interrupt Code
Processing an Interrupt from Timer2
The animation below shows the code to setup and process an interrupt from Timer2 on the PIC16F1xxx enhanced mid-range MCU. The control icons at the bottom of the animation allow for the display to be paused and single stepped.
Further explanation of PIC16F1xxx interrupts can be found in the Interrupts page.
The Timer2/4/6 page provides the details on the setup and operation of Timer2.