PIC16F877A – Interrupt Tutorial

This article is a continuation of the series of tutorials on the PIC16F877A Microcontroller. The aim of this series is to provide easy and practical examples that anyone can understand. In our previous tutorial, we have seen PIC16F877A I2C Tutorial. Now we are going to see PIC16F877A Interrupt Tutorial.

Prerequisites

Before learning PIC16F877A Interrupt Tutorial, we should know the basic interrupts and their functioning. Please refer to these below links.

PIC16F877A Interrupt Tutorial

As the name suggests Interrupts are special events that require immediate attention, it stops a microcontroller/microprocessor from the running task and serves a special task known as Interrupt Service Routine (ISR) or Interrupt Handler.

PIC 16F877A has the following 15 interrupt sources :

  • External
  • Timer 0
  • Timer 1
  • RB Port Change
  • Parallel Slave Port Read/Write
  • A/D Converter
  • USART Receive
  • USART Transmit
  • Synchronous Serial Port
  • CCP1 (Capture, Compare, PWM)
  • CCP2  (Capture, Compare, PWM)
  • TMR2 to PR2 Match
  • Comparator
  • EEPROM Write Operation
  • Bus Collision

In this tutorial, we will see USART Interrupts, Timer Interrupts, External Interrupts.

Registers Used for Interrupts

  • INTCON
  • OPTION_REG
  • PIE1
  • PIR1
  • PIE2
  • PIR2

INTCON Register

The INTCON register is a readable and writable register, which contains various enable and flag bits for the TMR0 register overflow, RB port change and external RB0/INT pin interrupt.

GIE: Global Interrupt Enable bit

1-Enables all unmasked interrupts
0-Disables all interrupts

PIE: Peripheral Interrupt Enable bit

1-Enables all unmasked peripheral interrupts
0-Disables all peripheral interrupts

TMR0IE: TMR0 Overflow Interrupt Enable bit

1-Enables the TMR0 interrupt
0-Disables the TMR0 interrupt

INTE: RB0/INT External Interrupt Enable bit

1 = Enables the RB0/INT external interrupt
0 = Disables the RB0/INT external interrupt

RBIE: RB Port Change Interrupt Enable bit

1 = Enables the RB port change interrupt
0 = Disables the RB port change interrupt

TMR0IF: TMR0 Overflow Interrupt Flag bit

1-TMR0 register has overflowed (must be cleared in software)
0-TMR0 register did not overflow

INTF: RB0/INT External Interrupt Flag bit

1 = The RB0/INT external interrupt occurred (must be cleared in software)
0 = The RB0/INT external interrupt did not occur

RBIF: RB Port Change Interrupt Flag bit

1 = At least one of the RB7:RB4 pins changed state; a mismatch condition will continue to set the bit. Reading PORTB will end the mismatch condition and allow the bit to be cleared (must be cleared in software).
0 = None of the RB7:RB4 pins have changed state

OPTION_REG

The OPTION_REG Register is a readable and writable register, which contains various control bits to configure the TMR0 Prescaler/WDT Postscaler (single assignable register known also as the Prescaler), the external INT interrupt, TMR0, and the weak pull-ups on PORTB.

RBPU: PORTB Pull-up Enable bit (This bit is not used for timers)

1 = PORTB pull-ups are disabled
0 = PORTB pull-ups are enabled by individual port latch values

INTEDG   Interrupt Edge Select bit

1 = Interrupt on the rising edge of RB0/INT pin
0 = Interrupt on the falling edge of RB0/INT pin

T0CS: TMR0 Clock Source Select bit

1 = Transition on T0CKI pin
0 = Internal instruction cycle clock (CLKO)

T0SE: TMR0 Source Edge Select bit

1 = Increment on high-to-low transition on T0CKI pin
0 = Increment on low-to-high transition on T0CKI pin

PSA: Prescaler Assignment bit

1 = Prescaler is assigned to the WDT
0 = Prescaler is assigned to the Timer0 module

PS2:PS0: Prescaler Rate Select bits

Note: There is only one Prescaler available which is mutually exclusively shared between the Timer0 module and the Watchdog Timer. A Prescaler assignment for the Timer0 module means that there is no Prescaler for the Watchdog Timer and vice versa. This Prescaler is not accessible but can be configured using PS2:PS0 bits of OPTION_REG.

