You are on page 1of 44

Interrupts

Introduction
Interrupts in the PIC16F877A
Setting up the Interrupts
Using the Interrupts
Summary

Introduction

An interrupt is a specific event that causes the normal program


execution to be suspended wherever it is and an interrupt function is
executed.
Interrupts increases the program efficiency by allowing external
devices or internal events to force a change in the execution
sequence.
When an interrupt signal is received, the current instruction is
completed and the address of the next instruction (the return
address) is pushed into the first available stack location.
Then the program jumps to program address 004, and continues
from there until it sees a Return From Interrupt (RETFIE) instruction.
When the interrupt function ends, the return address is pulled from
the stack. Program execution then restarts at the original location.
Normal program execution continues when the interrupt function
returns.
The PIC16F877A has a number of interrupt sources such as a timer
overflow, an incoming RS-232 character or a change on a pin.
2

Interrupts in the PIC16F877A


The primary interrupt sources for PIC16F877A
are Timers and Port B
The overflow of the Timers triggers the interrupt
RB0/INT is an external interrupt input pin and is
configured using the INTEDG bit
(OPTION_REG<6>)
Pins B4-B7 can be set up so that any change on
these inputs initiates the interrupt (interrupt
on(
change feature)
This could be used to detect when a button on a
keypad connected to Port B has been pressed
3

Interrupts in the PIC16F877A

Interrupts in the PIC16F877A

Setting up the Interrupts

Setting up the Interrupts


The Interrupt Control register (INTCON) records
individual interrupt requests in flag bits.
It also has individual and global interrupt enable bits.
INTCON contains various enable and flag bits for
the TMR0 register overflow, RB port change and
external RB0/INT pin interrupts.
INTEDG is Interrupt Edge Select bit
If set to 1 : Interrupt on rising edge of RB0/INT pin
If set to 0 : Interrupt on falling edge of RB0/INT pin
7

Setting up the Interrupts


Interrupt flag bits are set when an interrupt condition
occurs regardless of the state of its corresponding
enable bit or the global enable bit, GIE (INTCON<7>).
User software should ensure the appropriate interrupt
flag bits are clear prior to enabling an interrupt.

When bit GIE is enabled and an interrupts flag


bit and mask bit are set, the interrupt will vector
immediately.
The GIE bit is cleared on Reset.
8

Setting up the Interrupts

Setting up the Interrupts


The PIE1 register contains the individual
enable bits for the peripheral interrupts.
The peripheral interrupt sources are from
ADC, Timer and Serial I/O
Bit PEIE (INTCON<6>) must be set to
enable any peripheral interrupt.

10

Setting up the Interrupts

11

Setting up the Interrupts


The PIR1 register contains the individual
flag bits for the peripheral interrupts.
Interrupt flag bits are set when an interrupt
condition occurs regardless of the state of
its corresponding enable bit or the global
enable bit, GIE (INTCON<7>).
User software should ensure the
appropriate interrupt bits are clear prior to
enabling an interrupt.
12

Setting up the Interrupts

The bits in the PIR1 register


ADIF: A/D Converter Interrupt Flag bit
1 = An A/D conversion completed
0 = The A/D conversion is not complete
TMR2IF: TMR2 to PR2 Match Interrupt Flag bit
1 = TMR2 to PR2 match occurred (must be cleared in
software)
0 = No TMR2 to PR2 match occurred
TMR1IF: TMR1 Overflow Interrupt Flag bit
1 = TMR1 register overflowed (must be cleared in software)
0 = TMR1 register did not overflow
13

Setting up the Interrupts

14

Setting up the Interrupts


The PIE2 register contains the individual
enable bits for the CCP2 peripheral
interrupt, the SSP bus collision interrupt,
EEPROM write operation interrupt and the
comparator interrupt.

15

Setting up the Interrupts

16

Setting up the Interrupts


The PIR2 register contains the flag bits for the
CCP2 interrupt, the SSP bus collision interrupt,
EEPROM write operation interrupt and the
comparator interrupt
The peripheral interrupt flags are contained in the
Special Function Registers, PIR1 and PIR2.
The corresponding interrupt enable bits are
contained in Special Function Registers, PIE1 and
PIE2, and the peripheral interrupt enable bit is
contained in Special Function Register, INTCON
17

Setting up the Interrupts


When an interrupt is responded to, the GIE bit is cleared to
disable any further interrupt, the return address is pushed
onto the stack and the Program Counter (PC) is loaded with
0004h.
Once in the Interrupt Service Routine, the source(s) of the
interrupt can be determined by polling the interrupt flag bits.
The interrupt flag bit(s) must be cleared in software before reenabling interrupts to avoid recursive interrupts.
For external interrupt events, such as the INT pin or PORTB
change interrupt, the interrupt latency will be three or four
instruction cycles.
18

Setting up the Interrupts


By default, all the interrupts in the PIC16F877A
are disabled
The interrupts can be enabled by
GIE=1; // Global interrupt enable
The interrupts can be disabled by
GIE=0; // Global interrupt disable
Individual interrupts can be enabled separately as
well
For example, INTE=1; enables the external
interrupt input from Pin RB0
19

Using the Interrupts


INT INTERRUPT
External interrupt on the RB0/INT pin is edge triggered, either
rising if bit INTEDG (OPTION_REG<6>) is set or falling if the
INTEDG bit is clear.
When a valid edge appears on the RB0/INT pin, flag bit, INTF
(INTCON<1>), is set.
This interrupt can be disabled by clearing enable bit, INTE
(INTCON<4>).
Flag bit INTF must be cleared in software in the Interrupt
Service Routine before re-enabling this interrupt.
The INT interrupt can wake-up the processor from Sleep if bit
INTE was set prior to going into Sleep.
The status of global interrupt enable bit, GIE, decides whether
or not the processor branches to the interrupt vector following
wake-up.
20

Using the Interrupts


TMR0 INTERRUPT
An overflow (FFh 00h) in the TMR0
register will set flag bit, TMR0IF
(INTCON<2>).
The interrupt can be enabled/disabled by
setting/clearing enable bit, TMR0IE
(INTCON<5>).

21

Using the Interrupts


PORTB INTCON CHANGE
An input change on PORTB<7:4> sets flag
bit, RBIF (INTCON<0>).
The interrupt can be enabled/disabled by
setting/clearing enable bit, RBIE
(INTCON<4>).

22

Using the Interrupts


The interrupt function is designated by preceding it with
interrupt.
In the interrupt service routine functions can be specified by
preceding each with the proper name like RBIF for the Port B
change interrupt (RB4-B7)
An interrupt must be specifically enabled (For example
RBIE=1 for enabling Port B change interrupt) and interrupts
must be globally enabled (GIE=1). The GLOBAL
enable/disable controls whether any interrupts are serviced.
If interrupts are disabled and an interrupt event happens, then
the interrupt function will be called when interrupts are
enabled. If multiple interrupt events of the same type happen
while interrupts are disabled, then the interrupt function is
called only once when interrupts are enabled.

23

Using the Interrupts


In the case of Timer Interrupts, interrupts are
disabled before the timer is read and combined
with the overflow count.
This is done to prevent the following situation:
The timer value is read and it is 65535
The overflow interrupt happens and the counter
is incremented to 1
The program continues and reads the counter
as 1
The time is an assumed to be 65536+65535
when in fact the correct time is 65535
24

Using the Interrupts

An example (Using RB interrupts, continues on next slide):

#include <htc.h>
#include <pic16f877a.h>
#define _XTAL_FREQ 20000000 // Set the oscillator frequency to 20MHz
int i=0;
int j=0;
//---Function Definition----//--Interrupt Service function-interrupt ISR (void) // Interrupt function definition
{
if (RBIF) // If the RB change flag is 1, do .....
{
RBIE=0; //Disable RB change interrupt
{
while (!RB7); //Detect Pin B7 to be logic low (Falling Edge)
__delay_ms(100);
PORTC=j;
j++;
}
RBIF=0; // Reset the external interrupt flag
RBIE=1; // RE-Enable RB change interrupt
}
GIE=1; //Enable Global Interrupt
}

25

Using the Interrupts

An example (Using RB interrupts, continued from previous slide):

//--Main Funtion -void main(void)


{
ADCON1 = 0b00000111; //Set Port A as digital I/O
TRISA=0xFF; // Ser PORT A as an OUTPUT
TRISB=0xF0; // Set PORT B as an IN/OUTPUT
nRBPU=0; //Enable Port B Internal Pull Up Resistors
TRISC=0; // Set PORT C as an OUTPUT
PORTC=0; // Set the value of PORT C to 0
INTE=1; // Enable external interrupts from RB0
RBIE=1; //Enable the RB port change interrupt
GIE=1; // Global interrupt enable
RBIF=0; //Clear RB port change interrupt flag
while(1) //Keeps running
{
PORTB++;// Increase the PORT B value by 1.
for(i=0;i<30000;i++); // a simple delay
}
}

26

Using the Interrupts


In this example, the RB interrupt is used
The input of pins B4 to B7 are monitored
using this interrupt
Falling edge will trigger the interrupt
A falling edge at pin B7 will increase the
counter which output to Port C (Can be 8
LEDs or BCD 7 segment)
And now construct the circuit for this
program
27

Using the Interrupts

Another example (Using Timer1 interrupts, continues on next slide):

#include <htc.h>
#include <pic16f877a.h>
#define _XTAL_FREQ 20000000 // Set the oscillator frequency to 20MHz
char count1=0, count2=0;
//--Interrupt Service function-interrupt ISR(void) // Interrupt function definition
{
if (TMR1IF) // If the TMR1 Overflow flag is 1, do .....
{
TMR1IE=0; // TMR1 Overflow Interrupt Disable
TMR1ON=0; //Turn off Timer 1
RB0=!RB0; //Blinking the LED RB0
TMR1L=count1; //Change the counter values for Timer1
TMR1H=count2; //Change the counter values for Timer1
TMR1IF=0; // Reset the TMR1 Overflow interrupt flag
TMR1IE=1; // TMR1 Overflow Interrupt Enable
TMR1ON=1; //Turn on Timer 1
}
GIE=1; //Enable back the global interrupt inputs, if not interrupt only happens for once! HahA!
}

28

Using the Interrupts


Another example (Using Timer1 interrupt to generate pulse,
continued from previous slide and continues on next slide):
void main (void) //--Main Funtion -{ unsigned int reading=0;
TRISA=0xFF; // Ser PORT A as an INPUT
TRISB=0xF0; // Set PORT B as an IN/OUTPUT
nRBPU=0;
ADCON1=0b01001110; //Set ADFM (bit 7 of ADCON1) to 0 for left justified
//Only RA0 is selected as analog input
ADCON0=0b11000001;
T1CKPS1 = 0; /* Prescaler of 1 */
T1CKPS0 = 0; /* Prescaler of 1 */
TMR1CS = 0; /* Select internal Clock source */
TMR1ON = 1; /* Enable timer1 */

29

Using the Interrupts

Another example (Using Timer1 interrupts, continued from previous slide):


TMR1IE = 1; /* Enable timer1 interrupts */
TMR1L = 0x00; /* Low byte */
TMR1H = 0x00; /* High byte */
GIE=1; // Global interrupt enable
TMR1IF=0; //Clear TMR1 interrupt flag
PEIE=1; //Peripheral Interrupt Enable
while (1)
{
__delay_ms(100);
ADCON0=ADCON0|1;
GO = 1; //Start A/D Conversion
while(GO==1); //Wait end of conversion (conversion complete)
reading = (65535-ADRESH*255); //Start A/D conversion and read the data
count1 = reading%256 ;
count2 = reading/256.0;
}

}
30

