So verwenden Sie Interrupts in Micro C

Ich baue einen Roboter, der Linien folgen, Hindernissen ausweichen und Pfeilen folgen kann. Ich habe Code für das Folgen von Zeilen und Pfeilen geschrieben, aber ich weiß nicht, wie man Interrupts mit mehr als zwei Prioritätsstufen implementiert. Kann mir jemand sagen, wie man Interrupts für mehr als zwei Prioritätsstufen verwendet?

Quellcode -

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);
     }
  }
}  
Sie erwähnen den bestimmten Controller, den Sie verwenden, nicht, da ich aufgrund Ihrer Beschreibung einen PIC 18F vermute. Der 18F hat nur zwei Interrupt-Ebenen, so dass Sie Ihre mehreren Ebenen in der Software handhaben müssen.
Ich verwende den Mikrocontroller PIC16F887. können Sie Beispielcode für Interrupt im obigen Code senden
Schauen Sie sich Post #5 von joshi_shantanu an . Dies wird Ihnen keine anderen Prioritäten verschaffen, wie er sagt (lesen Sie den Rest des Threads), aber es ist das Nächste, was Sie in einem 16F bekommen werden.
Ich bin mir nicht sicher, was der Beispielcode mit der Frage zu tun hat, da er weder Interrupts verwendet noch Kommentare enthält, die angeben, wo Interrupts wünschenswert sein könnten (geschweige denn die Frage nach mehreren Prioritäten). Wenn ein Micro Interrupts innerhalb eines ISR wieder aktivieren kann (fast alle tun dies auf die eine oder andere Weise), ist es im Allgemeinen möglich, mehrere Prioritäten in Software zu implementieren. Aber es ist ein sehr fortgeschrittenes Thema - Sie müssen wissen, wie Sie mit den daraus resultierenden Reentrancy-Problemen umgehen, und es erfordert ein gründliches Verständnis des Laufzeitsystems Ihres C-Compilers.

Antworten (1)

Dies mag eine etwas offensichtliche Antwort sein, aber da es keine anderen Antworten gibt und das Gerät PIC16 ist, denke ich, dass die einzige Möglichkeit, Ebenen zu erhalten, darin besteht, einen Block von if- oder gleichwertigen Anweisungen zu verwenden.

Zum Beispiel so etwas:

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

void interupt(void)Grundsätzlich innerhalb der Interrupt-Funktion, die in mikroC für normale und High-Level-Interrupts und void interrupt_low (void)für Low-Level-Interrupts auf 18F oder mit dem Schlüsselwort deklariert werden muss iv, platzieren Sie eine Liste ifs, die jedes Interrupt-Flag in der gewünschten Reihenfolge überprüfen. Innerhalb von if platzieren Sie den Handler, der den Interrupt behandelt und das Flag löscht, und gehen dann zum Netzflag über. Leider bedeutet dies, dass es keine einfache Möglichkeit gibt, mehrere Ebenen von Interrupts zu implementieren.

Ein "Hack" könnte darin bestehen, nach Interrupt-Flags zu suchen, die innerhalb eines if-Blocks eines Interrupts mit niedrigerer Priorität vor Teilen, die lange dauern, eine höhere Priorität haben sollen. Dies führt jedoch zu langen und komplizierten Interrupt-Service-Routinen.

Zum Beispiel

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

Eine andere Möglichkeit wäre, die Interrupt-Verarbeitung von der ISR in die Hauptschleife zu verschieben, wenn Sie können. Erstellen Sie einige globale Variablen (außerhalb von Funktionen deklariert) und verwenden Sie sie als Flags, die in der ISR gesetzt und dann in der Hauptschleife verarbeitet werden. Falls Sie einige sehr kritische Interrupts haben, die nicht warten können, bis die Hauptschleife kommt und sie verarbeitet, können Sie den hybriden Ansatz wählen. Platzieren Sie die Behandlungsroutinen für die wichtigsten Interrupts in der ISR und verwenden Sie für die restlichen Interrupts Flags, die in der Hauptschleife verarbeitet werden. Sie könnten sogar ein paar weitere "Ebenen" von Interrupts hinzufügen, indem Sie die vom ISR gesetzten Flags für die wichtigeren Interrupts mehrmals in der Hauptschleife und für die weniger wichtigen Interrupts nur am Anfang oder am Ende der Schleife überprüfen.

Zum Beispiel

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

Hier ist der Link zur Dokumentation von mikroElektronika für Interrupts.