PIE1 Register

The PIE1 register contains the individual enable bits for the peripheral interrupts.

PSPIE: Parallel Slave Port Read/Write Interrupt Enable bit(1)

1 = Enables the PSP read/write interrupt
0 = Disables the PSP read/write interrupt

Note (1): PSPIE is reserved on PIC16F873A/876A devices; always maintain this bit clear.

ADIE: A/D Converter Interrupt Enable bit

1 = Enables the A/D converter interrupt
0 = Disables the A/D converter interrupt

RCIE: USART Receive Interrupt Enable bit

1 = Enables the USART to receive interrupt
0 = Disables the USART receive interrupt

TXIE: USART Transmit Interrupt Enable bit

1 = Enables the USART to transmit interrupt
0 = Disables the USART transmit interrupt

SSPIE: Synchronous Serial Port Interrupt Enable bit

1 = Enables the SSP interrupt
0 = Disables the SSP interrupt

CCP1IE: CCP1 Interrupt Enable bit

1 = Enables the CCP1 interrupt
0 = Disables the CCP1 interrupt

TMR2IE: TMR2 to PR2 Match Interrupt Enable bit

1 = Enables the TMR2 to PR2 match interrupt
0 = Disables the TMR2 to PR2 match interrupt

TMR1IE: TMR1 Overflow Interrupt Enable bit

1 = Enables the TMR1 overflow interrupt
0 = Disables the TMR1 overflow interrupt

PIR1 Register

The PIR1 register contains the individual flag bits for the peripheral interrupts.

Note: 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.

PSPIF: Parallel Slave Port Read/Write Interrupt Flag bit(1)

1 = A read or a write operation has taken place (must be cleared in software)
0 = No read or write has occurred

Note (1): PSPIF is reserved on PIC16F873A/876A devices; always maintain this bit clear.

ADIF: A/D Converter Interrupt Flag bit

1 = An A/D conversion completed
0 = The A/D conversion is not complete

RCIF: USART Receive Interrupt Flag bit

1 = The USART receive buffer is full
0 = The USART receive buffer is empty

TXIF: USART Transmit Interrupt Flag bit

1 = The USART transmit buffer is empty
0 = The USART transmit buffer is full

SSPIF: Synchronous Serial Port (SSP) Interrupt Flag bit

CCP1IF: CCP1 Interrupt Flag bit

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

PIE2 Register

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

CMIE: Comparator Interrupt Enable bit

1 = Enables the comparator interrupt
0 = Disable the comparator interrupt

EEIE: EEPROM Write Operation Interrupt Enable bit

1 = Enable EEPROM write interrupt
0 = Disable EEPROM write interrupt

BCLIE: Bus Collision Interrupt Enable bit

1 = Enable bus collision interrupt
0 = Disable bus collision interrupt

CCP2IE: CCP2 Interrupt Enable bit

1 = Enables the CCP2 interrupt
0 = Disables the CCP2 interrupt

PIR2 Register

The PIR2 register contains the flag bits for the CCP2 interrupt, the SSP bus collision interrupt, EEPROM write operation interrupt and the comparator interrupt.

CMIF: Comparator Interrupt Flag bit

1 = The comparator input has changed (must be cleared in software)
0 = The comparator input has not changed

EEIF: EEPROM Write Operation Interrupt Flag bit

1 = The write operation completed (must be cleared in software)
0 = The write operation is not complete or has not been started

BCLIF: Bus Collision Interrupt Flag bit

1 = A bus collision has occurred in the SSP when configured for I2C Master mode
0 = No bus collision has occurred

CCP2IF: CCP2 Interrupt Flag bit

Serial Interrupt – PIC16F877A Interrupt Tutorial

Circuit Diagram

LCD:

RS –  RC0

RW – RC1

EN – RC2

Data Lines – Port D

UART:

TX – RC6

RX – RC7

Programming

In this program, I have added only the main code. You can find the header files and full project here. My PCLK is 11.0592MHz.

#include<pic.h>
#include"serial.h"
#include"lcd.h"

__CONFIG( FOSC_HS & WDTE_OFF & PWRTE_OFF & CP_OFF & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);

#define delay for(z=0;z<=50000;z++)

unsigned int z;

void interrupt ser();

