Path:
Home =>
AVR-Überblick =>
Interrupt-Programmierung => Ablauf
(This page in English:
Interruptprogrammierung in AVR Assembler
Hier wird erläutert, wie interrupt-gesteuerte Programme grundsätzlich ablaufen
müssen. Um das Prinzip zu verdeutlichen, wird zuerst ein einfacher Ablauf
demonstriert. Dann wird gezeigt, was sich bei mehreren Interrupts ändert.
Warnung! Hier gibt es ein Konzept zu erlernen!
Für alle, die bisher nur in Hochsprachen oder, in Assembler, nur schleifengesteuerte
Programme gebaut haben, hier eine wichtige Warnung. Das Folgende wirft einiges
Gewohntes über Programmierung über den Haufen. Mit den gewohnten Schemata
im Kopf ist das Folgende schlicht nicht zu kapieren. Lösen Sie sich von dem
Gewohnten und stellen Sie ausschließlich die Interrupts in den Vordergrund. Um
diese dreht sich bei dieser Programmierung nun alles. Das heißt, er ist
unser Ausgangspunkt für so ziemlich alles:
- mit ihm beginnt jeder Ablauf,
- er steuert alle Folgeprozesse,
- sein Wohlergehen (Funktionieren, Eintreten, rechtzeitige Bearbeitung, etc.) ist
alleroberste Maxime,
- alle anderen Programmteile horchen auf seinen Eintritt und sind reine Sklaven
und Zulieferanten des Masters Interrupt.
Wenn Sie Schwierigkeiten und Unwohlsein beim Kapieren des Konzepts verspüren,
versuchen Sie aus dem ungewohnten Dilemma auch nicht den Ausweg, in alte Strukturen
zu verfallen. Ich garantiere Ihnen, dass eine Mischung aus Interrupts und gewohntem
linearen Programmieren am Ende viel komplizierter ist als das neue Konzept in seiner
Reinform anzuwenden: sie verheddern sich in diversen Schleifen, der nächste
Interrupt kommt bestimmt, aber ob Ihr Hauptprogramm auf ihn hört, bleibt ein
Rätsel.
Wenn Sie das Interrupt-Konzept verinnerlicht haben, geht alles viel leichter und
eleganter. Und garantiert noch schneller und eleganter als in der Hochsprache, die
solche netten Erfindungen vor Ihnen verheimlicht, sie in vorgefertigte und oft
unpassende Korsette einschnürt, so dass Sie die wahre Vielfalt des Möglichen
gar nicht erst zu Gesicht bekommen.
Ablauf eines interruptgesteuerten Programms
Den Standardablauf eines interrupt-gesteuerten Propgrammes in allgemeiner Form
zeigt das folgende Bild.
Reset, Init
Nach dem Einschalten der Betriebsspannung beginnt der Prozessorstart immer bei der
Adresse 0000. An dieser Adresse MUSS ein Sprungbefehl an die Adresse des Hauptprogrammes
stehen (in der Regel RJMP, bei großen ATmega kann auch JMP verwendet werden).
Das Hauptprogramm setzt zu allererst die Stapeladresse in den bzw. die Stapelzeiger,
weil alle interruptgesteuerten Programme den Stapel ZWINGEND benötigen.
Dann initiiert das Hauptprogramm die Hardware, schaltet also Timer, AD-Wandler,
Serielle Schnittstelle und was auch immer gebraucht wird ein und ermöglicht die
entsprechenden Interrupts. Außerdem werden dann noch Register mit ihren
richtigen Startwerten zu laden, damit alles seinen geregelten Gang geht. Dann ist noch
wichtig, den Schlafmodus so zu setzen, dass der Prozessor bei Interrupts auch wieder
aufwacht. Am Ende wird das Interrupt-Flag des Prozessors gesetzt, damit er auch auf
ausgelöste Interrupts reagieren kann. Damit ist alles erledigt und der Prozessor
wird mit der Instruktion SLEEP schlafen gelegt.
Interrupt
Irgendwann schlägt nun Interrupt 3 zu. Der Prozessor
- wacht auf,
- schaltet die Interrupts ab,
- legt den derzeitigen Wert des Programmzählers (die nächste Instruktion
hinter SLEEP) auf dem Stapel ab,
- schreibt die Adresse 0003 in den Programmzähler, und
- setzt die Verarbeitung an dieser Adresse fort,
- dort steht ein Sprungbefehl zur Interrupt-Service-Routine an Adresse ISR3:,
- ISR3: wird bearbeitet und signalisiert durch Setzen von Bit 4 in einem
Flaggenregister, dass eine Weiterverarbeitung des Ereignisses notwendig wird,
- ISR3 wird beendet, indem mit der Instruktion RETI die Ausgangsadresse vom
Stapel geholt und in den Programmzähler geladen wird und schließlich
die Interrupts wieder zugelassen werden,
- der nun aufgeweckte Prozessor setzt die Verarbeitung an der Instruktion hinter
SLEEP fort,
- falls ISR3 das Flaggenbit gesetzt hat, kann jetzt die Nachbearbeitung des
Ereignisses erfolgen und das Flaggenbit wieder auf Null gesetzt werden,
- ohne oder mit Nachbearbeitung wird der Prozessor auf jeden Fall wieder
schlafen gelegt.
Der Ablauf zeigt, wie die Interrupt-Service-Routine mit dem Rest des Programmablaufs
kommuniziert: über das Flaggenbit wird mitgeteilt, dass etwas Weiteres zu tun
ist, was nicht innerhalb der Service-Routine erledigt wurde (z.B. weil es zu lange
dauern würde, zu viele Resourcen benötigt, etc.).
Ablauf bei mehreren interruptgesteuerten Abläufen
Sind mehrere Interrupts aktiv, beginnt der Programmablauf genauso und auch alle
weiteren Abläufe sind ganz ähnlich. Durch die Wahl der Reihenfolge der
Nachbearbeitung lässt sich steuern, welche zuerst fertig ist.
Das Schema lässt sich leicht um weitere Interrupts und deren Nachbearbeitung
erweitern. Das Ganze funktioniert nur, wenn die Interrupt-Service-Routinen kurz sind
und sich nicht gegenseitig blockieren und behindern.
Bei zunehmendem Zeitbedarf und vielen rasch aufeinander folgenden Interrupts sind
sorgfältige Überlegungen zum Timing wichtig. Folgen zwei Setzvorgänge
im Flaggenregister zu rasch aufeinander und dauert die Nachbearbeitung zu lange,
würde ein Ereignis verpasst. Man muss dann andere Wege versuchen, die Lasten
bei der Bearbeitung zu verteilen.
Man erkennt hier nebenbei die Zentrierung des gesamten Programmablaufes auf die
Interrupts. Sie sind die zentrale Steuerung.
To the top of that page
©2009 by http://www.avr-asm-tutorial.net