Interruptions are one of the great things about microcontrollers, if you want to do something fast, reliable, and simple… well, not exactly simple in a programming language sense perhaps, but really simpler from the hardware perspective point of view. So, the main purpose of interruption is to interrupt your main program cycle and do whatever you want in case of that event (a timer has reached the settled time, a button has been pressed, and so on). Here is the picture from the mikroe ebook (www.mikroe.com), just because they really made quite nice pictures and quite a nice manual by the way.
Going further…
Two main things to keep in mind with interruptions – enable of interruption and the flag of the interruption. To enable interruption the one should set *IE bit to “1”, if the interruption event has happened then *IF bit will be settled by the controller to “1”. Some of main enables and flag could be found in the INTCON register:
• GIE – the global interruption enable
• PEIE – the periphery interruption enable bit
• T0IE – TMR0 overflow interruption
• INTE – the RB0 pin state change interruption
• RBIE – B port all pins interruptions
• T0IF – the flag indicating that TMR0 has the overflow condition
• INTF – the flag if the RB0 pin state is changed
• RBIF – similar to the previous but for all pins of the B port
From the picture, it is obvious that there are many more different interruptions packed to the controller, so my recommendation would be to check the datasheet for your particular controller and find the required register.
So in order to use an interruption, we need to set the global (or periphery) interruption bit to 1 (enable the main interruption switch) and then do the same with the required module. In this experiment what I wanted is to do similar stuff I did in the timer 0 experiment but with utilizing more advanced interruption technic.
As soon as you enabled GIE and your local interruption module the cpu will be checking with some internal clock period if the interruption event has happened, as it became the case the interruption post-processing procedure will be executed. In the code that procedure is called interrupt isr(), not going to pretend as smarty pants and knowing the whole history behind that, I don’t care much there, it is just the fact I accepted.
The one useful note for everybody who is going to use the interruption and variables inside – you must declare that variable with the word volatile in the beginning. As I understood that is related to the fact that the main program cycle uses register banks for the memory, while interruption isr() flow operates directly with the RAM, and if you won’t use the volatile declaration it all will be messy and produce weird results since there are two copies of the same variable circulating thru the code.
So, let me make RB5 change the state with the frequency 500Hz and I will even show that in hardware with old cull soviet union scope:
#include <htc.h> #define _XTAL_FREQ 4000000 #define tmr0presc 0x02 #define period 125 __CONFIG(WDTDIS & UNPROTECT & MCLREN & LVPDIS & HS); void main() { __delay_us(500); TRISB = 0b00001111; PORTB = 0; OPTION &= 0b11000000; OPTION |= tmr0presc; T0IE = 1; GIE = 1; TMR0 = 255 - period + 1; for (;;) { } } interrupt isr() { if (T0IF) { TMR0 = 255 - period + 1; RB5 = !RB5; T0IF = 0; } }
And as promised – the scope picture