Forum: Mikrocontroller und Digitale Elektronik Interrupt beeinflusst Flag von cpi


von René (Gast)


Lesenswert?

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

von Ralf G. (ralg)


Lesenswert?

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.

von Patrick J. (ho-bit-hun-ter)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

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.

von René (Gast)


Lesenswert?

>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.

von Wolfgang (Gast)


Lesenswert?

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 ;-)

von spess53 (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.