Sunteți pe pagina 1din 31

PIC18 Interrupt Programming

Interrupt Programming
• Contra and compare interrupts versus polling
• Explain the purpose of the ISR
• List all the major interrupts of the PIC18
• Explain the purpose of the IVT
• Enable and disable PIC18 interrupts
• Program the interrupt using c language
Interrupt
• Whenever any device needs the
microcontroller’s service the device notifies it by
sending an interrupt signal. Upon receiving an
interrupt signal, the microcontroller stops
whatever it is doing and serve the device. The
program associated with the interrupt is called
ISR (interrupt service routine) or interrupt
handler.
• Each device can get the attention of the
microcontroller based on the priority assign to it.
• Can ignore a device request for service
Polling
• The microcontroller continuously monitors the status
of a given device; when the status condition met, it
performs the service. After that, it moves on to
monitor the next device until each one is service.
• Cannot assign priority because it checks all devices in
a round-robin fashion.
• Cannot ignore a devices for service
Interrupt Service Routine (ISR)

Interrupt ROM Location (hex)

Power-on-Reset 0000

High Priority Interrupt 0008 (Default upon power-on


reset)
Low Priority Interrupt 0018

Interrupt Vector Table

Fixed Location in Memory


Step in Executing an Interrupt
1. It finishes the instruction it is executing and saves
the address of the next instruction (program
counter) on the stack
2. It jumps to a fixed location in memory (interrupt
vector table (IVT)). The IVT directs the
microcontroller to the address of the ISR
3. The microcontroller gets the address of the ISR
from the IVT and jumps to it. It start to execute
the interrupt service subroutine until it reaches
the last instruction of the subroutine - RETFIE
(Return from Interrupt Exit)
4. Upon executing the RETFIE instruction, the
microcontroller returns to the place where it was
interrupted
Sources of Interrupt
• Each Timers
• 3 interrupts for external hardware. Pin RB0 (INT0),
RB1 (INT1) and RB2 (INT2)
• 2 interrupts for serial communication (Receive and
Transmit)
• The PORTB-Change interrupt (RB4-RB7)
• The ADC
• The CCP
Enable and Disable an Interrupt

BSF INTCON,GIE
BCF INTCON,GIE
Timer Interrupts
Interrupt Flag Bit Register Enable Bit Register

Timer0 TMR0IF INTCON TMR0IE INTCON

Timer1 TMR1IF PIR1 TMR1IE PIE1

Timer2 TMR2IF PIR1 TMR3IE PIE1

Timer3 TMR3IF PIR3 TMR3IE PIE2

Timer Interrupt Flag Bits and Associated Registers

INTCON Register with Timer0 Interrupt Enable and Interrupt Flag


Interrupt vector to control the ISR

Because C18 does not place ISR at IVT automatically, we use


ASM instruction GOTO at IV to transfer control to ISR

#pragma code high_vector=0x0008 //High priority int location


void My_HiVect_int(void)
{
_asm
GOTO my_isr
_endasm
}
#pragma code //end of code
Redirect from 0008 to another program to find interrupt source
and the ISR

#pragma interrupt my_isr //interrupt is a reserved word


