Interrupt
Folgendes Problem war zu lösen:
Nur eine Taste soll das Blinken (SOS-Morse-Signal) der LED13 einschalten und auch
wieder ausschalten können.
Also:
- Taste kurz drücken: es wird SOS "gefunkt"
- Taste nochmals kurz drücken: SOS wird zuende "gefunkt".
Danach bleibt die LED aus.
- ... von vorn
Interrupt:
Interrupt bedeutet Unterbrechung.
Unterbrochen wird der normale Programmablauf.
Wozu ist das nützlich?
Die folgenden zwei Beispiele sollen Dir das erläutern:
Beispiel 1
Ein Tastendruck von einer Taste, die an einem
Interrupteingang des Mikrocontrollers angeschlossen ist, soll ein
laufendes Programm
sofort unterbrechen.
Dann realisiert man das am besten mit einem externen Interrupt.
Beachte den Unterschied:
- eine Taste an einem normalen digitalen Eingang des
Mikrocontrollers wird immer erst dann abgefragt, wenn der
Programmablauf gerade an der Tastenabfrage "vorbeikommt"
- eine Taste an einem Interrupteingang des
Mikrocontrollers unterbricht sofort
den
Programmablauf.
Beispiel 2
Im Hauptprogramm macht der
Mikrocontroller etwas zeitunabhängiges - z. B. steuert er einen kleinen
Roboter, der fröhlich im Zimmmer herumfährt und Hindernissen ausweicht.
Exakt jede Minute soll er aber "Piep" sagen, und dabei ist es völlig
egal, womit er gerade beschäftigt ist. Seine "normale" Tätigkeit wird
unterbrochen und er sagt pünktlich "Piep".
Schau Dir folgenden Pseudocode an:
setup-funktion {
irgendwas einstellen;
}
loop-funktion {
fahre ewig herum und weiche Hindernissen aus;
}
interrupt-funktion(exakt jede Minute) {
sage "Piep";
}
Stell Dir einfach zwei kleine Männchen im Gehirn dieses Roboters vor:
- Der Fahrer fährt mit dem Roboter, wie mit einem Auto
herum und passt darauf auf, nirgends anzustoßen.
Er sitzt am Lenkrad, betätigt Gas, Kupplung und Bremse und hält
Ausschau nach Hindernissen.
- Exakt jede Minute hält
ihm sein Beifahrer die Augen zu, schiebt ihm vom Lenkrad weg und hupt!
Egal, was der Fahrer gerade tut, der Beifahrer unterbricht
ihn einfach dabei.
Für solcherart Interrupts (exakt jede Minute) kann man einen im Mikrocontroller vorhandenen
Timer benutzen. Das wäre ein Timerinterrupt.
Schaltung für unser Problem:
Der 10k-Widerstand sorgt dafür, dass 5V am Interrupt-Eingang anliegen wenn die Taste ungedrückt ist.
Er ist ein sog. Pull-Up-Widerstand.
Code für unser Problem:
int kurz = 250;
int lang = 800;
volatile int status = LOW; // blinken oder nicht
void setup()
{
pinMode(13, OUTPUT); // Board-LED
attachInterrupt(1, tastenBetaetigung, FALLING); // Interrupt 1 liegt an Pin 3
}
void loop () {
if (status==HIGH){
s();
o();
s();
delay(lang); delay(lang);
}
}
// Die folgende Interrupt Service Routine wird
// bei jeder Buttonbetätigung aufgerufen
void tastenBetaetigung() {
status = !status; // Status umkehren
}
void s(){
did(); did(); did(); delay(kurz);
}
void o(){
da(); da(); da(); delay(kurz);
}
void did(){
digitalWrite(13, HIGH); delay(kurz);
digitalWrite(13, LOW); delay(kurz);
}
void da(){
digitalWrite(13, HIGH); delay(lang);
digitalWrite(13, LOW); delay(kurz);
}
Untersuchen wir einmal ein paar Zeilen:
attachInterrupt(1, tastenBetaetigung, FALLING);
1: Der Interrupt 1 wird benutzt werden (er liegt am Pin 3).
tastenBetaetigung: Das ist der Name der Funktion, die bei dem Interrupt ausgeführt wird.
FALLING: Auf Deutsch: "FALLEND" - wenn am Interrupt-Eingang der Zustand von HIGH zu LOW wechselt.
status = !status; // Status umkehren
!: Das Ausrufezeichen ist ein logischer Operator. Er macht aus einem HIGH
ein LOW und umgekehrt. Diesen Vorgang nennt man Negieren oder Invertieren.
-
Eine Simulation dieses Experimentes findest Du
hier.
-
Ein ähnliches Experiment -aber ohne Interrupt-
findest Du hier.
|