Using the Interrupts


In this example, the Timer1 interrupt is used
The interrupt will be triggered when Timer1 overflows
Each time the Timer1 interrupt is triggered, the LED at
Pin RB0 will change the lighting pattern
The counter values for Timer1 is changed according to
the reading from ADC
So the input from ADC will affect the speed of the LED
blinking
And now construct the circuit for this program
Dont forget, enable the Peripheral Interrupt Enable bit
(PEIE, bit 7 of INTCON register) if you want to use
interrupt from Timers (1&2)
31

Using the Interrupts

Another example (Using Timer0 interrupt to generate pulse, continues on


next slide):

#include <htc.h>
#include <pic16f877a.h>
#define _XTAL_FREQ 20000000 // Set the oscillator frequency to 20MHz
char count1=0, count2=0;
//--Interrupt Service function-interrupt ISR(void) // Interrupt function definition
{
if (TMR0IF) // If the TMR0 Overflow flag is 1, do .....
{
TMR0IE=0; // TMR0 Overflow Interrupt Disable
RB0=!RB0; //Blinking the LED RB0
if (count2++%2)
TMR0=count1; //Change the counter values for Timer0
else
TMR0=255-count1; //Change the counter values for Timer0
TMR0IF=0; // Reset the TMR0 Overflow interrupt flag
TMR0IE=1; // TMR0 Overflow Interrupt Enable
}
GIE=1;
}

32

Using the Interrupts


Another example (Using Timer0 interrupt to generate pulse,
continued from previous slide and continues on next slide):
//--Main Funtion -void main(void)
{ TRISA=0xFF; // Ser PORT A as an INPUT
TRISB=0xF0; // Set PORT B as an IN/OUTPUT
ADCON1=0b01001110; //Set ADFM (bit 7 of ADCON1) to 0 for left justified
//Only RA0 is selected as analog input
ADCON0=0b11000001;
T0CS = 0;
PSA = 0;
PS2 = 1;
PS1 = 1;
PS0 = 0;

/* Select internal Clock source */


/* Prescaler is assigned to the Timer0 module */

/* Set prescaler rate to 1:128 */

33

Using the Interrupts


Another example (Using Timer0 interrupt to
generate pulse, continued from previous slide):
TMR0IE = 1; /* Enable timer0 interrupts */
TMR0 = 0x00; /* Timer0 Counter */
GIE=1; // Global interrupt enable
TMR0IF=0; //Clear TMR1 interrupt flag
PEIE=1; //Peripheral Interrupt Enable
while (1)
{
__delay_ms(100);
ADCON0=ADCON0|1;
GO = 1; //Start A/D Conversion
while(GO==1); //Wait end of conversion (conversion complete)
count1 = 255-ADRESH; //Start A/D conversion and read the data
}
}
//End of program

