Hallo, habe einen Atmega8 und werte über INT0 eine externen Interrupt aus. In der Interrupt-Routine zähle ich einen 16 Bit Zähler hoch (mit volatile deklariert), wenn eine aufsteigende Flanke auftritt. Im Hauptprogramm kopier ich mir dann den Wert des Zählers in eine lokale Variable und möchte damit dann im Hauptprogramm weiterarbeiten. (Das Kopiern der 16Bit Variable in die lokale Variable des main-Programms passiert in einer atomaren Operation). Nun möchte ich immer wenn sich der Wert der lokalen Varible ändert eine Aktion ausführen. Der Code für diese Aktion ist zu groß um dies in der Interrupt-Routine zu machen. Nun müsste ich ja im Hauptprogramm ständig vergleichen, ob sich der Wert der lokalen Variable geändert hat um dann meine Aktion auszulösen. Dadurch habe ich aber dann die Main-Schleife zu 100% mit dieser Aufgabe 'belastet'. Der Vorteil, den ich mir über die Interrupt-Routine ermöglicht habe (nur zu reagieren, wenn eine Flanke an INT0 anliegt und main somit zu entlasten) habe ich mir damit wieder kaputt gemacht. Wie kann ich so etwas nun elegant lösen? Möchte also eine komplexe Funktionalität ausführen, nur wenn an INT0 eine Flanke auftritt. In der INT-Routine kann ich den Code nicht packen, weil der zu komplex und zu groß ist. Im Hauptprogramm dann über while(1) ständig das ändern des Zählers prüfen würde aber die Interrupt-Routine überflüssig machen. Danke für Eure Hilfe!
Das mit dem zu groß und zu komplex für den Code im Interrupt ist immer relativ. Wenn sonst nichts anliegt, kann der ISR code sich auch viel Zeit lassen, und hinsichtlich Größe gibt es gar eine extra Begrenzung. Ein Möglichkeit wäre es eine 2. zusätzliche ISR (als Quasi softwareInterrupt) nutzen, die relativ früh nach einem ggf. kritischen Teil interrupts wieder freigibt. In der ISR von Int0 müsste dann nur noch geprüft werden ob die zusätzliche ISR noch läuft. Wie man den Fall behandelt das die Routine noch nicht fertig ist, wenn das nächste Signal kommt, ist unabhängig davon wie man das ganze löst.
Mr.Burns schrieb: > Dadurch habe ich aber dann die Main-Schleife zu 100% mit dieser Aufgabe > 'belastet'. Nö. Das ist aber eine Milchmädchenrechnung. Wenn deine Hauptschleife sonst nichts anderes tut, als diese Flankenauswertung zu machen, dann ist klar, dass sie zu 100% ausgelastet ist. Sie tut ja sonst nichts anderes. Wenn die Hauptschleife auch noch eine zweite Aufgabe hat, dann teilt sich die Rechenzeit innerhalb der Schleife auf die beiden Aufgaben auf und du überprüfst eben nicht mehr 100% der Zeit ob eine Flanke vorlag, sondern machst hauptsächlich das andere (weil die Flankenauswertung schnell geht und fast keine Zeit beansprucht) > Im Hauptprogramm dann über while(1) > ständig das ändern des Zählers prüfen würde aber die > Interrupt-Routine überflüssig machen. Du hast gut erkannt, warum man für zb Tastenauswertung keinen Interrupt braucht. Die komplexe Funktionalität eventuell in Einzelabschnitte aufteilen, die nacheinander von der Hauptschleife abgearbeitet werden. Damit bist du auf dem Weg eine Zustandsmaschine zu realisieren.
Mr.Burns schrieb: > Der Code für diese Aktion ist zu groß um dies in der > Interrupt-Routine zu machen. Nun ja, machen musst du die Aktion trotzdem. Solange du keine anderen Interrupts oder gepollte Reaktionen auf externe Ereignisse nutzt, ist es dann auch egal, ob das in der ISR oder in main passiert. Ansonsten brauchst du eine mainloop, die garantiert schneller läuft, als die Flanken kommen. Die kann dann auf ein Flag aus der ISR reagieren. Und last but not least, wenn deinen Aktion zeitlich nicht zwischen zwei Flanken passt, dann passt die nicht, eal, ob in der ISR oder in main. Oliver
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.