void my_isr(void)
{

//C18 places RETFIE here automatically due to interrupt


//keyword

Note : “pragma” , “code” and “interrupts” reserved keyword


EX. Use T0 and T1 to generate square-wave on pins RB1
and RB7, while data being transfer from PC to PD.

#include <P18f458.h>
#define MyPB1bit PORTBbits.RB1 //input switch
#define MyPB1bit PORTBbits.RB7 //input switch

void T0_ISR(void);
void T1_ISR(void);
#pragma interrupt my_isr
void chk_isr(void)
{
If(INTCONbits.TMR0IF==1) //T0 causes int ?
T0_ISR //yes, execute T0 ISR
If(INTCONbits.TMR1IF==1) //T1 causes int ?
T1_ISR //yes, execute T0 ISR
}
#pragma code My_HiPrio=0x0008 //High priority int loc
void My_HiPrio_int(void)
{
_asm
GOTO chk_isr
_endasm
}
#pragma code

void main(void)
{
TRISBbits.TRISB1=0; //PB1 as output;
TRISBbits.TRISB7=0; //PB7 as output;
TRISC = 0xFF //PC as intput;
TRISD = 0x00 //PD as output;
T0CON = 0x00; //T0, 16-bit , no pre-scale
TMR0H = 0x35;
TMR0L = 0x00;
T1CON = 0x08; //T1, 16-bit , no pre-scale
TMR0H = 0x35;
TMR0L = 0x00;
INTCONbits.TMR0IF=0; //clear TF0;
PIR1bits.TMR1IF=0; //clear TF1;
INTCONbits.TMR0IE=1; //enable T0 int;
INTCONbits.TMR1IE=1; //enable T1 int;
INTCONbits.TMR0ON=1; //turn on T0;
INTCONbits.TMR1ON=1; //turn on T1;
INTCONbits.PEIE=1; //enable all pheperal int;
INTCONbits.GIE=1; //enable all int globally;
While(1) //keep looping until int occur
{
PORTD=PORTC //send data fromPC to PD
}
}
void T0_ISR(void)
{
myPB1bit=~myPB1bit; //toggle PB.1;
TMR0H = 0x35;
TMR0L = 0x00;
INTCONbits.TMR0IF=0; //clear TF0;
}

void T1_ISR(void)
{
myPB7bit=~myPB7bit; //toggle PB.7;
TMR1H = 0x35;
TMR1L = 0x00;
INTCONbits.TMR1IF=0; //clear TF1;
}
External Hardware Interrupts
Interrupt Flag Bit Register Enable Bit Register

INT0(RB0) INT0IF INTCON INT0IE INTCON

INT1 (RB1) INT1IF INTCON3 INT1IE INTCON3

INT2 (RB2) INT2IF INTCON3 INT2IE INTCON3

Hardware Interrupt Flag Bits and Associated Registers

Positive-edge-
triggered interrupt
EX. When ↑ (rise-edge) on pin INT0, LED will toggle.

#include <P18f458.h>
#define Mybit PORTBbits.RB7
void chk_isr(void);
void INT0_ISR(void);

#pragma interrupt chk_isr


void chk_isr(void)
{
If(INTCONbits.INT0IF==1 ) //INT0 causes int ?
INT0_ISR(); //yes, execute INT0 prg
}
#pragma code My_HiPrio_Int=0x08 //high-priority int loc
void My_HiPrio_int(void)
{
_asm
GOTO chk_isr
_endasm
}
#pragma code
void main(void)
{
TRISBbits.TRISB7=0; //PB7 as output;
TRISBbits.TRISB0=1; //PB1 as input;
TRISC = 0xFF //PC as intput;
TRISD = 0x00 //PD as output;
INTCONbits.INT0IF=0; //clear TF0;
INTCONbits.INT0IE=1 //enable T0 interrupt
INTCONbits.GIE=1; //enable all int globally;
While(1) //keep looping until int occur
{
PORTD=PORTC //send data fromPC to PD
}
}

void INT0_ISR(void)
{
mybit=~mybit; //toggle mybit;
INTCONbits.INT0IF=0; //clear INT0 flag;
}
Serial Communication Interrupts
Interrupt Flag Bit Register Enable Bit Register
TXIF TXIF PIR1 TXIE PIE1
(Trasmit)

RCIF RCIF PIR1 RCIE PIE1


(Receive)

Serial Port Interrupt Flag Bits and Associated Registers

PIE1 Register Bits Holding TXIE and RCIE


EX. Get data from PD and send to TXREG continuously while
incoming data from serial is send to PB. Assume XTAL 10
MHz and baud rate is 9600.

#include <P18f458.h>
void chk_isr(void);
void TX_ISR(void);
void RC_ISR(void);

#pragma code My_HiPrio_Int=0x08 //high-priority int loc


void My_HiPrio_int(void)
{
_asm
GOTO chk_isr
_endasm
}
#pragma code
#pragma interrupt chk_isr //used for high prioity int
void chk_isr(void)
{
If(PIR1bits.TXIF==1) //Tx causes int ?
TX_ISR(); /yes, execute Tx prg
If(PIR1bits.RCIF==1) //RC causes int ?
RC_ISR(); /yes, execute RC prg
}

void main(void)
{
TRISD = 0xFF //PD as intput;
TRISB = 0x00 //PB as output;
TRISBbits.TRISC6=0; //TX pin output;
TRISBbits.TRISC7=1; //RC pin input;
TXSTA=0x20 //low baud rate, 8-bit
SPBRG=15 //9600 baud rate (XTA =10
RCSTAbits.CREN=1;
RCSTAbits.SPEN=1;
TXSTAbits.TXEN=1;
PIE1bits.RCIE= 1; //enable RC int
PIE1bits.TXIE= 1; //enable TX int
INTCONbits.PIE=1; //enable peripheral int;
INTCONbits.GIE=1; //enable all int globally;
While(1); //keep looping until int occur
}
void TX_ISR(void)
{
TXREG=PORTD;
}
void RC_ISR(void)
{
PORTB=RCREG;
}
}
PORTB-Change Interrupt
Differences Between External Hardware and
PORTB-Change Interrupt
External Hardware PORTB-Change

This (RB0-RB2) interrupts has its own pin Use all four (RB4-RB7) and considered to be
and is independent each other a single interrupt even though it can use up
to four pins

Has it own flag (INTxIF) and independent Single flag only (RBIF)
each other

Can be programmed to trigger on the Cause an interrupt either pin changes


negative or positive edge status from HIGH-LOW or LOW-HIGH
EX. Connect SW1 and SW2 to pins RB4 and RB5
respectively. SW1 and SW2 will change LED1 and LED2.

#include <P18f458.h>
#define LED1 PORTCbits.RC1
#define LED2 PORTCbits.RC2
void chk_isr(void);
void RBINT_ISR(void);

#pragma code My_HiPrio_Int=x08 //high-priority int loc


void My_HiPrio_int(void)
{
_asm
GOTO chk_isr
_endasm
}
#pragma code
#pragma interrupt chk_isr //used for high prio int

void chk_isr(void)
{
If(INTCONbits.RBIF==1 //RBIF causes int ?
RBINT_ISR(); //yes, execute INT0 prg
}

void main(void)
{
TRISCbits.TRISC1=0; //PC4 as output;
TRISCbits.TRISC2=0; //PC5 as ouput;
TRISBbits.TRISB4=1; //PB4 input for int;
TRISBbits.TRISB5=1; //PB5 input for int;
INTCONbits.RBIF=0; //clear RIF;
INTCONbits.RBIE=1; //enable RB int;
INTCONbits.GIE=1; //enable all int globally;
}
void RBINT_ISR(void)
{
LED1 = PORTBbits.RB4;
LED2 = PORTBbits.RB5;
INTCONbits.RBIF=0; //clear RBIF flag;
}
Interrupt Priority
Interrupt ROM Location (hex)

Power-on-Reset 0000

High Priority Interrupt 0008 (Default upon power-on reset)

Low Priority Interrupt 0018


RCON Register
IPR1 Peripheral Interrupt Priority Register

S-ar putea să vă placă și