ON INTERRUPT/de

From MCS Wiki AVR
Jump to: navigation, search

Contents

Funktion

Führt die Subroutine aus wenn der angegebene Interrupt auftritt.

 

 

Syntax

ON interrupt label [NOSAVE|SAVE|SAVEALL]

 

 

Anmerkungen

interrupt

INT0, INT1, INT2, INT3, INT4,INT5, TIMER0 ,TIMER1, TIMER2, ADC , EEPROM , CAPTURE1, COMPARE1A, COMPARE1B,COMPARE1. Man kann auch die AVR Namenskonventionen benutzen:

 

OC2 , OVF2, ICP1, OC1A, OC1B, OVF1, OVF0, SPI, URXC,

UDRE, UTXC, ADCC, ERDY and ACI.

label

Label, zu dem gesprungen werden soll wenn der Interrupt auftritt.

NOSAVE

Wenn man NOSAVE angibt dann werden keine Register bei Aufruf/Verlassen der Interruptroutine gesichert/wiederhergestellt. Wenn Sie diese Option benutzen dann müssen Sie selbst die benutzten Register sichern und wiederherstellen.

 

Wenn Sie NOSAVE nicht schreiben dann werden alle benutzten Register gesichert. Das sind:

SREG , R31 bis R16 und R11 bis R0 mit Ausnahme von R6,R8 und R9.

 

R12 – R15 werden nicht gesichert. Wenn in der Interruptroutine Fließkommaarithmetik benutzt wird (was nicht empfohlen wird) dann müssen Sie R12 bis R15 selbst sichern und wiederherstellen.

My_Isr:

Push R12 ' Register sichern

Push R13

Push R14

Push R15

 

Single = single + 1 ' Fließkommaarithmetik wird benutzt

 

Pop R15  ' Register wiederherstellen

Pop R14

Pop R13

Pop R12

RETURN

 

 

Notice.jpg
Wenn der Mikrocontroller Extendet IO-Space hat (wie zum Beispiel ATmega48, 88, 168, siehe Datenblatt am Ende: Registersummary) dann benutzt der Compiler R23 für einige Operationen. R23 muss dann auch gesichert/wiederhergestellt werden.

SAVE

Dies ist der Standardwert wenn kein Parameter angegeben wird. Die gebräuchlichsten benutzten Register, SREG und RAMPZ werden gesichert und wiederhergestellt.

Gesichert: SREG , R31 bis R16 und R11 bis R0 mit Ausnahme von R6,R8 und R9.

Wenn RAMPZ vorhanden ist dann wird es auch gesichert und wiederhergestellt.

SAVEALL

Dies sichert alle Register, die auch SAVE sichert und zusätzlich noch R12-R15. Man sollte diese Option benutzen wenn man Gleitkommaarithmetik in der Interruptroutine benutzt.

 

Aus der Interrupt-Routine muss man mit dem RETURN-Befehl zurückkehren

 

Der erste RETURN-Befehl der außerhalb einer Abfrage angetroffen wird generiert eine RETI Instruktion. Man kann nur einen solchen RETURN-Befehl in der ISR haben weil der Compiler die Register wiederherstellt und eine RETI-Instruktion erzeugt wenn es auf das RETURN in der ISR stößt. Alle anderen RETURN-Befehle werden in eine RET-Instruktion umgewandelt

 

Die möglichen Interrupt-Namen können in der Register-Datei des benutzten Mikrocontrollers nachgelesen werden. Die Datei 2313def.dat zeigt zum Beispiel, dass der Name für den Compare-Interrupt den Namen COMPARE1 hat. Siehe am unteren Enede der Datei.

 

 

Wofür gibt es Interrupt Service Routinen?

 

Ein Interrupt unterbricht das Programm und springt zu der angegebenen Routine. MAn kann eine DO..LOOP Schleife schreiben und zum Beispiel den Stus eines Eingabepins abfragen um eine Routine anzuspringen wenn der Zustand des Pins sich ändert.

 

