4
\$\begingroup\$

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);
     }
  }
}  
\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – embedded.kyle Aug 28 '12 at 11:41
  • \$\begingroup\$ i am using PIC16F887 microcontroller. can you send example code for interrupt in above code \$\endgroup\$ – Thulana Vimukthi Aug 28 '12 at 12:19
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – embedded.kyle Aug 28 '12 at 12:25
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Dave Tweed Aug 28 '12 at 21:44
3
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.