Forum: Mikrocontroller und Digitale Elektronik Fehler beim Auslesen des SRAM (ASM)


von pacer (Gast)


Lesenswert?

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"
4
  ldi ZH,high(seconds)
5
  
6
  rcall TWI_START
7
  ldi   temp, DS1337_Write_ADDRESS
8
  rcall TWI_SlaveAdresse
9
  ldi   temp, Seconds_Register  ; select "second"-Register (00h)
10
  rcall TWI_Daten_schreiben
11
12
 Write_Loop:
13
  lpm   temp, Z+          ; write Daten
14
  rcall TWI_Daten_schreiben
15
  dec   Work            ; Register "Month" read?
16
  brne  Write_Loop        ; no,loop again
17
18
  rcall TWI_STOP
19
ret

Danke

von Michael U. (amiga)


Lesenswert?

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

von pacer (Gast)


Lesenswert?

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.

von pacer (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

lpm liest aus dem Flash, nicht dem SRAM.

von Michael U. (amiga)


Lesenswert?

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

von pacer (Gast)


Lesenswert?

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.

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.