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
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...
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...
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
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
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).
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).
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
@ 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: SRAMAVR-Tutorial: Speicher
MFg
Falk
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.
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
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.