Overview

In this tutorial, we will learn how to use an External Interrupt in PIC Microcontroller and why/where we will need them. This is a part of the sequence of PIC Tutorials in which we started learning PIC Microcontrollers from scratch; hence this tutorial assumes that you are familiar with how to program a PIC MCU using MPLABX.

Components required table

S.NoComponentsQuantitylink
1DSPIC33FJ64GS6061https://www.mouser.in/ProductDetail/Microchip-Technology-Atmel/dsPIC33FJ64GS606
2PICkit4 Programmer1https://www.amazon.in/MPLAB-PICkit4-in-Circuit-Debugger
3LED’S1https://www.amazon.in/Traffic-Lights-Signal-Module-Digital
4Push Button1https://robu.in/product/momentary-tactile-push-button
5Breadboard – 21https://www.amazon.in/Robotbanao-Solderless-MB102-Breadboard1
6Jumper wires1(set)https://www.amazon.in/YUVS-Jumper-Wires

Software Requirments

  • MPLAB X IDE
  • MPLAB X X16 Compailer

Circuit Diagram

Registers Used for Interrupts

  • ICxCON: INPUT CAPTURE x CONTROL REGISTER
  • IFS0: INTERRUPT FLAG STATUS REGISTER 0
  • IEC0: INTERRUPT ENABLE CONTROL REGISTER 0

ICxCON: INPUT CAPTURE x CONTROL REGISTER

IFS0: INTERRUPT FLAG STATUS REGISTER

IEC0: INTERRUPT ENABLE CONTROL REGISTER 0

  • PIC I/O Register Configurations
  • PIC I/O Register Configurations
RegisterDescription
TRISxUsed to configure the respective PORT as output/input
PORTxUsed to Read/Write the data from/to the Port pins
LATxUsed to Read/Write the data from/to the Port pins

Source code

Input and output selection

TRISGbits.TRISG3 = 0; // 0 as a output 1 as a input Led
TRISGbits.TRISG2 = 1; // 0 as a output 1 as a input Pushbutton
  • 1st set as input capture register
  • 2nd set as Capture mode, every rising edge or falling edge
  • 3rd Interrupt flag status for the selected channel
  • IC1IF: Input Capture Channel 1 Interrupt Flag Status bit
  • 4th Interrupt enables control for the selected channel
  • IC1IE: Input Capture Channel 1 Interrupt Enable bit

Example for interrupt Selection

    // set RD8 as interrupt pin  
    IC1CONbits.ICSIDL   = 0;    // Input Capture Registers
    IC1CONbits.ICM      = 1;    //  001 = Capture mode, every edge (rising and falling)
                                //  010 = Capture mode, every falling edge
                                //  011 = Capture mode, every rising edge
    IFS0bits.IC1IF      = 0;    // Interrupt request has not occurred 
                                //INTERRUPT FLAG STATUS
                                // Input Capture Channel 1 Interrupt Flag Status bit
                                // 1 = Interrupt request has occurred
                                // 0 = Interrupt request has not occurred
    IEC0bits.IC1IE = 1;         // Input Capture Channel 1 Interrupt Enable bit

Final Source Code

/*
 * File:   main.c
 * Author: Admin
 *
 * Created on 4 March, 2023, 5:59 PM
 */


#include "xc.h"
#include <p33FJ64GS606.h>
#include "stdio.h"
#include "stdlib.h"
#include <string.h>
#include <math.h>
#include <dsp.h>

#include "libpic30.h"

#define Led_High_A   LATGbits.LATG3  = 1;
#define Led_Low_A    LATGbits.LATG3  = 0;

#define Led_High_B   LATGbits.LATG2  = 1;
#define Led_Low_B    LATGbits.LATG2  = 0;

#define Led_High_C   LATDbits.LATD2  = 1;
#define Led_Low_C    LATDbits.LATD2  = 0;


_FOSCSEL(FNOSC_FRC & IESO_OFF);						// Internal FRC start-up without PLL,// no Two Speed Start-up
_FOSC(FCKSM_CSECMD & OSCIOFNC_ON & POSCMD_NONE);	// POSCMD_XT);// Clock switch enabled,// Primarly Oscillator XT
_FWDT(FWDTEN_OFF);									// Watchdog Timer disabled
_FICD(JTAGEN_OFF);									// & ICS_PGD3);// Disable JTAG
_FPOR(FPWRT_PWR128);								// Power up timer enabled by 128 mS



void initOscFreq(void);
void initInputCapture();


uint32_t Hal_Flag_1=0;
uint32_t Hal_Flag_2=0;
uint32_t Hal_Flag_3=0;


