Forum: Mikrocontroller und Digitale Elektronik 16 Bit Werte aus dem Speicher lesen


von Christian (Gast)


Lesenswert?

Hallo ich möchte mittels Z-Pointer Werte aus dem Speicher lesen aber ich 
schaffe es nicht ganz an das High-Byte des Wortes zu kommen. Kann mir 
jemand sagen was ich falsch mache?

main:
  ldi ZL, LOW(pwmValue*2)
  ldi ZH, HIGH(pwmValue*2)
  lpm temp, Z
  ldi ZL, LOW(pwmValue)
  ldi ZH, HIGH(pwmValue)
  lpm temp1, Z
  rjmp main
.DSEG
pwmValue:
.dw 0x11FF

Er läd mir in beide Register 0xFF hinein ... anscheinend hab ich das mit 
der Multiplikation mit 2 noch nicht so richtig verstanden ....

Danke schonmal für die Hilfe

gruß Christian

von Johannes M. (johnny-m)


Lesenswert?

Christian wrote:
> ... anscheinend hab ich das mit
> der Multiplikation mit 2 noch nicht so richtig verstanden ....
So sieht es aus. Die Multiplikation brauchts, weil LPM mit Byte-Adressen 
arbeitet, Adressen im Programmspeicher an sich aber Wort-Adressen sind.

Wenn die zwei Bytes des 16-Bit-Wertes im Speicher hintereinander liegen, 
dann liegt das eine Byte an der Byte-Adresse pwmValue*2 und das andere 
an der Adresse pwmValue*2 + 1. Und jetzt überlege mal, wie Du wohl an 
das zweite Byte drankommst...

von Johannes M. (johnny-m)


Lesenswert?

Zwei kleine Tips noch am Rande:
Du hast den Wert im Flash mit .dw erzeugt. Die AVRs sind little-endian, 
d.h. das High-Byte steht im Speicher "hinter" dem Low-Byte (also bei der 
höheren Adresse).

Außerdem gibt es (falls Dir das noch nicht bekannt sein sollte) den 
Befehl adiw, der u.a. mit den Pointer-Registern funktioniert und der 
maßgeschneidert ist für solche Anwendungen...

von Michael U. (Gast)


Lesenswert?

Hallo,

main:
  ldi ZL, LOW(pwmValue*2)
  ldi ZH, HIGH(pwmValue*2)
  lpm temp, Z+   ; lädt (Z) nach temp und erhöht anschließen Z üm 1
  lpm temp1, Z
  rjmp main

.DSEG
pwmValue:
.dw 0x11FF

Gruß aus Berlin
Michael

von Johannes M. (johnny-m)


Lesenswert?

@Michael:
Hmmm, das wäre ja die ganz elegante Methode... Hab glaub ich zu lange 
nicht mehr in Assembler programmiert.

von crazy horse (Gast)


Lesenswert?

lpm temp, Z+ gibts aber nicht auf allen Controllern, wenn nicht, wird 
der Assembler schon meckern :-)

von Michael U. (Gast)


Lesenswert?

Hallo,

dann käme:

main:
  ldi ZL, LOW(pwmValue*2)
  ldi ZH, HIGH(pwmValue*2)
  lpm temp, Z   ; lädt (Z) nach temp und erhöht anschließen Z üm 1
  adiw Z,1
  lpm temp1, Z
  rjmp main

adiw gibt esa uch nicht auf allen, also dann

main:
  ldi ZL, LOW(pwmValue*2)
  ldi ZH, HIGH(pwmValue*2)
  lpm temp, Z
  subi ZL,-1
  sbci ZH,0
  lpm temp1, Z
  rjmp main

oder

main:
  ldi ZL, LOW(pwmValue*2)
  ldi ZH, HIGH(pwmValue*2)
  lpm temp, Z
  inc ZL
  brne m_0

  inc ZH

m_0:
  lpm temp1, Z
  rjmp main

alle können auch lpm nicht in beliebige Register, also noch:

main:
  ldi ZL, LOW(pwmValue*2)
  ldi ZH, HIGH(pwmValue*2)
  lpm
  mov temp,r0
  subi ZL,-1
  sbci ZH,0
  lpm
  mov temp1,r0
  rjmp main

Fehlt noch was? ;-)

Gruß aus Berlin
Michael

von Johannes M. (johnny-m)


Lesenswert?

Michael U. wrote:
> Fehlt noch was? ;-)
Vermutlich nicht...

von Obelix (Gast)


Lesenswert?

Mal eine allgemeine Frage, da ich nicht mit den AVRs arbeite.
Haben die AVRs nicht alle den selben Befehlssatz?

von crazy horse (Gast)


Lesenswert?

ein klares Jein.
Es gibt den ganz alten Befehlssatz, den haben alle nach wie vor. Ist dan 
aber im Laufe je nach Entwicklungsrichtung was dazugekommen.

von Johannes M. (johnny-m)


Lesenswert?

Zunächst mal gibt es Befehle, die bestimmte Hardware-Eigenschaften 
voraussetzen. Das sind v.a. die Multiplikationsbefehle. Die AVRs der 
ATMega-Reihe waren die ersten, die einen Hardware-Multiplier hatten, und 
dementsprechend sind die entsprechenden Befehle auch nur für diese µCs 
relevant.