Bei Verwendung eines Interrupts kann man andere Ausgaben ausführen und wenn der Zustand des Pins sich ändert dann wird ein bestimmter Programmteil angesprungen. Wenn man zum Beispiel INPUT "Name ", v benutzt um einen Usernamen über die serielle Schnittstelle einzulesen dann wird gewartet bis ein RETURN empfangen wird. Wenn man eine Interruptroutine hat und der Interrupt tritt ein dann wird der Interrupt-Code ausgeführt und wenn er beendet ist dann wird zu dem Input-Befehl zurückgekehrt und gewartet bis ein RETURN empfangen wird.

 

Vielleicht ist ein Uhrenprogramm ein besseres Beispiel. Man könnte einen Sekundenzähler im Programm hochzählen aber es ist besser, einen Timer zu benutzen und einen Sekundenzähler in der Interruptroutine des Timers hochzuzählen.

 

Es gibt verschiedene Interrupt-Quellen und es hängt vom verwendeten Mikrocontroller ab welche jeweils vorhanden sind.


 

Um Interrupts benutzen zu können muss der globale Interrupt-Schalter mit ENABLE INTERRUPTS eingeschaltet werden. Nur dann können Interrupts benutzt werden. Außerdem müssen die jeweiligen individuellen Interrupt-Schalter eingeschaltet werden.


 

ENABLE TIMER0 zum Beispiel erlaubt es, dass TIMER0 Interrupts auftreten können.

 

Mit dem DISABLE-Befehl können die Schalter ausgeschaltet werden.

 

Wenn der Prozessor einen Interrupt verarbeiten muss dann springt er an eine Adresse am Anfang des Flash-Speichers. Die Adressen stehen in der DAT-Datei.

 

Der Compiler erzeugt normalerweise eine RETI-Instruktion zu diesen Adressen so dass im Falle eines Interrupt-Ereignisses sofort zurückgekehrt wird.

 

Wenn man ON..LABEL benutzt dann erzeugt der Compiler Code, der zu dem angegebenen Label springt. DAS SREG und andere Register werden gesichert und wenn RETURN erreicht wird werde die Register wieder hergestellt und ein RETI erzeugt so dass das Programm dort fortgesetzt wird wo es war als der Interrupt aufgetreten war.

 

Wenn eine Interruptroutine ausgeführt wird dan können keine anderen Interrupts auftreten weil der Prozessor (nicht der Compiler) alles Interrupts DISABLEd indem das MASTER Interrupt Bit gelöscht wird. Nach Abarbeitung der Serviceroutine werden die Interrupts wieder eingeschaltet.

 

Es ist nicht möglich, Interrupts eine Priorität zu vergeben. Der Interrupt mit der niedrigsten Adresse hat die höchste Priorität.


 

 

Zum Schluss ein paar Tipps :

 

  • Wenn Sie einen Timer-Interrupt haben der alle 10 uS auftritt dann stellen Sie sicher, dass der Interrupt-Code in 10 uS ausgeführt werden kann.


 

  • Es ist am besten, in der Interruptroutine nur ein Flag zu setzen und dessen Status im Hauptprogramm abzufragen. Dies ermöglicht die Benutzung der NOSAVE Option die Stack- und Programmplatz spart. Man muss dann nur R24 und SREG sichern und wiederherstellen.

 

  • Weil man ein Hardware-Register nicht PUSHen kann muss man es erst laden:

 

PUSH R24 ; Weil wir R24 benutzen werden sichern wir es lieber

 

IN r24, SREG ; Inhalt von SREG in R24

PUSH R24 ; Man kann ein Register sichern

 

hier steht Ihr Assembler-Code

POP R24 ;Inhalt von SREG zurück

 

OUT SREG, R24 ; In SREG sichern

POP R24 ; r24 zurück

 

Siehe auch

On VALUE

 

 

Teilbeispiel


Enable Interrupts
Enable Int0 'Int0 Interrupt einschalten
On Int0 Label2 Nosave 'Sprung zu label2 wenn INT0 auftritt
Do'Endlosschleife
nop
Loop
End
 
Label2:
Dim A As Byte
If A > 1 Then
Return 'generiert ein RET weil es in der Abfrage ist
End If
Return 'generiert ein RETI weil es das erste RETURN ist
Return 'generiert ein RET weil es das zweite RETURN ist

Languages   English Deutsch  
Personal tools
Namespaces
Variants
Actions
Navigation
In other languages
Language