Forum: Compiler & IDEs Interruptprogrammierung


von Braun Fabian (Gast)


Lesenswert?

Hallo miteinander!

Habe Probleme mit Interruptprogrammierung in AVR-GCC!
Es gibt ja zwei verschiedene Arten wie man Interruptroutinen aufrufen 
kann.
Die eine ist INTERRUPT(SIG_OVERFLOW0) und die andere 
SIGNAL(SIG_OVERFLOW0). Was ist der Unterschied zwischen diesen Beiden? 
Im Englischen Tutorial hab ich sowas rauslesen können, dass SIGNAL auch 
benutzt werden kann wenn die Interrupts nicht eingeschaltet sind. Und 
was nützten überhaupt sei() und cli()?
Ich hatte ein Programm wo ich während der Ausführung immer beim Externen 
Interrupt 0 (INT0) von Triggern auf steigende und Triggern auf fallende 
Flanke wechselte. Dies Funktionierte erst als ich vor dem Wechsel cli() 
und nach dem Wechsel sei() angefügt habe. Wieso das?

Wär echt froh wenn mir das jemand mal auf Deutsch erklären könnte! Danke 
schon im Voraus.

Gruss Fabian

von Peter Fleury (Gast)


Lesenswert?

Bei INTERRUPT() kann die Interrupt-Routine durch einen anderen Interrupt 
unterbruchen werden.
Bei SIGNAL() wird die Interrupt-Routine nicht durch einen anderen 
Interrupt unterbrochen.

Da steht übrigens im avr-libc User Manuel, zwar auf English.

Eine lokale Kopie dieses Manuals befindet sich auf deinem PC im 
Verzeichnis:
C:\WinAVR\doc\avr-libc\avr-libc-user-manual\index.html

von Joerg Wunsch (Gast)


Lesenswert?

Du hast das aus dem Englischen nicht ganz richtig rausgelesen:
SIGNAL() läßt die Interrupts ausgeschaltet (was sie erstmal
innerhalb einer Interruptroutine standardmäßig sind -- mit dem
abschließenden RETI werden sie wieder zugeschaltet), während
INTERRUPT() sofort im Funktionskopf ein sei() ausführt und
damit geschachtelte Interrupts zuläßt.

Wenn Du nicht weißt, was Du willst, dann willst Du immer SIGNAL(). :-)
Insebesondere Interruptroutinen für UARTs sind hier extrem mit
Vorsicht zu genießen, da bei denen die Interruptbedingung erst
gelöscht wird, wenn das zugehörige UDR gelesen bzw. geschrieben
wird.  Werden die Interrupts vorher wieder freigeschaltet, dann
wird sofort ein neuer Interrupt ausgelöst!

Während aller Aktionen, die die Interruptbedingungslogik
umschalten, sollte man generell die Interrupts erstmal
ausschalte (cli()), andernfalls kann es passieren (je nachdem,
welcher Interrupt und ob seine Bedingung jetzt schon anliegt),
daß sofort beim Umstellen ein Interrupt ausgelöst wird.  Gerade
bei externen Interrupts ist es allemal auch eine gute Idee,
das entsprechende Hardware-Flag nach dem Umstellen und vor
dem sei() noch manuell zu löschen (das ist das zugehörige
INTFx Flag, je nach Prozessor im GIFR oder im EIFR Register
gelegen).  Achtung, Löschen bedeutet dabei, ein 1-Bit zu
schreiben (das ist beinahe generell beim AVR so).

von Braun Fabian (Gast)


Lesenswert?

Hallo!

OK...langsam machts klick :-)
Also d.h. wenn ich jetzt eine Interruptroutine mit SIGNAL(blablabla) 
nehmen und in dieser cli() ausführe etwas ändere und nacher nicht mehr 
sei() ausführen sondern diesen befehl einfach auslasse, dann wird das 
sozusagen am schluss automatisch gemacht? ist das korrekt?

herzlichen dank für eure hilfe!

Fabian Braun

von Joerg Wunsch (Gast)


Lesenswert?

Immer noch nicht. :)  Du brauchst gar kein cli() innerhalb von
SIGNAL() machen, Interrupts sind automatisch abgeschaltet für
diese Zeit.

Du kannst aber innerhalb von SIGNAL() explizit ein sei() machen,
wenn Du bereits vorfristig Interrupts wieder zulassen willst
(und damit eine Schachtelung von Interruptroutinen), anonsten
werden sie ab dem Ende der SIGNAL-Routine wieder freigegeben.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.