Hallo Forum,
ich versuche eine "Statemachine" zu realisieren.
in Register r24 wird der aktuelle Status gehalten und mitteles eines
Tasters
weitergeschaltet. In Status 1 und 2 läuft ein Timer der dann bei einem
bestimmten Stand abschaltet. So der Gedanke!!!!
Es klappt soweit das der Timer nach Betätigung des Tasters anläuft.
Auf wundersame Art und Weise ändert sich der Status von alleine und der
Timer stopt. Was um Gottes Willen ändert den Inhalt von r24?????
Ich habe den Quellcode (Assembler) als zip angehängt.
Es wäre schön, wenn jemand sich das mal anschaut und mir einen Tip gibt
Gruß
hubupet
Kleiner Tip:
Wenn du möglichst viele Leute ermuntern willst, deinen Code zu
studieren, dann mach es ihnen einfach das zu tun.
Ein 2 Seiten Assembler File in einem Zip-File zu verpacken, ist für die
Helfenden mit zusätzlicher Arbeit verbunden. Also lass es. Häng dein
Assembler File als Attachment an und jeder kann es ohne zusätzliche
Schritte, wie entpacken, lesen.
In diesem Sinne: neues Attachment
hubipet schrieb:> Auf wundersame Art und Weise ändert sich der Status von alleine und der> Timer stopt. Was um Gottes Willen ändert den Inhalt von r24?????
Was heißt 'der Status ändert sich von alleine'.
Dir ist schon klar, dass du deinen Taster gar nicht so schnell wieder
loslassen kannst, dass dir dein Status nicht durch die Tastenbetätigung
alleine bis zum State 4 durchrauscht?
Zusätzlich solltest du in deiner iSR auf jeden Fall noch das SREG
sichern. Und deine Zeitweiterschaltung stimmt IMHO auch nicht.
Hauptproblem denke ich, ist aber die Tastenabfrage.
Alles in allem finde ich deinen Code ziemlich unübersichtlich durch die
vielen Hin und Her Sprünge.
hubipet schrieb:> Test4:> cpi State, 4> rcall State4> rjmp loop ; Zurueck nach Loop
Fehlt hier nicht was hinter cpi und vor rcall?
Aber:
.DEF State = r24
...
rcall State4
...
State4:
clr State
State4 wird immer angesprungen wenn die vorherigen Abfragen ins leere
laufen.
Ich denke, dass ich in der Button routine darauf warte, dass der Taster
wieder losgelassen wird und ich auf die steigende Flanke reagiere.
Ich gebe dir natürlich Recht: Das ist alles unübersichtlich und lässt
sich besser machen. Ist halt nur ein erster Ansatz "Quick and dirty"
Peter
hubipet schrieb:> Ich denke, dass ich in der Button routine darauf warte, dass der Taster> wieder losgelassen wird und ich auf die steigende Flanke reagiere.
Ich bins noch mal durchgegangen. Ich denke du hast recht hast aber
trotzdem etwas übersehen: Tasten prellen.
Entprellung
Auch wenn du nur einmal die Taste niederdrückst und wieder loslässt,
heißt das nicht, dass du nur 1-nen 1-0 und einen 0-1 Übergang am Pin
kriegst.
Zudem, wenn ich mich nicht noch einmal vertan habe, musst du die Taste
genau in dem Moment loslassen, in dem sich das Programm in
rcall delay50us
befindet.
Diw Wahrscheinlichkeit dafür ist recht hoch, weil der Rest nicht
allzuviel Zeit beansprucht, aber sie ist nicht 100%, d.h. es kann sein,
dass dein Programm ein paar Tastenloslasser übersieht.
Hallo Karl Heinz
ich benutze eine Hardwareentprellung (RC-Glied -> Schmitt-Trigger). Habe
das mit einem Logikanalyser überprüft (IKALOGIC). Sieht da gut aus.
Das Problem ist: Wenn der Timer nicht läuft bleibt das Teil stundenlang
im gleichen Status. Betätige ich den Taster läuft der Timer los. Auch
noch OK.
Aber nach einer nicht reproduzierbarer Zeit ändert sich r24 und der
Timer bleibt stehen. Habe das Prog. geändert und sichere das SREG auf
den Stack.
Problem bleibt!!!!!!!!!!!!!!!
Gruß
Peter
hubipet schrieb:> im gleichen Status. Betätige ich den Taster läuft der Timer los. Auch> noch OK.> Aber nach einer nicht reproduzierbarer Zeit
OK, davon war bisher noch nicht die Rede.
Das bewegt isch also im Sekundenbereich, ohne dass auf der Taste etwas
passiert, weder Drücken noch Loslassen?
Wenn du innerhalb der ISR r16 selbst nicht benutzt, r16 aber zum Sichern
des SREG benutzen willst, dann kannst du das nicht so machen
1
onCompA:
2
in r16, SREG
3
push r16
der push ist hier sinnlos, da du innerhalb der ISR r16 sowieso nicht
angreifst. Aber: r16 ist nach Aufruf der ISR zerstört worden.
Wenn schon, dann so rum
Das verstehe ich jetzt nicht ganz!?
Ich lade das SREG in r16. Schiebe r16(SREG) auf den Stack um den Inhalt
des SREG zu sichern. Am Ende der ISR hole ich r16 vom Stack zurück und
bringe das SREG auf den Zustand zurück den es zu Begin der ISR hatte.
Danach "reti". Vielleicht umständlich da ich mir push und pop sparen
könnte und SREG nur in r16 sichere weil ich das Register in der ISR
nicht benutze aber sicher ist sicher - oder nicht - ?
Peter
Hallo,
Bei ISR-Routinen gilt für Assembler:
ALLE benutzten Register, die auch im Hauptprogramm verwendet werden,
müssen zu Anfang der ISR gesichert werden (PUSH) und am Ende wieder
hergestellt werden (POP); es sei denn, sie werden als Übergabe-Register
zum Hauptprogramm gebraucht.
Mit deinem R16 wäre das dann:
Start:
push r16 ; Inhalt von R16 auf Stack sichern
in r16, SREG ; SREG über R16 auf Stack sichern
push r16
Ende:
pop r16 ; SREG über R16 vom Stack holen und zurückspeichern
out SREG, r16
pop r16 ; alten Inhalt von R16 vom Stack zurückspeichern
reti
Dann wird kein Register des Hauptprogrammes beeinflusst.
Oder du benutzt in der ISR ein noch nicht verwendetes Register; dann
muss auch nichts gesichert und wiederhergestellt werden (ausser das
Status-Register; das sollte man immer auf dem Stack zwischenspeichern,
wenn man SREG-beeinflussende Befehle verwendet).
OK.
Sichere jetzt r16 auf dem Stack -> lade SREG in r16 -> r16 auf den
Stack -> ISR -> r16 vom Stack -> zurück in SREG -> r16 vom Stack ->reti.
Das geht!!! Läuft seit 15 min.
Hab ich jetzt so nach Forum blind so programmiert.
Da muss ich aber mein Prog noch mal genau duchforsten wo die Macke
versteckt war - sprich r16 vom Interrupt nicht verändert werden darf -.
Danke an alle !!!!!!!!!!
Gruß
Peter
Hi
>Da muss ich aber mein Prog noch mal genau duchforsten wo die Macke>versteckt war - sprich r16 vom Interrupt nicht verändert werden darf -.
Die Macke war deine ISR!
MfG Spess