34

Using the Interrupts


In this example, the Timer0 interrupt is used for
generating a pulse with varying pulse width
The interrupt will be triggered when Timer0 overflows
Each time the Timer0 interrupt is triggered, the LED at
Pin RB0 will turn on and off alternately
The pulse width is changed according to the reading
from ADC
So the input from ADC will affect the ON time of the LED
Tap the pin of RB0 to an oscilloscope to check the
waveform
And now construct the circuit for this program
35

Using the Interrupts

Another example (Using Timer2 interrupt to generate pulse, continues on


next slide):

#include <htc.h>
#include <pic16f877a.h>
#define _XTAL_FREQ 20000000 // Set the oscillator frequency to 20MHz
//--Interrupt Service function-interrupt ISR(void) // Interrupt function definition
{ if (TMR2IF) // If the TMR2 Overflow flag is 1, do .....
{
TMR2IE=0; // TMR2 Overflow Interrupt Disable
RB2=!RB2; //Blinking the LED RB2
TMR2IF=0; // Reset the TMR2 Overflow interrupt flag
TMR2IE=1; // TMR2 Overflow Interrupt Enable
}
GIE=1;
}
36

Using the Interrupts

Another example (Using Timer2 interrupt to generate pulse, continued from previous
slide):

//--Main Funtion -void main(void)


{
TRISC=0x00; //Port C as outputs
TRISB=0x00; //Port B as outputs
T2CON = 0b00001001; // Timer 2 control register
//TOUTPS3:TOUTPS0: Timer2 Output Postscale Select to 1:2
//T2CKPS1:T2CKPS0: Timer2 Clock Prescale Select to 4
TMR2IE = 1; /* Enable timer0 interrupts */
PR2 = 0xA0; /* Timer0 Counter */
GIE=1; // Global interrupt enable
TMR2IF=0; //Clear TMR1 interrupt flag
TMR2ON=1;
//Turn on Timer 2
PEIE=1; //Peripheral Interrupt Enable
while (1); //Run Run Run!
}
//End of Program

37

Using the Interrupts

The previous example is modified to use the Timer2 interrupt for


generating a pulse
The interrupt will be triggered when Timer2 overflows
Each time the Timer2 interrupt is triggered, the LED at Pin RB2 will
turn on and off alternately (Toggling)
The Timer2 Control Register, T2CON sets Timer 2 with pre-scaler of
4, counting from 0 to A0h, post-scaler is 2, so every 2 times Timer 2
overflows, an interrupt is generated
If the clock frequency is 20MHz, the instruction clock frequency is
5MHz (divide by 4)
Instruction clock period is 0.2 s, the time taken for Timer 2 to
overflow = 160 x 4 x 2 x 0.2 = 256 s
Tap the pin RB2 to an oscilloscope to check the waveform

