Previous Tutorial | Tutorial 8 | 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!
[toc]
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.
Or Equivalently
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.
1 2 3 |
CCP1IE = 1; // CCP1 Interruot Enable Bit PEIE = 1; // Peripherals Interrupts Enable Bit GIE = 1; // Global Interrupts Enable Bit |
Write The ISR Handler Definition
The definition of the ISR handler routine is syntactically written as follows
1 2 3 4 |
void interrupt ISR() { } |
*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
1 2 3 4 |
void __interrupt ISR (void) { } |
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
1 2 3 4 5 6 7 8 9 10 11 |
void interrupt ISR() { if(ADCIF == 1) { // Do ABC... } if(EEIF == 1) { // Do XYZ... } } |
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 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.
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 | Tutorial 8 | Next Tutorial |
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?
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
}