Hallo, ich bin dabei kein Programm für einen Atmega32 auf einem RNControl Testboard zu schreiben. Ich habe eine Funktion Sendchar über das USART Interrupt, daraus abgeleitet eine Send_String Funktion, beide funktionieren. Der 16 Bit Timer ist auch initialisiert, und steuert im Millisekunden Takt die Problembehaftete ISR an. In dieser möchte ich im Sektunden Takt einen Messwert übertragen(dem einsprechend inkrementiere ich eine Laufvariable usw.).Der Messwert ist ein Zählerstand eines Impulszählers. Dieser ergibt sich durch ein Signal am PORTB,durch den INT2_vektor ebenfalls über eine ISR wird der Messwert erhöht. Beim wenn ich nun in der ISR, die durch den Timer ausgelöst wird den Messwert Senden will gehen während des Sendens Impulse verloren. Beispielsweise Sendet er mit bei einem 4kHz Signal nur 3996 als Zählerstand. Lasse ich jedoch das senden weg, und lasse mir statt dessen den Zählerstand an den LEDs des PORTC ausgeben, so stimmt er. Komischerweise Stimmt auch er erste übertragene Wert nach einem Reset. Kann mir jemand weiterhelfen?
Ro Bret schrieb: > wenn ich nun in > der ISR, die durch den Timer ausgelöst wird den Messwert Senden will > gehen während des Sendens Impulse verloren. In einer ISR sind Interrupts im Normalfall ausgeschaltet, weshalb während des Sendens keine Impulse gezählt werden können, da dies ja ebenfallt über einen Interrupt (INT2) geschiet. Mögliche Lösungen wären dass man vor dem Senden die Interrupts wieder freigibt (unsauber), die Senderoutine so umbaut, dass diese die zu sendenden Bytes in ein Buffer schreibt und sofort zurückkehrt (über den USART TXC Interrupt werden die Bytes im Buffer dann nacheinander gesendet), oder in der Timer-ISR wird lediglich ein Flag gesetzt, welches in der Hauptschleife gepollt wird und das Senden dann von dort aus (also mit aktivierten Interrupts) geschiet. MfG Mark
Vielen Dank erstmal für die Schnelle Antwort, aber laut Datenblatt haben Externe Interrupts eine höhere Priorität als der Sende Interrupt, wieso ist es in diesem Fall scheinbar nicht so? Ich bin ja wenn ich mir den MW nur auf den LEDs anzeigen lasse auch in der Timer ISR, und der INT2 ISR funktioniert. Gibt es beim ATMega eigentlich die Möglichkeit reine Software "Interrupts" also Threads oder Events zu initialisieren?
Leider kein Quellcode. (Siehe Netiquette http://www.mikrocontroller.net/articles/Netiquette) Aber Deine Formulierung: Ro Bret schrieb: > wenn ich nun in > der ISR, die durch den Timer ausgelöst wird den Messwert Senden will lässt vermuten, das Du in der der ISR des Timers tatsächliche die UART-Sendefunktionen aufrufst. Falls Du nicht nur ein Zeichen von innerhalb der ISR sendest, blockiert das natürlich unnötig die anderen Interrupts. Ein bewährtes alternatives Entwurfsschema ist, in der Timer-ISR nur einfach den Zählerstand in einer Variablen zu speichern und evtl. ein Flag zu setzen. Das ist kurz genug, das höchstens ein weiterer INT2 auftritt (hängt natürlich von der maximalen Frequenz ab, die Du messen willst). Die weitere Möglichkeit wäre, garkeinen Interrupt für das Messen der Frequenz zu benutzen, sondern den externen Takteingang für Timer0 resp. 1 zu verwenden. Dann hält der Sendeinterrupt die Zählung überhaupt nicht auf. Trotzdem sollte auch in diesem Fall (wie auch sonst nicht) das senden nicht in einer ISR erfolgen. Die einzige Ausnahme ist das senden eines einzelnen Zeichens aus den Interrupts, die ein leeres Senderegister anzeigen.
Ro Bret schrieb: > aber laut Datenblatt haben Externe Interrupts eine höhere Priorität als > der Sende Interrupt, wieso ist es in diesem Fall scheinbar nicht so? Wie kommst Du darauf, das es in diesem Fall scheinbar nicht so ist? Unter Interrupt Priorität werden verschiedene Dinge verstanden. Beim AVR bezieht sich die Priorität lediglich auf die Reihenfolge der Ausführung von mehreren gleichzeitig anstehenden Interrupts. Nicht jedoch auf die in manchen uCs implementierte Fähigkeit die Priorität von laufender ISR gegen die neu auftretender ISR abzuwägen. Insbesondere kann beim AVR jede neuer Interrupt einen schon laufenden Interrupt unterbrechen (falls das globale Interrupt-Flag das erlaubt) egal ob der neue Interrupt eine höhere oder niedrigere "Priorität" als der laufende hat. D.h.: Die höhere Priorität kommt nicht zum tragen, solange die Interrupts gesperrt sind oder gerade eine ISR ausgeführt wird. Die Interrupts werden bei auftreten eines Interrupts global gesperrt. Das bedeutet, das die anderen Interrupts, nicht sofort, sondern erst nach verlassen, der gerade laufenden ISR abgearbeitet werden. Dann aber kommt, und das ist der einzige relevante Fall, in dem die Priorität beim AVR überhaupt relevant ist, falls mehrere verschiedene Interrupts aufgetreten sind, diejenige ISR mit der höchsten Priorität zur Ausführung. Lies mal den Artikel: http://www.mikrocontroller.net/articles/Interrupt und das Datenblatt.
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.