Ich habe nochmal zwei Fragen zu Interrupts beim AVR bei denen ich mich absichern möchte bevor ich es in der Praxis erprobe... 1. Verträgt ein ATMega644 Timer-generierte Interrupts mit 20kHz? Die Interruptroutine soll nur prüfen ob sie aktiv ist, wenn ja einen Wert aus einer Tabelle im Flash laden und diesen an einem Port ausgeben. Viele Takte braucht das nicht und bei 20Mhz hätte ich 1000 Takte bis zum nächsten Interrupt Zeit. Den Controller würde ich dafür mit den maximal möglichen 20Mhz oder wenn nötig mit dem nächstkleineren Baudratenquarz (18,432Mhz) betreiben. 2. Wie kann ich verhindern, daß diese Interrupt-Routine z.B. durch weitere Interrupts unterbrochen wird? Muß ich während der Abarbeitung der Interrupt-Routine Interrupts global deaktivieren und danach wieder aktivieren? Mein Problem ist, daß diese "20kHz-Routine" einigermaßen zeitkritisch ist. Ich muß irgendwie sicherstellen, daß diese Routine beim Auslösen durch den Timer definitiv abgearbeitet wird bevor der Controller (wieder) was anderes macht. Problematisch könnte sein wenn sofort nach dem Timer-Interrupt ein anderer Interrupt die Routine unterbricht bevor die Interrupts global deaktiviert sind. Kann man das irgendwie verhindern oder bleibt da ein Restrisiko? Vergisst der AVR Interrupts, die während der "Sperre" durch die Deaktivierung der Interrupts auftreten oder werden die nach dem Wiederzulassen ausgeführt? Wenns einer weiß dann schon mal Danke im Voraus!
Eine Interrupt Routine wird nicht unterbrochen. 20kHz sollten sehr gut machbar sein, da 1000 Takte dazwischen sind.
Interrupts sind eigentlich ein wesentliches Merkmal von µC. Man kann die Interruptbelastung gerne über 90% der Gesamtlaufzeit hoch fahren, wenn man das möchte, und wenn das Hauptprogramm sonst nicht viel zu tun hat. Es ist aber immer darauf zu achten, daß man im Interrupt nur das allernötigste tut, um ihn schnellstens wieder zu beenden. Wie die Interruptstruktur deines µC ist, das mußt du in der Dokumentation dazu suchen.
Eben. So komplex wie der x86 ist der bei weitem nicht. Weiß denn jemand ob der beim Auslösen eines Interrupts das Interrupt-Flag löscht und beim Interrupt Return wieder setzt?
Die 8 Bit AVRs haben keine Prioritäten im eigentlichen Sinn. Das Problem ist also weniger das der Timer Interrupt von einem anderen unterbrochen wird, sondern das ein anderer Interrupt noch läuft, wenn der Timer Interrupt auftritt. Eine kleine Verzögerung von bis zu etwa 5-10 Zyklen läßt sind dabei nicht vermeiden, auch wenn man in den anderen Interruptroutinen früh Interrupts wieder frei gibt. 20 kHz oder 1000 Zyklen sind keine Problem, das ist noch nicht einmal besonders häufg. Eine kurze Interruptroutine beim AVR liegt so in der Größenordnung 20 Zyklen in ASM. Bei einer Hochsprache kommen meist noch ein paar extra Zyklen dazu, je nach Compiler. Bei den meisten Intrrupts wird das auftreten eines Interrupts in einem Flag gespeichert. Der Interrupts wird entsprechend ggf. Nachgeholt und geht nicht verloren. Nur wenn in der Zeit in der Interrupts gesperrt sind der eine Interrupt 2 mal auftritt, wird der Interrupt nur 1 mal nachgeholt. Beim nachholen der Interrupts gilt die Reihenfolge der Interruptsvektoren, nicht die in der die Events aufgetreten sind.
Beim Interruptaufruf wird das Globale Interuptflag im Status Register gelöscht (entpricht CLI). Beim Rücksprung aus dem Interrupt wird das Globale Interuptflag wieder hergestellt (entspricht SEI). Man kann per SEI in der ISR auch erlauben dass die ISR unterbrochen wird. Bei den meisten Interruptquellen wird zusätzlich bei Interruptaufruf das Flag im SFR, das den Interrupt signalisiert automatisch gelöscht.
> Ein AVR kennt keine Interrupt-Prioritäten. Wohl, bitte Doku lesen. Eine laufende Interrupt-Routine wird beim AVR nicht durch weitere Interrupts unterbrochen (es sei denn, man reaktiviert die Interrupts innerhalb der Interrupt-Routine). Der AVR merkt sich, dass während der Interrupt-Routine weitere Interrupts aufgetreten sind und holt diese dann nach, wenn die Interrupt-Routine abgeschlosen ist. Wobei sich der AVR nur merkt, dass ein bestimmter Interrupt aufgetreten ist, und nicht wie oft. Wenn mehrere unterschiedliche Interrupts auf der Warteliste stehen, werden sie entsprechend in der Reihenfolge ihrer Prioritäten abgearbeitet. irgendwo habe ich nocht ein Gerät liegen, bei dem ein AT2313 mit 8 Mhz intern Timer-generierte Interrupt mit über 30 kHz bedient. Nebenher kommunziert der AVR noch per UART mit der Aussenwelt, wodurch zusätzlich noch weitere Interrupts mit bis zu etwa 23 kHz dazukommen. - Klaus
Klaus schrieb: > irgendwo habe ich nocht ein Gerät liegen, bei dem ein AT2313 mit 8 Mhz > intern Timer-generierte Interrupt mit über 30 kHz bedient. Nebenher > kommunziert der AVR noch per UART mit der Aussenwelt, wodurch zusätzlich > noch weitere Interrupts mit bis zu etwa 23 kHz dazukommen. Alles kein Problem, wenn es richtig gestaltet ist. Ein Standard-8051 konnte sowas vor 30 Jahren auch schon. Beim ARM7, LPC2000, erreichten wir schon Interruptfrequenzen von einigen 100.000 pro Sekunde. Wenn man in den Interrupts einen Pin bewegt, kann man die Aktivitäten auch sehr gut am Oszi darstellen, um die tatsächliche Interruptbelastung ein wenig zu beurteilen. Der 8051 war so gestaltet, daß zwischen Interrupts immer mindestens ein Befehl des Hauptprogrammes abgearbeitet wird. Wohl, damit das nicht ganz zu kurz kommt. Beim älteren 8085 war das noch nicht so, wenn ich mich recht erinnere. Da hatten sie also schon was dazu gelernt. Um zu sehen, was im Interrupt und mit dem Programm passiert, arbeitete ich früher schon mal mit Pseudo-Single-Step per Software mit einem per Software entprellten Taster am externen Interrupt-Pin, ohne Debugger, das geht alles auch. Um den Interrupt quasi festzuhalten. Zustände von Flags konnte man da mit LEDs an einem Port ausgeben.
> Beim Interruptaufruf wird das Globale Interuptflag im Status Register > gelöscht (entpricht CLI). Beim Rücksprung aus dem Interrupt wird das > Globale Interuptflag wieder hergestellt (entspricht SEI). Man kann per > SEI in der ISR auch erlauben dass die ISR unterbrochen wird. Danke! Das sollte meine Sorgen wegen unterbrochenen Interrupt-Routinen vermeiden, schön daß die Controller das machen. Die 20kHz hab ich nicht als Problem gesehen, ich wollte nur sichergehen daß ich nicht von irgendwelchem Mist überzeugt bin und am Ende damit Schiffbruch erleide. Für komplexe Aufgaben nehm ich keine Interrupts, da würde ich in der ISR nur ein Flag setzen und die eigentliche Aufgabe in der Hauptschleife ausführen.
Eine ISR die nur ein Flag setzt kann man sich auch fast sparen, denn zum auslösen der ISR setzt die Hardware in den meisten Fällen auch schon ein Bit. Man kann das Bit auch direkt nutzen, ohne eine ISR. Die AVRs führen normal zwischen 2 Interrupts auch wenigstens einen Befehl des Hauptprogramms aus. Man kann das unterdrücken, wenn man die ISR nicht mit RETI, sondern mit SEI + RET beendet: mit SEI ist dann sozusagen die ISR zu Ende, und RET ist der eine Befehl der dann ausgeführt wird.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.