16 Bit Werte aus dem Speicher lesen

Gast #739943
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
#739958
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...
#739966
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...
Gast #739987
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
Gast #740064
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
#740110
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).
#741453
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.
#741688
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
#741698
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren