Hallo,
ich experimentiere gerade mit einer RTC (DS1337).
Um die Uhr zu stellen, frage ich einmal am Anfang des Programms nach der
Uhrzeit. Diese kann man mit einem Terminalprogramm über die RS232
eingeben.
Das Programm wandelt die ASCII-Zeichen in einen BCD-Code um und
speichert diese im SRAM. In der Initalisierungsroutine wird der Code aus
dem Speicher gelesen und an die TWI-Schnittstelle übergeben.
Bei der Simulation konnte ich festestellen, dass die Zeichen korrekt im
Speicher abgelegt wurden und der Z-Pointer mit dem richtigen Wert
geladen wurde. Merkwürdigerweise wird jedoch bei lpm temp, z+ der
falsche Wert ausgelesen, woher der Wert kommt ist mir unklar.
ich hoffe es kann mir jemand helfen. Wahrscheinlich ist es sinnlos den
kompletten Code zu posten, denn er ist etwas umfangreich und besteht aus
mehreren Dateien.
Hier der Code für die Umwandlung von ASCII in BCD:
1
ASCII2BCD:
2
ldi ZL, low(seconds)
3
ldi ZH, high(seconds)
4
5
ASCI2BCD_loop:
6
receive_loop1:
7
sbis UCSRA, RXC ; warten bis ein Byte angekommen ist
8
rjmp receive_loop1
9
in temp, UDR
10
out UDR, temp
11
subi temp, '0' ; sub=0x30
12
swap temp
13
mov Work1, temp ; Arbeitskopie des empfangenen Zeichens
14
15
receive_loop2:
16
sbis UCSRA, RXC ; warten bis ein Byte angekommen ist
17
rjmp receive_loop2
18
in temp, UDR
19
out UDR, temp
20
subi temp, '0'
21
add Work1, temp
22
23
st Z+, Work1
24
ldi temp, low(year_high) ; end of packed BCD reached?
25
cp temp, ZL
26
brlt EndBCD ; yes
27
rjmp ASCI2BCD_loop ; no,convert next BCD to ASCII
28
EndBCD:
29
ret
Und hier der Code für die Initroutine:
1
DS1337_Init:
2
ldi Work,8 ; write first 6 Registers (Seconds->Month)
3
ldi ZL,low(seconds) ; set pointer to SRAM-Location "seconds"
Hallo,
cp temp, ZL
brlt EndBCD ; yes
das kann unter vielen Umständen schiefgehen.
brlt wertet den Vergleich als signed aus. Wenn also die Tabelle im Ram
über einer 256Byte-Grenze liegt, und ZL damit von 0x7F auf 0x80
wechselt...
Erstmal mit brlo springen, der wertet unsigned aus und außerdem die
Tabelle im Ram so anlegen, daß sichergestellt ist, daß es keinen
Übertrag von ZL nach ZH geben kann oder eben ZL und ZH auf den Endwert
vergleichen.
Wobei ich bei feststehender Anzahl Bytes da meist ein Hilfsregister als
Zähler nehme, um diesen Problemen gleich aus dem Weg zu gehen. ;-)
Gruß aus Berlin
Michael
So wie ich erkennen konnte, liegt der Apeicherbereich bei 0x0060, damit
sollte das erst mal kein Problem darstellen.
Ansonsten ist der Einwand richtig. Den Speicherbereich selbst festlegen
geht sich nur, wenn ich im Programm feste Adressen vergebe. Mir ist aber
nicht klar, wie ich diesen Speicherbereich reservieren kann. Kannst du
mir da ein Beispiel geben?
Den Weg über die Register wäre sicher eine Überlegung wert.
also das Problem konnte ich bis jetzt immer noch nicht lösen.
Ich habe mal ein Bild von meiner Debugsession angehängt.
Ich hoffe jemand kann damit was anfangen und mir erklären warum ein
falscher Wert aus der richtigen Adresse ausgelesen wird.
Hallo,
den vermutlich entscheidenden Hinweis hat ja Stefan Ernst (sternst)
schon gegeben.
>Ansonsten ist der Einwand richtig. Den Speicherbereich selbst festlegen>geht sich nur, wenn ich im Programm feste Adressen vergebe. Mir ist aber>nicht klar, wie ich diesen Speicherbereich reservieren kann. Kannst du>mir da ein Beispiel geben?
Den Teil, wo Du z.B. seconds zugewiesen hast, habe ich noch nicht
gesehen.
Ansonsten allgemein:
.DSEG
.ORG 0x100 ; aktuelle Adresse festlegen
seconds: .byte 2 ; oder wie auch immer
Gruß aus Berlin
Michael
vielen Dank an euch beide.
Auf den Fehler mit lpm wäre ich wohl von alleine nicht gekommen.
Jetzt funktioniert es aber.
Durch die Festlegung des Speicherortes der Tabelle ergeben sich auch
keine Probleme mit dem unsigned Vergleich.