Hallo, mein Programm (läuft auf einem Atmega8) empfängt alle 5ms neue Steuerdaten über UART. Der UART-Empfang ist interrupt-gesteuert. Außerdem werden alle Timer für die weiteren Funktionen benötigt. Ich würde nun gerne einen Fehlermechanismus einbauen: Wenn der AVR z.B. 10ms keine Daten per UART empfängt, soll eine Fehlerroutine aufgerufen werden. Leider werden alle Timer gebraucht, somit fällt die Lösung, nach jedem erfolgreichem Empfang einen Timer zu starten, schonmal weg. Hat jemand eine Idee, wie ich das sonst realisieren könnte? Danke im voraus Fabian
Hi >Leider werden alle Timer gebraucht, somit fällt die Lösung, nach jedem >erfolgreichem Empfang einen Timer zu starten, schonmal weg. Ein Timer kann durchaus mehrere Funktionen erfüllen. Erzähle mal, was du mit den vorhandenen Timern machst. MfG Spess
Fabian K. schrieb: > Leider werden alle Timer gebraucht, Und? Es ist nicht verboten, einen Timer für mehr als 1 Sache zu benutzen. > somit fällt die Lösung, > nach jedem erfolgreichem Empfang einen Timer zu starten, schonmal > weg. Du musst ihn ja nicht dezidiert starten. Lass ihn doch laufen. Hauptsache der Timer benachrichtigt regelmässig. Ob das Timeout jetzt genau 5ms beträgt, oder sich im Bereich 5 bis 10ms bewegt, ist doch in den meisten Fällen wurscht. Timer lässt man sowieso nach Möglichkeit durchlaufen und stellt sie sich so ein, dass man eine der Applikation angemessene Basiszeit hat. Hast du einen Timer, der zb alle 1ms einen Overflow erreicht, dann gibst du dir in die Overflow ISR rein volatile uint8_t uartTimeout; ISR( .... ) { if( uartTimeout > 0 ) uartTimeout--; ... } mit jedem Zeichen, welches über die UART reinkommt, setzt du uartTimeout auf zb 7. 'Erwischt' du die Variable ja dabei, mal 0 zu werden, dann hattest du einen Timeout. Ist dein Timer auf eine andere Geschwindigkeit eingestellt (aber kleiner als 5ms von Overflow zu Overflow), dann hast du halt andere Zahlen, aber das Prinzip ist nach wie vor das gleiche. Ob derselbe Timer dann auch noch eine PWM erzeugt, oder in der ISR die Tasten entprellt werden, oder ob er dafür zuständig ist eine LED blinken zu lassen ... lass ihn doch das tun. Für dich ist nur wichtig, dass die ISR regelmässig alle x Zeiteinheiten aufgerufen wird. Und vielfache von x kann man ja leicht mit einer Variablen abzählen.
Hallo, zur Ergänzung: nimm einen Timer an mit einer Ablaufzeit von 1 ms, sowas in der Art braucht man fast in jedem Controllersystem. Dann zählst du in der Timer-Routine eine Variable jede ms hoch, ein UART-Empfang setzt diese Variable auf 0 zurück. Die Timerroutine stösst dann eine Fehlerbehandlung an, wenn der Wert grösser wird als 5. Gruss Reinhard
Nee sowas stoesst man im main() an. Die interrupt routine generiert nur eine Boolean.
Danke für die schnelle Antwort. Ich werde also einfach in die ISR von einem der Timer eine (globale) Variable inkrementieren und beim Erreichen eines bestimmten Wertes (abhängig von der Timerzeit) die Fehlerroutine aufrufen. So einfach, eigentlich hätt ich selbst draufkommen müssen, den Timer mehrfach zu nutzen (: Danke nochmal Fabian
Fabian K. schrieb: > Ich werde also einfach in die ISR von einem der Timer eine (globale) > Variable inkrementieren und beim Erreichen eines bestimmten Wertes > (abhängig von der Timerzeit) die Fehlerroutine aufrufen. Dann denke an volatile und atomare Zugriffe ;)
Flääsch Gordon schrieb: > Nee sowas stoesst man im main() an. Die interrupt routine generiert nur > eine Boolean. So war das ja auch gemeint - für einen Anfänger aber vielleicht missverständlich ausgedrückt. Wobei es nicht unmöglich ist, von der ISR in ein Unterprogramm zurückzukehren und erst von dort an den Ausgangspunkt, aber das gehört in die Schublade übelste Trickserei. Übrigens braucht man nicht einmal eine Boolean - man kann einfach in main die Variable abfragen und eine Fehlerbehandlung einleiten, wenn der Schwellwert überschritten ist. Was das atomare angeht: kritisch ist nur der Fall, dass während des Inkrementierens ein UART-Interrupt die Variable auf 0 setzt. Gruss Reinhard
Reinhard Kern schrieb: > Was das atomare angeht: kritisch ist nur der Fall, dass während des > Inkrementierens ein UART-Interrupt die Variable auf 0 setzt. wenn er das inc/dec in der Timer-ISR macht, und das laden in der UART-ISR dann hat er kein Problem, da ja immer nur eine ISR läuft. Sascha
Sascha Weber schrieb: > da ja immer nur eine ISR läuft. Da kannst du im speziellen Fall recht haben, die Prioritätssteuerung des AVR kenne ich nicht, aber allgemeingültig ist die Aussage nicht. Und selbst bei einer "flachen" Prioritätsstruktur kann man das in der Abteilung schweinische Tricks umgehen und auch während der Timer-ISR einen UART-IRQ zulassen. Bei höheren Baudraten ist es sogar dringend zu empfehlen, den UART mit hoher Priorität zu bedienen. In jedem Fall sollte ein atomares Increment zum Befehlssatz oder zum Handwerkszeug des Programierers gehören, notfalls in der Form Disable Interrupt Increment Variable Enable Interrupt Gruss Reinhard
Reinhard Kern schrieb: > Da kannst du im speziellen Fall recht haben, die Prioritätssteuerung des > AVR kenne ich nicht, aber allgemeingültig ist die Aussage nicht. Beim AVR, und um den geht es schliesslich, ist das kein Problem. Wer irgendwelche Hackermethoden bemüht, ist dann allerdings selber schuld, wenn es schiefgeht. Und das: Reinhard Kern schrieb: > Disable Interrupt > Increment Variable > Enable Interrupt geht gar nicht. Jedenfalls nicht in einer ISR. Das ist die totale Verschlimmbesserung. mfg.
Also beim AVR kenn ich das so, dass, während der Ausführung der ISR keine anderen ISR angesprungen werden, es sei denn in der ISR steht ein SEI ... Wenn dann nach Abarbeitung der ISR mehrere andere Interrupts anstehen, dann gehts der Tabelle nach. Das mit dem SEI in der ISR hat mich aber mal 3 Nächte Fehlersuche gekostet, das ist mir nur einmal passiert ... die ISR so kurz wie möglich halten hat sich bei mir besser bewährt.
Thomas Eckmann schrieb: > geht gar nicht. Jedenfalls nicht in einer ISR. Das ist die totale > Verschlimmbesserung. Das ist viel zu sehr verallgemeinert. Im Original IBM BIOS ist der erste Befehl einer Interrupt Routine STI (Interrupts wieder ein) und das ist auch das empfohlene Verfahren für ISRs. Es ist also keineswegs unmöglich, es übersteigt nur deine Kenntnisse. Keineswegs alle Prozessoren sind so primitiv, dass es keine Interupts während einer Interruptbearbeitung gibt, das ginge auch garnicht, in einem komplexen System gibt es mehrere bis viele Prioritäten und ein IRQ höherer Priorität kann sowieso eine ISR niederer Priorität unterbrechen (nicht zu verwechseln mit der Priorität innerhalb einer solchen Prioritätsklasse, das ist wieder eine andere Sache). Wenn du nicht glaubst dass sowas funktioniert schalte einfach deinen PC ein. Gruss Reinhard
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.