Embedded Priority Interrupts

Program Download:

Main C File
Priority_Interrupts.c
LED_Int_Pri.hex

The Software
           There are two main portions of code that we are concerned with:
    -Main Loop
    -Two Interrupt Routines



           Just as before the first portion of code sets up the interrupts and priority levels and then goes into a forever while loop running the 'knightrider' sequence of the LED back and forth on the LED bar.

Main Loop

------------« Begin Code »------------
#include <p18f452.h>
#include <delays.h>
void InterruptHandlerHigh (void);
void main(void){
unsigned int i = 0;
unsigned int j = 0;
unsigned int led_cnt = 0;
unsigned int direction = 0;
TRISC = 0x00;
TRISD = 0x00;
                     //Setup Interrupts
RCON = 0b10000000;
INTCON = 0b11010000;
INTCON2 = 0b00000000;
INTCON3 = 0b00001000;
     while(1){
          Delay10KTCYx(33);
          switch(led_cnt){
          case 0 : PORTC = 0x01;
                     PORTD = 0x00;
                     break;
          case 1 : PORTC = 0x02;
                     PORTD = 0x00;
                     break;
          case 2 : PORTC = 0x04;
                     PORTD = 0x00;
                     break;
          case 3 : PORTC = 0x08;
                     PORTD = 0x00;
                     break;
          case 4 : PORTC = 0x00;
                     PORTD = 0x01;
                     break;
          case 5 : PORTC = 0x00;
                     PORTD = 0x02;
                     break;
          case 6 : PORTC = 0x00;
                    PORTD = 0x04;
                     break;
          case 7 : PORTC = 0x00;
                    PORTD = 0x08;
                     break;
          case 8 : PORTC = 0x10;
                    PORTD = 0x00;
                     break;
          case 9 : PORTC = 0x20;
                    PORTD = 0x00;
                     break;
          default : PORTC = 0x00;
                    PORTD = 0x00;
                     break;
          }
          if(direction == 0)
               led_cnt++;
          else
               led_cnt--;
          if(led_cnt == 10){
               led_cnt = 9;
               direction = 1;
          }
          else if(led_cnt == -1){
               led_cnt = 0;
               direction = 0;
          }
     }
}
------------« End Code »------------

           Using a counter and direction and some math, a control loop is formed that makes a single led bit move back and forth on the LED bar (PORTC and PORTD). The interrupts are setup at the very beginning to get everything ready. INTCON, INTCON2, INTCON3 and RCON are the main interrupt registers used.

Two Interrupt Service Routines

------------« Begin Code »------------
//**BEGIN INTERRUPT CONTROL**
#pragma code InterruptVectorHigh = 0x08 //interrupt pointer address (0x08 high priority)
void InterruptVectorHigh (void)
{
          _asm                    //assembly code starts
          goto InterruptHandlerHigh //interrupt control
          _endasm                     //assembly code ends
}
#pragma code
#pragma interrupt InterruptHandlerHigh //end interrupt control

#pragma code InterruptVectorLow = 0x18 //interrupt pointer address (0x18 low priority)
void InterruptVectorLow (void)
{
          _asm                    //assembly code starts
          goto InterruptHandlerLow //interrupt control
          _endasm                     //assembly code ends
}

#pragma code
#pragma interrupt InterruptHandlerLow //end interrupt control
//**END INTERRUPT CONTROL**
void InterruptHandlerHigh() // Declaration of InterruptHandler
{
     if(INTCONbits.INT0IF){ //if INT0IF interrupt flag is set
     PORTC = 0x00;
     PORTD = 0x00;
     for(i=0;i<2;i++){
               Delay10KTCYx(50);
               PORTC = 0x00;
               PORTD = 0x00;
               Delay10KTCYx(50);
               PORTC = 0x3F;
               PORTD = 0x0F;
          }
     INTCONbits.INT0IF = 0; //Clear INT0IF Flag
     }
     INTCONbits.GIE = 1; //Re-enable all interrupts
return;
}

void InterruptHandlerLow() // Declaration of InterruptHandler
{
     if(INTCON3bits.INT1IF){ //If INT1IF interrupt flag is set
          for(j=0;j<4;j++){
               PORTC = 0x00;
               PORTD = 0x00;
               Delay10KTCYx(20);
               ...
               ..
               ...
               ..
               PORTC = 0x3F;
               PORTD = 0x0F;
               Delay10KTCYx(20);
          }
          INTCON3bits.INT1IF = 0; //Clear INT1IF Flag
     }
INTCONbits.GIEL = 1;          //Re-enable all interrupts
return;
}
------------« End Code »------------

           The low and high priority interrupt service routines occur when a hardware interrupt is detected. Then the PIC looks at the interrupt vector: 0x08 or 0x18 and follows the goto that leads to the InterruptHandlerHigh() or InterruptHandlerLow() function. These functions execute and then the interrupt flags are cleared and interrupts re-enabled. Then the program returns to the exact same state it was when main was looping forever.
           The important key here to remember is that even though there are two interrupts being used, one is more important to the microcontroller than the other. Anytime the High Priority interrupt is triggered, its code executes because it has the highest priority. So even if the low priority interrupt is executing, the high priority interrupt can override it.



;