www.mikrocontroller.net

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


Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
ASCII2BCD:
  ldi ZL, low(seconds)
  ldi ZH, high(seconds)
  
 ASCI2BCD_loop:  
  receive_loop1:
    sbis UCSRA, RXC             ; warten bis ein Byte angekommen ist
   rjmp  receive_loop1
    in   temp, UDR
  out  UDR,  temp
  subi temp, '0'          ; sub=0x30
  swap temp
    mov  Work1, temp        ; Arbeitskopie des empfangenen Zeichens

  receive_loop2:
    sbis UCSRA, RXC             ; warten bis ein Byte angekommen ist
   rjmp  receive_loop2
    in   temp, UDR
  out  UDR,  temp
  subi temp, '0'
    add  Work1, temp
  
  st   Z+, Work1
  ldi  temp, low(year_high)    ; end of packed BCD reached?
  cp   temp, ZL
  brlt EndBCD            ; yes           
  rjmp ASCI2BCD_loop         ; no,convert next BCD to ASCII
  EndBCD:
ret

Und hier der Code für die Initroutine:
DS1337_Init:
  ldi Work,8            ; write first 6 Registers (Seconds->Month)
  ldi ZL,low(seconds)        ; set pointer to SRAM-Location "seconds"
  ldi ZH,high(seconds)
  
  rcall TWI_START
  ldi   temp, DS1337_Write_ADDRESS
  rcall TWI_SlaveAdresse
  ldi   temp, Seconds_Register  ; select "second"-Register (00h)
  rcall TWI_Daten_schreiben

 Write_Loop:
  lpm   temp, Z+          ; write Daten
  rcall TWI_Daten_schreiben
  dec   Work            ; Register "Month" read?
  brne  Write_Loop        ; no,loop again

  rcall TWI_STOP
ret

Danke

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: pacer (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lpm liest aus dem Flash, nicht dem SRAM.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: pacer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.