Cómo usar interrupciones en micro C

Estoy haciendo un robot que puede seguir líneas, evitar obstáculos y seguir flechas. Escribí código para el seguimiento de líneas y de flechas, pero no sé cómo implementar interrupciones con más de dos niveles de prioridad. ¿Alguien puede decirme cómo usar interrupciones para más de dos niveles de prioridad?

Código fuente -

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);
     }
  }
}  
No menciona el controlador particular que está usando. Supongo que es un PIC 18F por lo que ha descrito. El 18F solo tiene dos niveles de interrupción, por lo que deberá manejar sus múltiples niveles en el software.
Estoy usando el microcontrolador PIC16F887. ¿Puedes enviar un código de ejemplo para la interrupción en el código anterior?
Echa un vistazo a la publicación n.º 5 de joshi_shantanu . Esto no le dará diferentes prioridades como él dice que lo hará (lea el resto del hilo), pero es lo más parecido que obtendrá en un 16F.
No estoy seguro de qué tiene que ver el código de ejemplo con la pregunta, ya que no usa interrupciones ni tiene comentarios que indiquen dónde podrían ser deseables las interrupciones (y mucho menos la cuestión de las múltiples prioridades). En general, si un micro tiene una forma de volver a habilitar las interrupciones dentro de un ISR (casi todos lo hacen, de una forma u otra), es posible implementar múltiples prioridades en el software. Pero es un tema muy avanzado: necesita saber cómo lidiar con los problemas de reentrada resultantes y requiere una comprensión profunda del sistema de tiempo de ejecución de su compilador de C.

Respuestas (1)

Esta puede ser una respuesta un poco obvia, pero dado que no hay otras respuestas y el dispositivo es PIC16, creo que la única forma de obtener niveles es usando un bloque de if o declaraciones equivalentes.

Por ejemplo algo como esto:

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

Básicamente, dentro de la función de interrupción, que en mikroC tiene que ser void interupt(void)para interrupciones normales y de alto nivel y void interrupt_low (void)para interrupciones de bajo nivel en 18F o declaradas usando ivuna palabra clave, coloca una lista que verifica cada indicador de interrupción en el orden que desee. Dentro del si coloca el controlador que maneja la interrupción y borra la bandera y luego pasa a la bandera de red. Desafortunadamente, eso significa que no hay una manera fácil de implementar múltiples niveles de interrupciones.

Un "truco" podría ser verificar los indicadores de interrupción que desea que tengan mayor prioridad dentro de un bloque if de una interrupción de menor prioridad antes de las partes que toman mucho tiempo. Sin embargo, esto conduce a rutinas de servicio de interrupción largas y complicadas.

Por ejemplo

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
    }
}

Otra forma sería mover el procesamiento de interrupciones del ISR al ciclo principal, si es posible. Cree algunas variables globales (declaradas fuera de cualquier función) y utilícelas como banderas que se establecerán en el ISR y luego se procesarán dentro del bucle principal. En caso de que tenga algunas interrupciones muy críticas que no pueden esperar a que llegue el bucle principal y las procese, puede utilizar el enfoque híbrido. Coloque las rutinas de manejo para las interrupciones más importantes en el ISR y para el resto de las interrupciones use banderas que serán procesadas en el bucle principal. Incluso podría agregar algunos "niveles" más de interrupciones verificando los indicadores establecidos por el ISR para las interrupciones más importantes varias veces en el ciclo principal y para las interrupciones menos importantes solo al principio o al final del ciclo.

Por ejemplo

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;
    }
  }
}

Aquí está el enlace para la documentación de mikroElektronika para interrupciones.