void main()
{
TRISD=0;
    INTCON|=0b11000000;
    PIE1=0b00100000;
    lcd_init();
    serial_init();
    while(1) {
        cmd(0x01);
    }
}

void interrupt ser()
{
    unsigned char a = RCREG;
    tx(a);
    cmd(0x80);
    show("Serial interrupt");
    cmd(0xc0);
    show("  Key : ");
    cmd(0xc8);
    dat(a);
    delay;delay;
}   
            

Output

Here I pressed ‘O’ in UART Terminal. Then it is displayed in LCD Module.

Serial Interrupt - PIC16F877A Interrupt Tutorial

Timer Interrupt – PIC16F877A Interrupt Tutorial

Circuit Diagram

LCD:

RS –  RC0

RW – RC1

EN – RC2

Data Lines – Port D

Programming

In this program, I have added only the main code. You can find the header files and full project here. My PCLK is 11.0592MHz.

#include<pic.h>
#include"lcd.h"

#define delay for(z=0;z<=50000;z++)

unsigned int z;

int a=0,b=0,c=0;

void interrupt tmr0()
{
    if(TMR0IF) {
        a++;
        if(a==42)                   //1sec
        {
            cmd(0x80);
            show("Timer 0 interupt");
            a=0;
            delay;
        }
        TMR0IF=0;   
    } else if(TMR1IF) {
        b++;
        if(b==84)                   //2secs
        {
            cmd(0xc0);
            show("Timer 1 interupt");
            b=0;
            delay;
        }
        TMR1IF=0;   
    } else if(TMR2IF) {
        c++;
        if(c==2025)                 //3secs
        {
            cmd(0x80);
            show("Timer 2 interupt");
            c=0;
            delay;
        }
        TMR2IF=0;   
    }
            
}

void intr_init()
{
    INTCON=0xe0;
    PIE1=0x03;
}

void timer_init()
{
    OPTION_REG=0b00000111;      //internal clk,rising edge,prescaler with tim0,256
    T1CON=0b00000001;           //prescale=1,oscilator is off,internal clk,timer on
    T2CON=0b01111100;           //postscale=16,prescale=1,timer on
}

void main()
{
    lcd_init();
    timer_init();
    intr_init();
    while(1) {
        cmd(0x01);
    }
}
        
        

Output

In this tutorial timer 0 generates an interrupt on 1sec. Timer 1 generates interrupts in 2 secs. Timer 2 generates 3secs. Each interrupts will display the interrupt in LCD Module.

Timer Interrupt - PIC16F877A Interrupt Tutorial[ Please find the output image Here ]

External Interrupt – PIC16F877A Interrupt Tutorial

Circuit Diagram

LED – RD0

Switch – RB0

PIC16F877A Interrupt Tutorial

Programming

You can find the header files and full project here. My PCLK is 11.0592MHz.

#include<pic.h>

#define LED PORTD

void interrupt  ISR(void)
{
    unsigned int i,j;
    LED=0X55;
    for(i=0;i<600;i++)
    for(j=0;j<200;j++);
    INTF=0;
}


void main(void)
{
    LED=0;
    TRISB0=1;
    TRISD=0;
    OPTION_REG=0X00;        //falling edge int @ enable pullup portb
    INTCON|=0Xd0;
    while(1) {
        LED=0x00;
    }
}

Output

Whenever I press the switch it generates the interrupt and glows the LED. The switch is connected to an External interrupt pin.

PIC16F877A Interrupt Tutorial[ Please find the output image Here ]

In our next tutorial, we will see how to use the multiple external interrupts in PIC16F877A.

You can also read the below tutorials.

Linux Device Driver TutorialsC Programming Tutorials
FreeRTOS TutorialsNuttX RTOS Tutorials
RTX RTOS TutorialsInterrupts Basics
I2C Protocol – Part 1 (Basics)I2C Protocol – Part 2 (Advanced Topics)
STM32 TutorialsLPC2148 (ARM7) Tutorials
PIC16F877A Tutorials8051 Tutorials
Unit Testing in C TutorialsESP32-IDF Tutorials
Raspberry Pi TutorialsEmbedded Interview Topics
Reset Sequence in ARM Cortex-M4BLE Basics
VIC and NVIC in ARMSPI – Serial Peripheral Interface Protocol
Bootloader TutorialsRaspberry PI Pico Tutorials
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
2
0
Would love your thoughts, please comment.x