AdSense

Mittwoch, 11. September 2013

Pin Change Interrupt mit dem ATMega oder Arduino

(English version) Viele Microcontroller (z.B. ein ATMega 168) haben nicht nur einige externe Interrupts sondern auch sogenannte Pin Change Interrups. Diese Interrupts funktionieren auf allen Kanälen. Die Grundidee ist: Wenn sich an einem Kanal was ändert wird eine Interrupt-Funktion aufgerufen. Allerdings ist das hier nicht so bequem wie mit "normalen" Interrupts, man bekommt nämlich nicht gesagt, welcher Kanal sich verändert hat und man kann auch nicht einstellen, auf welche Flanke der Interrupt warten soll, wann immer sich etwas bei einem Kanal ändert wird die Interrupt-Funktion aufgerufen.

Ich beschreibe nun am ATMega168 wie das genau aussieht. Ich benutze die Kanäle PB0, PD5..7 als Interrupt-Kanäle. Um nun die Interrupts anzuschalten gehe ich folgendermaßen vor:

PCICR |= (1 << PCIE0)|(1 << PCIE2);

Das schaltet die Interrupts für PCINT0 und PCINT2 an, also für PORTB und PORTD. Nun muss man die Kanäle definieren, welche diese Interrupts auslösen sollen:

PCMSK0 |= (1 << PCINT0);
PCMSK2 |= (1 << PCINT23)|(1 << PCINT22)|(1 << PCINT21);


Nun muss man nur noch die Interrupts anschalten (sei();). Benutzt man die Arduino-Entwicklungsumgebung, so geschieht all dies in der setup-Funktion. Als nächstes gibt es die Funktionen, welche aufgerufen werden, wenn die Interrupts ausgelöst werden. Diese müssen folgendermaßen heißen:

ISR(PCINT2_vect)
{
}


und

ISR(PCINT0_vect)
{
}


Um nun herauszufinden, welcher Kanal einen Interrupt hatte, kann man die Kanäle auslesen und nachschauen ob sich etwas verändert hat. Oder wenn man einfach 4 Schalter über Interrupts abfragen will, so kann man auslesen welcher Schalter gedrückt wurde:

int Button0 = digitalRead(8); 
int Button1 = digitalRead(7); 
int Button2 = digitalRead(6);  
int Button3 = digitalRead(5);

2 Kommentare: