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);
}
}
}
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.
eingebettet.kyle
Thulana Vimukthi
eingebettet.kyle
David Tweed