Hallo!
Du hat ja bereits BITWAIT kennen gelernt. Damit kann man auf einen Tastendruck warten und daraufhin mit dem Programm fortfahren. Der Nachteil liegt auf der Hand Das Programm bleibt stehen, bis die Taste gedrückt wurde. Genau deshalb ist es sehr selten, dass man BITWAIT in Programmen antrifft.
Wenn das an einen Pin anliegende Signal nicht nachprellt, also z.B. von einem entprellten Taster stammt, dann kann man das Signal vom µC beobachten lassen. Tritt das Signal auf, dann unterbricht der µC die aktuelle Programmausführung und springt zu einem vorher bestimmten Label. Der Code unterhalb des Labels wird abgearbeitet und bei RETURN springt der Programmzeiger wieder zurück zur vorher verlassenen Stelle.
Der Vorteil liegt auf der Hand. Das Programm läuft und läuft und läuft. Nur dann, wenn sich auch wirklich etwas am beobachteten Pin tut, dann wird der dazupassene Code ausgeführt. Das nennt man Interrupt oder Interrupt Request und das Label, welches bei so einem Interrupt Request angesprungen wird, nennt man Interrupt Handler oder Interrupt Request Handler. Im Mikrocontroller-Bereich hat sich auch die Bezeichnung "Interrupt Service Routine" (ISR) eingebürgert.
So ein Interrupt unterbricht das laufende Programm. Setzt man Interrupts ein, muss man das Programm so schreiben, dass es an jeder Stelle egal ist, wenn die Ausführung mal kurz unterbrochen wird. -- Man kann sich aber auch absichern und Codeteile die nicht durch einen Interrupt unterbrochen werden dürfen vor so einer Unterbrechung schützen. Man kann mögliche Unterbrechungen einfach dadurch umgehen, indem man vor so einem Codeteil die Unterbrechung durch Interrupts ausschaltet und danach wieder einschaltet. Der µC merkt sich die in der Zwischenzeit anfallenden Interrupts und arbeitet sie danach ab.
Das Einfachste aber ist, wenn man in einem Interrupt-Handler nichts macht was lange dauert. Idealerweise setzt man in einem Interrupt-Handler eine Variable und kümmert sich um die restliche Abarbeitung des Jobs in der Hauptschleife.
Es gibt beim ATmega8 zwei Pins, die so einen Interrupt auslösen können. INT0 und INT1. Wenn man sich den Anschlussplan im ATmega8-Datenblatt auf Seite 2 ansieht, dann findet man heraus, dass INT0 der Pin PD2 und INT1 der Pin PD3 ist. Dieses Wissen können wir jetzt dafür nutzen, um eine LED bei einem Tastendruck ein und bei erneutem Tastendruck auszuschalten. Und um zu beweisen, dass die Hauptschleife währenddessen weiter läuft, lassen wir eine zweite LED in der MainLoop blinken.
Zum Testen genügt diese Schaltung
Ein neuer Befehl wird eingeführt: TOGGLE
TOGGLE entspricht (in etwa) dieser Befehlsfolge:
IF bit_variable = 0 THEN
bit_variable = 1
ELSE
bit_variable = 0
END
Die neuen Befehle sind im Code beschrieben.
$regfile = M8def.dat
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100
'LED1 an PD7
Led1 Alias Portd.7
Config Led1 = Output
'LED2 an PD6
Led2 Alias Portd.6
Config Led2 = Output
'TASTER1 an PD2
Taster1 Alias Pind.2
Config Taster1 = Input
Taster1 = 1 'PullUp-Widerstand einschalten
'Wenn der Interrupt INT0 auftritt, dann springe zum Label On_int0
On Int0 On_int0
'Der Interrupt INT0 wird ausgelöst wenn der Pin PD2 gegen GND gezogen wird.
'Also beim Übergang von HIGH nach LOW. Der Interrupt wird nicht ausgelöst, wenn
'der Pin bereits gegen GND zieht.
Config Int0 = Falling 'fallende Flanke
'INT0 einschalten
Enable Int0
'Interrupts global einschalten. Das ist der Hauptschalter für alle Interrupts
Enable Interrupts
Do
Toggle Led1
Waitms 200
Loop
End
On_int0:
Toggle Led2
Return
mfg Gerold :-)
Den zugehörigen Original-Beitrag findest du im Loetstelle-Forum.
Ich programmiere Progressive Web Applications, Mobile Apps, Desktop-Programme und noch vieles mehr. Falls es dich interessiert, findest du mehr Informationen darüber auf meiner Business-Website.