Außerdem gibt es Befehle, deren Einsatz von der Größe des Speichers 
(Adressraum) abhängt. So haben alle AVRs mit bis zu 8 KiB Flash nur 
relative Sprung- und Call-Befehle, weil sich mit der Adressbreite von 
rjmp und rcall der Speicher komplett ansprechen lässt und 
dementsprechend die absoluten Befehle, die mehr Platz im 
Programmspeicher brauchen, unsinnig wären. Erst ab 16 KiB Flash gibt es 
die absoluten Befehle jmp und call, die einen größeren Adressbereich 
zulassen, aber auch zwei Worte breit sind (rjmp und rcall nur ein Wort).

von Frankl (Gast)


Lesenswert?

Wie addiere ich jetzt zum Pointer eine Variablen. adiw unterstüzt doch 
nur Konstante.

von Johannes M. (johnny-m)


Lesenswert?

Frankl wrote:
> Wie addiere ich jetzt zum Pointer eine Variablen. adiw unterstüzt doch
> nur Konstante.
Da musste auf die Ochsentour ran. In der Befehlssatz-Dokumentation steht 
aber, wie's geht (bei add bzw. adc).

von Wolfram Q. (quehl)


Lesenswert?

ich denke, daß die o.g. Programmteile so nicht funktionieren. LPM liest 
aus dem Flash. Die Adresse liegt jedoch im stat. RAM ( .DSEG ). Oder 
habe ich da was falsch verstanden?

mfg

von Falk B. (falk)


Lesenswert?

@ Wolfram Quehl (quehl)

>ich denke, daß die o.g. Programmteile so nicht funktionieren. LPM liest
>aus dem Flash. Die Adresse liegt jedoch im stat. RAM ( .DSEG ). Oder
>habe ich da was falsch verstanden?

Das siehst du sehr richtig.

AVR-Tutorial: SRAM
AVR-Tutorial: Speicher

MFg
Falk

von spess53 (Gast)


Lesenswert?

Hi

Dann funktioniert das:

.DSEG
pwmValue:
.dw 0x11FF

auch nicht.

MfG Spess

von Johannes M. (johnny-m)


Lesenswert?

Wolfram Quehl wrote:
> ich denke, daß die o.g. Programmteile so nicht funktionieren. LPM liest
> aus dem Flash. Die Adresse liegt jedoch im stat. RAM ( .DSEG ). Oder
> habe ich da was falsch verstanden?
Autsch. Da hab ich gar nicht so genau hingeschaut. Klar, das kann nicht 
funktionieren. Muss natürlich entweder ein .cseg hin oder das lpm macht 
keinen Sinn.

spess53 wrote:
> Dann funktioniert das:
>
> .DSEG
> pwmValue:
> .dw 0x11FF
>
> auch nicht.
Richtich. .dw geht nur in .eseg und .cseg.

von Michael U. (amiga)


Lesenswert?

Hallo,

autsch... gilt auch für mich:
Wer lesen kann, ist klar im Vorteil...

wenn es im Ram stehen soll, muß es das Programm erstmal irgendwo 
hingeschrieben haben.

Dort wäre es nur eine Reservierung des Platzes

.org 0x060  ; erste SRAM-Adresse

pwmVALUE: .db 2  ; Reserviere 2 Byte

Der lesende Zugriff wäre dann z.B.

  lds temp,pwmVALUE
  lds temp1,pwmVALUE+1

Gruß aus Berlin
Michael

von Johannes M. (johnny-m)


Lesenswert?

Michael U. wrote:
> .org 0x060  ; erste SRAM-Adresse
>
> pwmVALUE: .db 2  ; Reserviere 2 Byte
>
> Der lesende Zugriff wäre dann z.B.
>
>   lds temp,pwmVALUE
>   lds temp1,pwmVALUE+1
Auch nicht. Wie oben schon gesagt: .db und .dw gehen nur in Flash und 
EEPROM, also in .cseg oder .eseg. Im SRAM (.dseg) geht das Reservieren 
von Speicher nur mit .byte. Und dann muss noch der Wert 
hineingeschrieben werden, was nur das Programm kann.

EDIT:
Es ist ein oft gesehener Irrtum, dass man ins SRAM, wie in die 
nichtflüchtigen Speicher auch, irgendwelche vordefinierten Werte 
schreiben kann, die bei Programmstart automatisch ins SRAM übernommen 
werden. Dem ist aber nicht so! Das SRAM ist nunmal flüchtig und nach 
einem Reset zunächst mal mit irgendwas gefüllt. Definierte Werte 
hineinschreiben kann nur das Anwenderprogramm.

Die Direktiven .db und .dw sind zur Definition konstanter Werte 
vorgesehen, die beim Programmieren direkt in den betreffenden Speicher 
geschrieben werden können, und das geht nunmal nur mit nichtflüchtigem 
Speicher.

von Christian (Gast)


Lesenswert?

Hallo kommt ein bischen verspätet, aber danke für alle Antworten ....
Ihr habt  mir  sehr geholfen

gruß Christian

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.