# How to use interrupts in micro C

I am making a robot which can follow lines, avoid obstacles and follow arrows. I wrote code for line following and arrow following but I don't know how to implement interrupts with more than two priority levels. Can anyone tell me how to use interrupts for more than two priority levels?

Source code -

unsigned short current_duty, old_duty, current_duty1, old_duty1;

void InitMain() {
ANSEL  = 0;                         // Configure AN pins as digital
ANSELH = 0;
C1ON_bit = 0;                       // Disable comparators
C2ON_bit = 0;

PORTA = 255;
TRISA = 255;                        // configure PORTA pins as input
PORTB = 0;                          // set PORTB to 0
TRISB = 0;                          // designate PORTB pins as output
PORTC = 0;                          // set PORTC to 0
TRISC = 0;                          // designate PORTC pins as output
PORTD = 0;                          // set PORTC to 0
TRISD = 0;                          // designate PORTC pins as output
PWM1_Init(5000);                    // Initialize PWM1 module at 5KHz
PWM2_Init(5000);                    // Initialize PWM2 module at 5KHz
}

void main() {
InitMain();
current_duty  = 255;                 // initial value for current_duty
current_duty1 = 255;                 // initial value for current_duty1

PWM1_Start();                        // start PWM1
PWM2_Start();                        // start PWM2
PWM1_Set_Duty(current_duty);         // Set current duty for PWM1
PWM2_Set_Duty(current_duty1);        // Set current duty for PWM2

while (1) {                          // endless loop

PORTD.F4=1;
PORTD.F5=0;
PORTD.F6=1;
PORTD.F7=0;

if (PORTB.F1==1) {                 // turn L  moter L pwm1
PWM1_Set_Duty(50);
PWM2_Set_Duty(175);
delay_ms(500);
PWM1_Set_Duty(150);
PWM2_Set_Duty(150);
}

if (PORTB.F3==1) {                    // turn R  moter L pwm1
PWM1_Set_Duty(175);
PWM2_Set_Duty(50);
delay_ms(500);
PWM1_Set_Duty(150);
PWM2_Set_Duty(150);
}

if (PORTB.F2==1 &&  PORTB.F3==1) {                    // turn R  moter L pwm1
PWM1_Set_Duty(175);
PWM2_Set_Duty(25);
delay_ms(500);
PWM1_Set_Duty(150);
PWM2_Set_Duty(150);
}

if (PORTB.F2==1 &&  PORTB.F1==1) {                    // turn R  moter L pwm1
PWM1_Set_Duty(25);
PWM2_Set_Duty(175);
delay_ms(500);
PWM1_Set_Duty(150);
PWM2_Set_Duty(150);
}
}
}

• You don't mention the particular controller you're using by I'm guessing a PIC 18F from what you've described. The 18F only has two interrupt levels so you will need to handle your multiple levels in software. – embedded.kyle Aug 28 '12 at 11:41
• i am using PIC16F887 microcontroller. can you send example code for interrupt in above code – Thulana Vimukthi Aug 28 '12 at 12:19
• Take a look at Post #5 by joshi_shantanu. This won't get you different priorities like he says it will (read the rest of the thread) but it's the closest thing you're gonna get in a 16F. – embedded.kyle Aug 28 '12 at 12:25
• I'm not sure what the example code has to do with the question, as it neither uses interrupts, nor has comments indicating where interrupts might be desirable (let alone the question of multiple priorities). In general, if a micro has a way of reenabling interrupts inside an ISR (nearly all of them do, one way or another), it is possible to implement multiple priorities in software. But it's a very advanced topic -- you need to know how to deal with the resulting reentrancy issues, and it requires a thorough understanding of your C compiler's run-time system. – Dave Tweed Aug 28 '12 at 21:44

This may be a bit obvious answer, but since there are no other answers and the device is PIC16, I think that the only way to get levels is using a block of if or equivalent statements.

For example something like this:

interrupt()
{
if(A)
{
handle(A);
}
if(B)
{
handle(B);
}
}


Basically inside the interrupt function, which in mikroC has to be void interupt(void) for normal and high level interrupts and void interrupt_low (void) for low level interrupts on 18F or declared using iv keyword, you place a list ifs which check each interrupt flag in order you like. Inside the if you place the handler that handles the interrupt and clears the flag and then go on to the net flag. Unfortunately, that means that there is no easy way to implement multiple levels of interrupts.

One "hack" could be to check for interrupt flags you want to have higher priority inside of a if block of a lower priority interrupt before parts which take long time. This however leads to long and complicated interrupt service routines.

For example

interrupt()
{
if(A)
{
handle(A);
}
if(B)//B takes a long time and several steps
{
init(B);
if(A)
{
handle(A);
}

handle(B);//This takes long time
}
}


Another way would be to move the interrupt processing from the ISR to the main loop, if you can. Make some global variables (declared outside of any functions) and use them a flags which will be set in the ISR and then processed inside the main loop. In case you have some very critical interrupts which cannot wait for the main loop to come and process them, you could make the hybrid approach. Place the handling routines for the most important interrupts in the ISR and for the rest of the interrupts use flags which will be processed in the main loop. You could even add few more "levels" of interrupts by checking flags set by the ISR for the more important interrupts several times in the main loop and for the less important interrupts only at the beginning or the end of the loop.

For example

char a,b,c;

interrupt()
{
if(A)
{
handle(A);
}
if(B)
{
b=1;
clear_B_interrupt_Flag;
}
}

main()
{

while (1)
{

if(b)
{
handle(B);
b=0;
}
}
}


Here's the link for the mikroElektronika's documentation for interrupts.