- 1.When using interrupt priority
levels, set IPEN and then select the user-assigned priority level for the
interrupt source by writing the control bits in the appropriate IPRx control
register.
Important: At a device Reset, the IPRx registers are initialized such
that all user interrupt sources are assigned to high priority.
- 2.Clear the Interrupt Flag Status
bit associated with the peripheral in the associated PIRx STATUS register.
- 3.Enable the interrupt source by
setting the interrupt enable control bit associated with the source in the
appropriate PIEx register.
- 4.If the vector table is used
(MVECEN =
1), then setup the start address for the Interrupt
Vector Table using IVTBASE. See Interrupt Vector Table Contents section for more details.
- 5.Once IVTBASE is written to, set
the interrupt enable bits in INTCON0.
- 6.An example of setting up
interrupts and ISRs using assembly and C can be found in Setting up Vectored Interrupts using MPASM and Setting up Vectored Interrupts using XC8.
Setting up Vectored Interrupts
using MPASM
; Each ISR routine must have a predetermined origin otherwise there will be
; an assembly error because the address is not determined until link time
; which is too late to do the divide by 4 math on the address.
; Predetermined addresses must be evenly divisible by 4.
ISRSW CODE 0x3E00
; SW interrupt service code here.
BANKSEL PIR0
BCF PIR0, SWIF
RETFIE FAST
ISRHLVD CODE 0x3E40
; HLVD interrupt service code here.
BANKSEL PIR0
BCF PIR0, HLVDIF
RETFIE FAST
ISROSF CODE 0x3E60
; OSF interrupt service code here.
BANKSEL PIR0
BCF PIR0, OSFIF
RETFIE FAST
IntInit:
; Disable all interrupts
BCF INTCON0, GIE, ACCESS
; Set IVTBASE (optional - default is 0x000008)
CLRF IVTBASEU, ACCESS
MOVLW 0x3F
MOVWF IVTBASEH, ACCESS
CLRF IVTBASEL, ACCESS
; Clear any interrupt flags before enabling interrupts
BANKSEL PIR0
BCF PIR0, SWIF
BCF PIR0, HLVDIF
BCF PIR0, OSFIF
; Enable interrupts
BANKSEL PIE0
BSF PIE0, SWIE
BSF PIE0, HLVDIE
BSF PIE0, OSFIE
; Set interrupt priorities if necessary
BANKSEL IPR0
BSF INTCON0, IPEN_INTCON0, ACCESS ; Enable interrupt priority
BCF IPR0, HLVDIP ; Make HLVD interrupt low priority
; Enable interrupts
BSF INTCON0, GIEH, ACCESS
BSF INTCON0, GIEL, ACCESS
RETURN 1
; Save SWISR in vector table (IVTBASE+0*2)
ISR1 CODE 0x3F00
DW (0x3E40>>2) ; (SWISR/4)
; Save HLVDISR in vector table (IVTBASE+1*2)
ISR2 CODE 0x3F02
DW (0x3E60>>2) ; (HLVDISR/4)
; Save CLC2ISR in vector table (IVTBASE+2*2)
ISR3 CODE 0x3F04
DW (0x3E00>>2) ; (OSFISR/4)
Setting up Vectored Interrupts
using XC8
// NOTE 1: If IVTBASE is changed from its default value of 0x000008, then the
// "base(...)" argument must be provided in the ISR. Otherwise the vector
// table will be placed at 0x0008 by default regardless of the IVTBASE value.
// NOTE 2: When MVECEN=0 and IPEN=1, a separate argument as "high_priority"
// or "low_priority" can be used to distinguish between the two ISRs.
// If the argument is not provided, the ISR is considered high priority
// by default.
// NOTE 3: Multiple interrupts can be handled by the same ISR if they are
// specified in the "irq(...)" argument. Ex: irq(IRQ_SW, IRQ_HLVD)
void __interrupt(irq(IRQ_SW), base(0x3008)) SW_ISR(void)
{
PIR0bits.SWIF = 0; // Clear the interrupt flag
LATCbits.LATC0 ^= 1; // ISR code goes here
}
void __interrupt(irq(default), base(0x3008)) DEFAULT_ISR(void)
{
// Unhandled interrupts go here
}
void INTERRUPT_Initialize (void)
{
INTCON0bits.GIEH = 1; // Enable high priority interrupts
INTCON0bits.GIEL = 1; // Enable low priority interrupts
INTCON0bits.IPEN = 1; // Enable interrupt priority
PIE0bits.SWIE = 1; // Enable SW interrupt
PIE0bits.HLVDIE = 1; // Enable HLVD interrupt
IPR0bits.SWIP = 0; // Make SW interrupt low priority
// Change IVTBASE if required
IVTBASEU = 0x00; // Optional
IVTBASEH = 0x30; // Default is 0x000008
IVTBASEL = 0x08;
}