Hallo alle zusammen,
folgendes Problem hat mich eben einige Zeit an Nachdenken gekostet! Und
ich frage mich, ob man das auch intelligenter lösen kann.
Es geht um den Befehl "brsh check_weiter". Es funktioniert soweit, dass
alle 1 s zu "check_weiter" gesprungen wird. Allerdings wird jedes 2. Mal
bereits nach 0,2 Sekunden zu "check_weiter" gesprungen. Nach viel Zeit
mit dem Debugger habe ich herausgefunden, dass es vorkommt, dass der
Timer0 Interrupt genauf auf den Befehl "brsh check_weiter" fällt.
Während des Interrupts scheint u.a. das Z-Flag gecleared zu werden und
deshalb springt der uC dann direkt zu "check_weiter", obwohl die
entsprechende Zeit noch nicht erreicht ist. Ich habe das jetzt so
gelöst, dass ich bei "check_weiter" erneut "cpi timer0cs, 10" frage
gefolgt von "brlo loop_Eingabe"
Kennt jemand eine elegantere Möglichkeit dieses Problem zu lösen? Wie
kann ich verhindern, dass ein Timer Interrupt direkt auf einen Befehl
wie brsh fällt und diesen durch die Flags beeinflusst?
Für die, die etwas mehr Hintergrundinfo möchten:
Es handelt sich um einen Zähler für einen Prüfstand. Bei jedem Zyklus
wird ein Kontakt geschlossen ("ZZaehler"). Dieses schließen findet aber
äußerst geprellt statt. Deshalb warte ich nach einem Kontakt 0,1 s und
inkrementiere dann den Zähler. Wird der Kontakt innerhalb dieser 0,1 s
erneut geschlossen, wird der Zähler resettet.
Anbei ein leicht geänderter Ausschnitt aus dem Code:
> loop_Eingabe:
> sbis PINB, ZZaehler
> rjmp check
> cpi timer0cs, 10
> brsh check_weiter
> sbis PINB, Auswahl
> rjmp Nullstellen
> sbis PINB, nachlinks
> rjmp links
> sbis PINB, nachrechts
> rjmp rechts
> rjmp loop_Eingabe
>check:
> sbr Flagreg, 2
> clr timer0
> clr timer0cs
> rjmp loop_Eingabe
>check_weiter:
> cpi timer0cs, 10
> brlo loop_Eingabe
> sbrs Flagreg, 1
> rjmp check_Ende
> inc Zyklus
>Check_Ende:
> clr timer0
> clr timer0cs
> rjmp loop_Eingabe
>;###################################################################### #
>Timer0_overflow: >;Timer0 zählt in Centi- und Sekundenschritten
> push temp1
> inc timer0
> cpi timer0, 50
> brne Timer0_overflow_Ende
> clr timer0
> inc timer0cs
>Timer0_overflow_Ende:
> pop temp1
> reti
René schrieb: > Während des Interrupts scheint u.a. das Z-Flag gecleared zu werden Deshalb sichert man das Statusregister beim Einsprung in die ISR.
Hi Am Ende der ISR sollte man Das aber wieder zurück holen. Im Grunde: push r16 in r16,sreg push r16 ... Deine ISR ... pop r16 out sreg,r16 pop r16 reti Oder, man benutzt ein Register, Welches NUR für die ISR benutzt wird, dann kann man auf einige push/pop verzichten. Meine temporären Variabeln heißen zero (ein unteres Register) temp (ein oberes Register) itemp (ebenfalls oberes Register) temp wird überall für Alles benutzt - außer in der ISR Dort was reinschreiben, was man in der nächsten Routine braucht, ist meist tödlich (da jede Funktion/Routiene dieses Register nach Belieben nutzt). Gleiches bei itemp, halt hier zur Verwendung in den ISR (da die ISR, im Normalfall nicht parallel verabeitet werden, geht Das). zero wird viel beim Zählen benötigt, wenn über eine Registerbreite gezählt werden soll. Dadurch hießen bei mir oben in dem ISR-Pseudocode das Register nicht r16, sondern itemp und wurde bereits im Header/oberen Bereich des ASM-Listing definiert. MfG
René schrieb: > Während des Interrupts scheint u.a. das Z-Flag gecleared zu werden ... Das kann dir mit jedem anderen Flag auch passieren, weil ein freigegebener Interrupt, i.A. immer in den restlichen Ablauf eingeschoben wird. Wenn du das unbedingt in Assembler programmieren willst, wirst du um Grundlagen wie Sicherung von Registern in der ISR und Rückladen beim Rücksprung nicht drumrum kommen. Nur der PC wird automatisch auf den Stack geschoben.
>AVR-Tutorial: Interrupts
Ihr habt ja so Recht! Durch eure Anmerkungen habe ich mir auch nochmal
das Tutorial für Interrupts durchgelesen, da wird das sogar ausdrücklich
erwähnt.
Gut, danke Leute! Jetzt kann ich weiter machen.
Patrick J. schrieb: > Am Ende der ISR sollte man Das aber wieder zurück holen. > > Im Grunde: > push r16 > in r16,sreg > push r16 > ... Ob es ein r16 überhaupt gibt, hängt vom Prozessor ab ;-)
Hi >Ob es ein r16 überhaupt gibt, hängt vom Prozessor ab ;-) Bei welchen anderen Controller außer AVRs gibt es ein SREG? MfG Spess
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.