int main(void) {


// -------------- HALL Sensors ------------- //
#define HALL1					PORTDbits.RD8 		// Hall sensor one
#define HALL2					PORTDbits.RD9 		// Hall sensor two
#define HALL3					PORTDbits.RD10 		// Hall sensor three
// Ouputs
TRISGbits.TRISG3 = 0;							// Led_1
TRISGbits.TRISG2 = 0;							// Led_2
TRISDbits.TRISD2 = 0;							// Led

initOscFreq();									// Oscillator Initialization
initInputCapture();

    while(1)
    {

    }
}



void initInputCapture()
{
    
    // set RD8 as external interrupt pin  
    IC1CONbits.ICSIDL   = 0;    // Input Capture Registers
    IC1CONbits.ICM      = 1;    //  001 = Capture mode, every edge (rising and falling)
                                //  010 = Capture mode, every falling edge
                                //  011 = Capture mode, every rising edge
    IFS0bits.IC1IF      = 0;    // Interrupt request has not occurred 
                                //INTERRUPT FLAG STATUS
                                // Input Capture Channel 1 Interrupt Flag Status bit
                                // 1 = Interrupt request has occurred
                                // 0 = Interrupt request has not occurred
    IEC0bits.IC1IE = 1;         // Input Capture Channel 1 Interrupt Enable bit

    // set RD9 as external interrupt pin 
    IC2CONbits.ICSIDL = 0;
    IC2CONbits.ICM = 1;
    IFS0bits.IC2IF = 0;
    IEC0bits.IC2IE = 1;

    // set RD10 as external interrupt pin 
    IC3CONbits.ICSIDL = 0;
    IC3CONbits.ICM = 1;
    IFS2bits.IC3IF = 0;
    IEC2bits.IC3IE = 1;

    // set RD11 as external interrupt pin 
	IC4CONbits.ICSIDL = 0;
    IC4CONbits.ICM = 1;
    IFS2bits.IC4IF = 0;
    IEC2bits.IC4IE = 1;
    
 
}



//***************Function Definitions starts from here************************************
void initOscFreq(void)
{
	// Configure PLL prescaler, PLL postscaler, PLL divisor for FOsc=80Mhz and Fcy=40Mhz
	PLLFBD = 63;			// M = 65
	CLKDIVbits.PLLPOST=0;	// N2 = 2
	CLKDIVbits.PLLPRE=1;	// N1 = 3

	// Initiate Clock Switch to Internal FRC with PLL (NOSC = 0b001)
	__builtin_write_OSCCONH(0x01);
	__builtin_write_OSCCONL(OSCCON | 0x01);	//Clock witch Enable

	//OSCTUNbits.TUN = 0b111111;		//FRC tuning to 7.345Mhz	
	
    while (OSCCONbits.COSC != 0b001);	// Wait for Clock switch to occur
	while (OSCCONbits.LOCK != 1);		//wait till PLL is locked

	/* Now setup the ADC and PWM clock for 120MHz
    ** ((FRC * 16) / APSTSCLR ) = (7.37 * 16) / 1 = ~ 120MHz
	*/
	ACLKCONbits.FRCSEL = 1;			// FRC provides input for Auxiliary PLL (x16)
	ACLKCONbits.SELACLK = 1;		// Auxiliary Ocillator provides clock source for PWM & ADC
	ACLKCONbits.APSTSCLR = 7;		// Divide Auxiliary clock by 1 
	ACLKCONbits.ENAPLL = 1;			// Enable Auxiliary PLL 
	
	while(ACLKCONbits.APLLCK != 1);	// Wait for Aux. PLL to Lock  {{for Testing}}
    
//	REFOCONbits.ROON = 0;			//REF OSC o/p is enabled on REFCLKO pin
//	REFOCONbits.RODIV = 0;			//Output at REFCLKO pin is Fosc/2 i.e. 40Mz
}


// Hal Sensor External Inputs   
// Hall A Interrupt
void _ISR __attribute__((no_auto_psv)) _IC1Interrupt()
{
    IFS0bits.IC1IF = 0;
   Led_High_A 	= 1;
   Led_Low_B 	= 1;
   Led_Low_C	= 1;

}
// Hall B Interrupt
void _ISR __attribute__((no_auto_psv)) _IC2Interrupt()
{
    IFS0bits.IC2IF = 0;
     
   Led_High_B 	= 1; 
   Led_Low_A	= 1;
   Led_Low_C	= 1;

 
}

// Hall C Interrupt
void _ISR __attribute__((no_auto_psv)) _IC3Interrupt()
{
    IFS2bits.IC3IF = 0;
   Led_High_C 	= 1;
   Led_Low_A	= 1;
   Led_Low_B	= 1;


}



By Devilal

Leave a Reply

Your email address will not be published. Required fields are marked *