38

Using the Interrupts (Output to


Virtual
Terminal)
Do this example (Continues on next slide):
#include <htc.h>
#include <pic16f877a.h>
#include <stdio.h>
#include <\Program Files\HI-TECH Software\PICC\9.81\samples\usart\usart.c>
#define _XTAL_FREQ 20000000
#define PUSH_BUTTON RB6
long int overflow_count;
void init_rs232()
{
BRGH = 1;
SPBRG = 129;
TX9 = 0;
SYNC = 0;
SPEN = 1;
TXEN = 1;
CREN = 1;
SREN = 0;
TXIE = 0;
RCIE = 0;
}

// set baud rate: Fosc=20Mhz, BR=9600


// ninebits?1:0,,,8- or 9-bit transmission
// asynchronous
// enable serial port pins
// enable the transmitter & (automatically)TXIF=1
// enable reception
// no effect
// disable tx interrupts
// disable rx interrupts

39

Using the Interrupts (Output to


Virtual Terminal)
Do this example (Continues from previous slide):

interrupt ISR(void) // Interrupt function definition


{
if (TMR1IF) // If the TMR1 Overflow flag is 1, do .....
{
TMR1IE=0; // TMR1 Overflow Interrupt Disable
overflow_count++;
TMR1IF=0; // Reset the TMR1 Overflow interrupt flag
TMR1IE=1; // TMR1 Overflow Interrupt Enable
}
GIE=1;
}
void main( )
{ unsigned long int time ; //32 bit integer data
init_rs232();
TRISB=0xF0; // Set PORT B as an IN/OUTPUT
nRBPU=0;
T1CKPS1 = 0; /* Prescaler of 1 */
T1CKPS0 = 0;
/* Prescaler of 1 */
TMR1CS = 0;
/* Select internal Clock source */
TMR1ON = 1; /* Enable timer1 */
TMR1IE = 1; /* Enable timer1 interrupts */
TMR1L = 0x00; /* Low byte */
TMR1H = 0x00; /* High byte */
GIE=1; // Global interrupt enable
TMR1IF=0; //Clear TMR1 interrupt flag
PEIE=1; //Peripheral Interrupt Enable
while(1)
{ while(PUSH_BUTTON);// Wait for press
TMR1H=0;
TMR1L=0;
overflow_count=0;
while(!PUSH_BUTTON);//Wait for release
GIE=0; //Disable all interrupts
time = TMR1H*256+TMR1L;
time = time + (overflow_count<<16);
time -= 15; // subtract overhead
printf("Time is %lu.%06lu seconds.\r\n", time/5000000, (time/5)%1000000);
}
}

40

Using the Interrupts (Output to


Virtual Terminal)
In this example, the timer 1 overflow interrupt will
be used to extend the timer 1 timer from 16 bits
to 32 bits by counting the number of times the
timer overflows.
When running the program, press the button and
release, the time it was held down is shown to 6
decimal places in the Monitor panel.
The %06lu format specifier is the same as %6lu
except leading zeros are printed.
41

Using the Interrupts (Output to


Virtual Terminal)
The formula time/5000000 in this printf
("Time is %lu.%06lu seconds.\r\n",
time/5000000, (time/5)%1000000);
Clock frequency is 20MHz, so instruction
clock frequency is 5MHz = 5000000 Hz
The timer value will increase by one, each
and everytime the instruction clock
complete a cycle
so the time to take for the timer value to
produce N cycles will become N/5000000
42

Summary
An interrupt causes the normal program
execution to be suspended and an interrupt
function is executed. Normal program execution
continues when the interrupt function returns.
The PIC16F877A has a number of interrupt
sources such as a timer overflow, an incoming
RS-232 character or a change on a pin (Port B4B7).
Interrupts are disabled by default.
They must be enabled before being used
43

Summary
To set up the interrupts, at first, clear the
interrupt flags and enable the interrupts at the
main function
For interrupt service routine, the function type
should be interrupt
In the interrupt service routine function, disable
the interrupts before doing the job
After finishing the jobs in interrupt service
routine, clear the interrupt flag and re-enable the
interrupts before leaving the interrupt service
routine
44

You might also like