Hi Ich habe den Quellcode im Anhang geschrieben, der auch soweit funktioniert, jedoch nur wenn das "sei" im Label sek steht. Die Aufgabe des Codes ist nach jedem Timer0 Overflow Interrupt einen Zähler zu erhöhen und wenn dieser den Wert 31 hat einen weiteren Zähler um eins erhöhen (dies geschieht immer so nach ca. 1 sekunde) Wenn ich dass besagte "sei" entferne funktioniert der Code für exakt eine Sekunde, danach nicht mehr. Wenn das "sei" an dieser Stelle ist funktioniert der Code einwandfrei. Was bewirkt das "sei" an dieser Stelle? Ich freue mich auf eure Hilfe
Sichere mal Dein SREG, bevor Du die eigentliche Interrupt-Service-Routine ausführst, nach der ISR mußt Du´s wieder rücksichern. Also: in Temp, SREG push Temp ..... ..... pop Temp out SREG, Temp reti
Weil im sek Teil direkt (ohne reti) in die Endlosschleife gesprungen wird, was zum einen dazu führt das es irgendwann garantiert zu einem Stackoverflow kommt, zum anderen wird (ohne reti) das globale Interruptflag nicht autom. gesetzt.
In dem Fall, wo du "sek" anspringst, beendest du deine ISR nicht mehr mit "reti". Das hat einerseits den Effekt, dass das I-Flag im SREG nicht wieder gesetzt wird und dadurch kein Interrupt mehr abgearbeitet wird. Dein "sei" täuscht nur vor, dass es funktioniert, aber dein Stack läuft über, weil kein RETI erreicht wird, dass die Rücksprungadresse des Int-Aufrufs wieder vom Stack nimmt. Du musst deine ISR so schreiben, dass sie immer mit RETI beendet wird. Der Übersichtlichkeit halber nimmt man dazu immer das selbe RETI. Denn wenn das Programm etwas größer wird (wenn es eine Mainloop bekommt), dann musst du in der ISR noch das SREG sichern und ggf lokale Variablen beschaffen, indem du Registerinhalte vorübergehend auf Stack legst (PUSH / POP). Der Stack muss dabei immer ausgewogen sein, jedes PUSH braucht sein POP, jedes (R)Call sein RET und jeder Int-Aufruf sein RETI. Falls du mal übern Zaun schaun willst, dann schau mal hier: www.hanneslux.de/avr ...
Danke für die schnelle Hilfe! Das Problem mit dem Stapelüberlauf habe ich verstanden, nur sehe ich das irgendwie bei der simulation im Studio nicht? Ich sehe auch keine Möglichkeit, wie ich dass umgehen kann (Ich bin totaler neuling) in Temp, SREG push Temp ..... ..... pop Temp out SREG, Temp reti Wie kann mir das Helfen?
Dieses Fragment sollte in jeder ISR (Interruptserviceroutine) stehen, für die Pünktchen setzt Du den eigenlichen Code ein, den die ISR abarbeiten soll. Verwendest Du dann in der ISR auch noch andere Variablen, die Du auch im Hauptprogramm benutzt, so mußt Du diese anfangs auch push-en und am Ende der ISR wieder pop-en, damit nach dem Interrupt alles so ist, wie es vorher war.
ok und wie mach ich das wenn ich wie in meinem Code ohne reti aus der ISR rausspringe? dann hab ich ja dennoch dass gleiche Problem wenn ich dass richtig verstanden habe.
Das darfst Du nicht! RETI ist IMMER das letzte, was eine ISR ausführen muß! Wenn Du aus der ISR ´raus willst, mußt Du immer noch die ganzen POP-s und das RETI ausführen lassen, sonst raucht Dein Stack ab!
So hab jetzt was in der ISR geändert, und kann es jetzt simulieren. Is da jetzt noch ein Stackproblem? Ich glaube, dass es jetzt ok sein müsste.
Warum schaust du bei der Simulation nich einfach mal deinem Stackpointer zu? Der wird doch nicht zum Spaß im Workspace, I/O angezeigt. ...
ich sehe da nur nen Stackmonitor, bei dem hinter jedem Eintrag immer disabled steht
in Temp, SREG push Temp ..... ..... pop Temp out SREG, Temp reti Das ist natürlich Quark :-), es sei denn, Temp wird ausschliesslich in ISRs verwendet. Vollständig muss es so aussehen: push Temp in Temp, SREG push Temp ..... ..... pop Temp out SREG, Temp pop Temp reti Ich habe immer gerne ein eigenes Register für die SREG-Sicherung benutzt. .def sreg_bak=R2 ISR: in sreg_bak, SREG . . out SREG, sreg_bak reti Das bietet sich an, wenn man noch freie Register hat oder es auf kürzeste Interrupt-Laufzeit ankommt. Bei den RAM-losen Typen geht es nur so.
ok hab ihn gefunden ;-) und ihm zugesehen und es verstanden. Also vielen Dank für eure Hilfe
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.