How To Write ISR Handlers

Previous Tutorial Previous Tutorial Tutorial 8 Next Tutorial Next Tutorial
How To Write ISR Handlers
PIC Microcontrollers Course Home Page 🏠

 

In this tutorial, we’ll discuss a few guidelines to follow while writing ISR handlers. Which you can use as a guide for the upcoming tutorials. We’ll be writing ISR routines for PIC microcontrollers in MPLAB IDE with XC8 compiler. Let’s see how to properly write ISR handlers!


  Hold The Interrupt Logic Diagram  

 

The interrupt logic circuitry is the first thing to consider before planning for any interrupt-driven system. This diagram tells you everything about the interrupt system implemented within your microcontroller which typically differs from an MCU chip to another. That’s why you should loop-up this diagram in the microcontroller’s datasheet. Here is the interrupt logic diagram for our MCU chip.

Interrupt Circuitry PIC16F

  Or Equivalently  

Interrupt Circuitry In Microcontrollers


  Enable The Interrupts You Need  

 

To enable a specific interrupt, you should set all the enable bits in the way between your device/peripheral and the CPU. For example, let’s enable the CCP1 interrupt. You’ll then have to set the following bits CCP1IE, PEIE, and GIE. This could be easily done with the following 3-lines of code.


  Write The ISR Handler Definition  

 

The definition of the ISR handler routine is syntactically written as follows

*Update: it turns out to be some changes has been made to the identifier keyword for the interrupt function in newer versions of xc8 compiler. The version I used while crafting this series of tutorials was v1.34

All in all, new versions define the ISR handler as follows

 


   Check The Flags   

 

As we’ve stated earlier that the interrupts in our MCU are non-vectored. That’s why we must poll (check) the flags. This could be easily done with consecutive if-statements. Consider a system in which we’re handling a couple of interrupts sources ADC & EEPROM. The ISR would be written as follows


   Write The Handler Itself   

 

The code between the curly braces { } of each if-statement is the handler c-code (program) to be executed when a specific interrupt occurs. Every event is handled in a different way through your project as we’ll see in future tutorials. For now, all you should know is that the handler code is everything between the if-statement’s braces.


   Keep It Elegant, Simple & Quick!   

 

ISR handlers are obviously the main source of bugs and problems. If it’s poorly written, it’ll turn out to be a real nightmare. You’ll be left off drowning in a see of bugs which could be solved indeed. But why to do so if we can easily avoid such a situation in the first place?!

Carefully design and plan for your interrupt-driven system, then writing the code for it. Try following consistent conventions and effectively comment your code.

In many situations, your system will be receiving an insane amount of interrupt signals. If it takes too long time to execute your ISR handler, then you’ll end up having a trapped system that keeps performing interrupt service routines without making significant advances in the main program itself. As if the main function is nearly blocked!

That’s why your ISR handlers should be quick to execute. So you should never use time delays within an ISR handler.


  Leave A Couple Of IO-Pins Free  

 

IO-Pins can improve your experience with interrupts significantly. And here are a couple of ways in which you can take advantage of a Free IO-Pin in your MCU.

The 1st way is to use the IO pin for debugging an ISR handler. Sometimes we’re absolutely curious and have no idea whether an ISR has been executed or not!

In this situation you can hook an LED to an IO-Pin, then drive thin pin High at the beginning of the ISR handler (which you suspect), and drive it low upon exiting this ISR. Finally, check the LED behavior. If it blinks, then it’s OK. You should notice that the ISR handler are very fast so you’ll have to add a time delay in order to see the blink effect. Otherwise, you’d better hook an Oscilloscope (CRO) to monitor the IO-Pin behavior.

Using Free IO Pins While Developing ISR Handlers
Using Free IO Pin While Developing ISR Handlers For Checking Validity

The 2nd way is to use the IO pin for measuring the execution time of an ISR handler. We’ve stated that the ISR execution speed is a very important parameter which we’d always prefer to monitor.

A very easy way to do so is by hooking an IO pin to a CRO probe. Drive the pin high at the beginning of the ISR, then drive it low upon exiting the ISR. The resulting pulse will tell you exactly how long did it take the CPU to execute the ISR handler.

Measuring The Execution Time Of ISR Handlers - Embedded Systems Tutorials With PIC Microcontrollers
Using Free IO Pin For Measuring The Execution Time Of ISR Handlers

 

Note !

*Update 04-2019: I don’t why they have got to change the identifier for the interrupts service routines. I’ve received many emails complaining about this error. All you’ve to do is to write your ISR with the following format.

*Update 09-2018: it turns out to be some changes has been made to the identifier keyword for the interrupt function in newer versions of xc8 compiler. The version I used while crafting this series of tutorials was v1.34

All in all, new versions define the ISR handler as follows

 

 

PIC Microcontrollers Course Home Page 🏠
Previous Tutorial Previous Tutorial Tutorial 8 Next Tutorial Next Tutorial
Share This Page With Your Network!

Khaled Magdy

I'm an embedded systems engineer doing both Software & Hardware. I'm an EE guy who studied Computer Engineering, But I'm also passionate about Computer Science. I love reading, writing, creating projects and Technical training. A reader by day a writer by night, it's my lifestyle. You can view my profile or follow me via contacts.

You may also like...

2 Responses

  1. Ayman Hussien says:

    void __interrupt ISR (void)
    {
    if (RCIF == 1){
    UART_Buffer = RCREG;
    PORTB = UART_Buffer;
    RCIF = 0;
    }
    }
    at building i receive these 2 errors:
    slave.c:49:7: error: variable has incomplete type ‘void’
    void __interrupt ISR (void)
    ^
    slave.c:49:18: error: expected ‘;’ after top level declarator
    void __interrupt ISR (void)

    Why?

    • Nash says:

      I think it’s because you used __interrupt instead of __interrupt()

      From my understanding, there are two ways to declare an interrupt:

      1)

      void interrupt name_of_ISR(void)
      {
      //insert ISR routines here and clear flags
      }

      2)

      void __interrupt() name_of_interrupt(void)
      {
      //insert ISR routines here and clear flags
      }

Leave a Reply

%d bloggers like this: