Interrupts

Interrupts can be easily handled by means of reserved words interrupt and iv. mikroC PRO for PIC implictly declares function interrupt which cannot be redeclared. Its prototype is:

void interrupt(void);

For P18 low priorty interrupts reserved word is interrupt_low:

void interrupt_low(void);

You are expected to write your own definition (function body) to handle interrupts in your application.

mikroC PRO for PIC saves the following SFR on stack when entering interrupt and pops them back upon return:

Disable Context Saving

Use the #pragma disablecontextsaving to instruct the compiler not to automatically perform context-switching.
This means that no register will be saved/restored by the compiler on entrance/exit from interrupt service routine, except STATUS, WREG and BSR registers in high priority interrupt ('Fast Register Stack').

This exception can be overridden by placing an asm RETFIE 0 instruction at the end of the high priority interrupt routine (with redirecting all routine exits to this instruction).
Thus, #pragma disablecontextsaving pragma enables the user to manually write code for saving registers upon entrance and to restore them before exit from interrupt.

P18 priority interrupts

  Note : For the P18 family both low and high interrupts are supported.
  1. function with name interrupt will be linked as ISR (interrupt service routine) for high level interrupt
  2. function with name interrupt_low will be linked as ISR for low level interrupt_low

If interrupt priority feature is to be used then the user should set the appropriate SFR bits to enable it. For more information refer to datasheet for specific device.

Function Calls from Interrupt

Calling functions from within the interrupt() routine is now possible. The compiler takes care about the registers being used, both in "interrupt" and in "main" thread, and performs "smart" context-switching between the two, saving only the registers that have been used in both threads.Check functions reentrancy.

Interrupt Handling

For the sake of interrupt handling convenience, new keywords, iv and ics, are introduced :

void Timer0_Interrupt() iv 0x000008 ics ICS_OFF {
  counter++;
  TMR0 = 96;
  INTCON = 0x20;
}

where :

As you can see, any valid routine name can be used as a interrupt routine name.
Bear in mind that appropriate interrupt vector address must be used (high priority interrupt vector is at 0x000008, while the low priority interrupt vector is at 0x000018) because in any other case compiler will report an error.

User can explicitly declare starting interrupt routine address using org directive :

void Timer0_Interrupt() org 0x600 iv 0x000008 {
  counter++;
  TMR0 = 96;
  INTCON = 0x20;
}  

In this way, the user can allocate the interrupt routine by its discretion, except for P16 family, where the interrupt routine must be allocated in the first bank.

Interrupt Examples

Here is a simple example of handling the interrupts from TMR0 (if no other interrupts are allowed):

void interrupt() {
  counter++;
  TMR0 = 96;
  INTCON = 0x20;
}

In case of multiple interrupts enabled, you need to test which of the interrupts occurred and then proceed with the appropriate code (interrupt handling):

void interrupt() {
  if (INTCON.TMR0IF) {
    counter++;
    TMR0 = 96;
    INTCON.TMR0IF = 0;
  }
  else if (INTCON.RBIF) {
    counter++;
    TMR0 = 96;
    INTCON.RBIF = 0;
  }
}
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code