Hallo! Ich programmiere einen Atmega 168 in Assembler. Meine Elektronik besteht aus einem LCD display, Drehimpulsgeber, Ausgangs- und Eingangsregister usw. Ich lasse in einer Schleife dauernd Daten auf dem LCD anzeigen (schreibe alles ins DDRAM vom LCD). Hat ja alles wunderbar geklappt. Brauchte jetzt aber einen Timer1 Interrupt, da ich für Berechnungen einen genauen Zeitwert(5s) brauche. Seitdem ich mit dem Timer1 interrupt arbeite, zeigt das LCD nach ca. 3s in einer Zeile den Wert den ich anzeigen lasse versetzt um 3 Kästchen nochmal was nicht sein sollte. Also im Grunde zeigt es Blödsinn an. Ich nehme an da der Interrupt irgendwann unterbricht gibt es beim LCD Probleme und er zeigt manche sachen falsch an? PS: LCD ist nicht zeitkritisch. ALso es würde auch ausreichen alle 2 sekunden zu aktualisieren ( Bis auf den Drehimpulsgeber, den muss ich so schnell als möglich aktualisieren) Bin dankbar um Hilfe. Liebe Grüße Luke
Luke schrieb: > Also im Grunde zeigt es Blödsinn an. Ich nehme an da der Interrupt > irgendwann unterbricht gibt es beim LCD Probleme und er zeigt manche > sachen falsch an? Nö. Die Ansteuerung eines LCD ist insofern nicht zeitkritisch, als ein Interrupt an jeder Stelle unterbrechen darf, sofern er * das SREG sichert und wieder herstellt * nichts an den restlichen gebrauchten Registern verändert D.h. wenn die ISR sauber programmiert ist, und der CPU Zustand nach der ISR exakt demjenigen vor Aufruf der ISR entspricht, dann gibt es auch keine Probleme. Denn: die ANsteuerung ist insofern nicht zeitkritisch, als alle Vorgänge zwar eine UNtergrenze für einzuhaltende Zeiten haben, aber keine Obergrenze. Wenn sich der Aufruf der ISR also nur dadurch bemerkbar macht, dass zwischen 2 Befehlen in der LCD Ausgabe etwas mehr Zeit vergeht als gewöhnlich, dann ist das überhaupt kein Problem. Aber: Das darf auch nur die einzige Art und Weise sein, wie sich der ISR Aufruf an dieser Stelle bemerkbar macht! Alle restlichen gebrauchten Register MÜSSEN ihre Werte behalten! > Bin dankbar um Hilfe. Dein Programm? Aber ehe du es postest: Überprüf mal, ob deine ISR insbesondere das SREG sichert und wiederherstellt, bzw. alle Register, die auch in den LCD Routinen benutzt werden. WEnn du dir nicht sicher bist, dann sichere in der ISR ALLE benutzten Register und stell sie am Ende der ISR wieder her. So bist du erst mal auf der sicheren Seite, auch wenn du unter Umständen etwas Zeit verbrutzelst.
Danke für die schnelle Antwort! Also habe jetzt meine ganzen Arbeitsregister in der ISR gesichert. Ich hab in meinem Programm jedoch sehr viele Speicherregister die sich im dseg befinden um alle möglichen Werte abzuspeichern. Müssen diese Register ebenfalls abgespeichert werden? Ich denke nur die Arbeitsregister?! Hab ebenfalls viele Strings, die ich dann in der LCD schleife aufrufe. Habe aber dasselbe Problem schonmal gehabt, dass mir das LCD versetzt Blödsinn anzeigt (da war die ISR noch nicht aktiv) und da ist mir aufgefallen dass ich in jedem Schleifendurchlauf den Cursor vom LCD ausschalte. Habe dies dann nur einmal in der Initialisierung des LCD gmacht und dann war es weg. Kanns da noch immer ein Problem geben? LG
Das sind die Programmausschnitte vom Timer1 interrupt den ich verwende. Ist hier ein Fehler erkennbar? Interrupt funktioniert ja super nur eben macht dann das LCD was es will. .cseg .org 0x0000 rjmp init .org OVF1addr jmp timer1_overflow Timer1_init: ldi temp,0b00000000 sts TCCR1A,temp ldi temp,0b00000010 sts TCCR1B,temp ldi temp,0b00000001 sts TIMSK1,temp ret timer1_overflow: push temp push temp3 push temp2 push temp1 ; temp 1 sichern in temp1,sreg ; SREG sichern call Berechnung out sreg,temp1 ; sreg wieder herstellen pop temp1 pop temp pop temp3 pop temp2 reti
Luke schrieb: > timer1_overflow: > push temp > push temp3 > push temp2 > push temp1 ; temp 1 sichern > > in temp1,sreg ; SREG sichern > > > call Berechnung > > > out sreg,temp1 ; sreg wieder herstellen > pop temp1 > pop temp > pop temp3 > pop temp2 Vergleich mal die Reihenfolgen :-) Die müssen schon sauber ineinander geschachtelt sein, so dass die pop die exakte Umkehrung der push sind! push temp <----------------+ push temp1 <-------------+ | | | ... | | | | pop temp1 <-------------+ | pop temp <----------------+ hast du hier eine Verdrehung, dann vertauscht du effektiv die Inhalte der Register bei einem ISR-Aufruf. Ein Stack ist wie ein Stapel Teller. Den Teller den du als letztes drauflegst, den kriegst du auch als erstes wieder. push X heißt Inhalt vom Teller X auf den Stack oben drauf pop X heißt obersten Inhalt vom Stack auf den Teller X legen Da sucht sich keiner zusammen, wie die korrekte Reihenfolge sein muss. Das musst schon du machen!
1 | in temp1,sreg ; SREG sichern |
2 | |
3 | |
4 | call Berechnung |
5 | |
6 | |
7 | out sreg,temp1 ; sreg wieder herstellen |
aber nur, wenn innerhalb von 'Berechnung' das temp1 nicht verändert wurde. Wird es das, dann schreibst du irgendwas nach SREG zurück, aber sicher nicht den Wert, den du dir vor dem call Berechnung in temp1 'gesichert' hast.
Luke schrieb: > Ich nehme an da der Interrupt > irgendwann unterbricht gibt es beim LCD Probleme und er zeigt manche > sachen falsch an? Nur wenn der Interrupt auch auf das LCD ausgibt. Das geht schief. Das LCD ist nicht reentrant.
Luke schrieb: > ldi temp,0b00000000 > sts TCCR1A,temp > > ldi temp,0b00000010 > sts TCCR1B,temp > > ldi temp,0b00000001 > sts TIMSK1,temp Was mir noch auffällt, m.E. ist "out" der richtige Befehl, um I/O-Register zu beschreiben und nicht "sts".
Icke ®. schrieb: > Luke schrieb: >> ldi temp,0b00000000 >> sts TCCR1A,temp >> >> ldi temp,0b00000010 >> sts TCCR1B,temp >> >> ldi temp,0b00000001 >> sts TIMSK1,temp > > Was mir noch auffällt, m.E. ist "out" der richtige Befehl, um > I/O-Register zu beschreiben und nicht "sts". Stimmt schon so wie er's hat. Beim Mega168 sind diese Register per OUT nicht erreichbar.
Karl Heinz Buchegger schrieb: > Stimmt schon so wie er's hat. > Beim Mega168 sind diese Register per OUT nicht erreichbar. Aha, wieder was gelernt.
Icke ®. schrieb: > Karl Heinz Buchegger schrieb: >> Stimmt schon so wie er's hat. >> Beim Mega168 sind diese Register per OUT nicht erreichbar. > > Aha, wieder was gelernt. :-) Ist einer der Gründe, warum ich reale Programme nicht in Assembler schreibe. Das ist mir zu mühsam, mich immer daran zu erinnern bzw. nachzuschlagen, bei welchem Prozessor ein OUT sein muss und bei welchem ein STS. Das kann der Compiler viel zuverlässiger.
Karl Heinz Buchegger schrieb: > Das kann der Compiler viel zuverlässiger. Der Assembler kann das auch (mit Macros):
1 | ;---------------------- macros for extended IO access ------------------- |
2 | .macro xout |
3 | .if @0 > 0x3F |
4 | sts @0, @1 |
5 | .else |
6 | out @0, @1 |
7 | .endif |
8 | .endmacro |
9 | ;--------------------------- |
10 | .macro xin |
11 | .if @1 > 0x3F |
12 | lds @0, @1 |
13 | .else |
14 | in @0, @1 |
15 | .endif |
16 | .endmacro |
17 | ;--------------------------- |
18 | .macro xlpm |
19 | .if FLASHEND > 0x7FFF |
20 | elpm @0, @1 |
21 | .else |
22 | lpm @0, @1 |
23 | .endif |
24 | .endmacro |
25 | ;------------------------------------------------------------------------ |
Karl Heinz Buchegger schrieb: > in temp1,sreg ; SREG sichern > > > call Berechnung > > > out sreg,temp1 ; sreg wieder herstellen > > aber nur, wenn innerhalb von 'Berechnung' das temp1 nicht verändert > wurde. Wird es das, dann schreibst du irgendwas nach SREG zurück, aber > sicher nicht den Wert, den du dir vor dem call Berechnung in temp1 > 'gesichert' hast. Ja das stimmt hab das schon vor push und nach pop geschrieben. Hab den Fehler schon eingrenzen können. Das Problem dürfte irgendwo in meiner Berechnung liegen. Schalte ich diese weg, dann gibt es kein Problem. Muss mir jez anschaun was ich da für einen Käse programmiert hab gg Danke für die vielen Antworten! LG
Luke schrieb: > Das Problem dürfte irgendwo in meiner > Berechnung liegen. Ja, das ist schon fast unheimlich. Zu 99% wird bei Codeausschnitten immer nur der Teil gepostet, an dem es nicht (allein) liegt. Auch scheint eine geradezu krankhafte Furcht zu bestehen, den Forum Host zu überlasten. Dabei wäre es doch das aller einfachste, den vollständigen Code als Anhang (Zip bei mehreren Dateien) zu senden.
Karl Heinz Buchegger schrieb: > Ist einer der Gründe, warum ich reale Programme nicht in Assembler > schreibe. Ja, ich stoße mittlerweile auch an die Grenzen der Fußlatscherei und werde mich wohl oder übel mit C anfreunden müssen. Die Syntax ist zwar gräßlich, aber vieles wird leichter zu erledigen sein.
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.