Forum: Mikrocontroller und Digitale Elektronik EEPROM Problem unter Assembler


von ANdy11 (Gast)


Lesenswert?

im Tutorial steht folgendes coding:
1
.include "m8def.inc"
2
 
3
; hier geht die Programmsektion los
4
.cseg
5
 
6
    ldi     r16, low(RAMEND)            ; Stackpointer initialisieren
7
    out     SPL, r16                    
8
    ldi     r16, high(RAMEND)
9
    out     SPH, r16                    
10
 
11
    ldi     r16, 0xFF
12
    out     DDRB, r16                   ; Port B Ausgang
13
 
14
    ldi     ZL,low(daten)               ; Z-Zeiger laden
15
    ldi     ZH,high(daten)
16
    rcall   EEPROM_read                 ; Daten aus EEPROM lesen
17
    out     PORTB, r16
18
 
19
loop:   
20
    rjmp loop
21
 
22
EEPROM_read:
23
    sbic    EECR,EEWE                   ; prüfe ob der vorherige Schreibzugriff
24
                                        ; beendet ist
25
    rjmp    EEPROM_read                 ; nein, nochmal prüfen
26
 
27
    out     EEARH, ZH                   ; Adresse laden
28
    out     EEARL, ZL    
29
    sbi     EECR, EERE                  ; Lesevorgang aktivieren
30
    in      r16, EEDR                   ; Daten in CPU Register kopieren
31
    ret
32
 
33
; Daten im EEPROM definieren
34
.eseg
35
daten:
36
    .db     0b10101010

was ich hier nicht verstehe sind die Zeilen wo dirn steht:
ldi     ZL,low(daten)               ; Z-Zeiger laden
ldi     ZH,high(daten)

was mache ich hier eigentlich?

was ich brauche ist: ich nehme mal an es sind Daten im EEPROM von der 
letzten Messung drinnen bevor ich die Versorgung ausgeschaltet habe. 
Jetzt will ich die Daten auslesen und in die selben Variablen laden wie 
in der vorigen Messung.
Jetzt habe ich aber ein Problem: Ich habe 256 byte zur Verfügung, geißt 
das ich kann 256 Variablen des Typs Byte speichern?
wenn ja lautet dann das coding zum Auslesen so:
1
  sbic    EECR,EEWE                   ; prüfe ob der vorherige Schreibzugriff
2
                                        ; fertig
3
    rjmp    EEPROM_read                 ; wenn nicht, dann nochmnal
4
 
5
    out     EEARH, ZH                   ; Adresse laden
6
    out     EEARL, ZL    
7
    sbi     EECR, EERE                  ; Lesevorgang = 1
8
  
9
    in Schwellwertleft, EEDR      ;Daten aus EPROM in Variable laden
ich habe hier aber folgendes Problem: aus welchem byte lade ich da jetzt 
in r16?
wie kann ich dieses festlegen welches ich auslesen will?

lg andy

von Otto (Gast)


Lesenswert?

Die Adresse des Bytes steht im Z-Zeiger

von ANdy11 (Gast)


Lesenswert?

>Die Adresse des Bytes steht im Z-Zeiger
aso, dh die daten, die in Klammern stehen sagen die adresse aus?

dh so müsste es eig funktionieren:
1
;Lese Werte von vorheriger Messung aus und speichere diese in 
2
;die Schwellwerte rein
3
  ldi r16, 0b00000000
4
  out ZH, r16            ;vernachlässigbar, da nur 1 byte drinnen
5
6
  ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
7
  out ZL, r16
8
9
  sbic EECR,EEWE                  ;prüfe ob der vorherige Schreibzugriff
10
                                     ;beendet ist
11
    rjmp EEPROM_read                ;nein, nochmal prüfen
12
 
13
    out EEARH, ZH                   ;Adresse laden
14
    out EEARL, ZL    
15
    sbi EECR, EERE                  ;Lesevorgang aktivieren
16
  
17
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden

von MarioT (Gast)


Lesenswert?

so:
ldi     ZL,low(daten)
ldi     ZH,high(daten)
daten:
    .db     0b10101010

oder so:

ldi     ZL,low(Karl_August)
ldi     ZH,high(Karl_August)

Karl_August:
    .db     0b10101010

von ANdy11 (Gast)


Lesenswert?

>ldi     ZL,low(Karl_August)
>ldi     ZH,high(Karl_August)

>Karl_August:
>    .db     0b10101010

was sagt denn das .db aus?

Karl_August legt in dem Fall die Adresse fest?

könnte ich das ganze denn nicht so machen?
1
;******************************************************************************
2
;Lese Werte von vorheriger Messung aus und speichere diese in 
3
;die Schwellwerte rein
4
5
6
  ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
7
  mov ZL, r16            ;Ausgabe
8
  rcall Read_EEPROM
9
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden
10
11
;*****************************Hauptprogramm************************************
12
Hauptprogramm:

UP:
1
Read_EEPROM:
2
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
3
                                     ;beendet ist
4
    rjmp Read_EEPROM                ;nein, nochmal prüfen
5
 
6
    out EEARH, ZH                   ;Adresse laden
7
    out EEARL, ZL    
8
    sbi EECR, EERE                  ;Lesevorgang aktivieren
9
ret

wenn ich komiliere funktioniert das

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> was sagt denn das .db aus?
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Speicher
Direktiven wie .db sind Anweisungen an den Assembler, keine 
Prozessorbefehle. Von denen kann man sie durch den vorangestellten Punkt 
unterscheiden. In diesem Fall sagen wir dem Assembler, dass er die 
angegebenen Bytes nacheinander im Speicher platzieren soll; wenn man die 
Zeile also assembliert, erhält man eine Hex-Datei, die nur diese Daten 
enthält.

Hast Du das erste Programm mal getestet?

ANdy11 schrieb:
> ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
>   mov ZL, r16            ;Ausgabe

Das wird nicht gehen.

von ANdy11 (Gast)


Lesenswert?

>Das wird nicht gehen.
Wieso denn nicht?
das einzige was zählt ist doch, dass die Adresse im ZL steht (wenn man 
jetzt ZH vernachlässigt) oder?

von MarioT (Gast)


Lesenswert?

Versuch macht kluch

von ANdy11 (Gast)


Lesenswert?

>Versuch macht kluch
ich würde nicht fragen wenn ich es im moment versuchen könnte

von MarioT (Gast)


Lesenswert?

Warum willst Du unbedingt dem ZL 0b00000001 geben und nicht Karl_August? 
Dein Programm wiord nicht größer und nicht schneller. Was steht denn in 
ZH drin? Solltest Du vieleicht vorher löschen, oder gib ihm wieder 
Karl_August und dein Programm wird gehen.

von MarioT (Gast)


Lesenswert?


von Otto (Gast)


Lesenswert?

@ANdy11,

die EEPROM-Adresse ist eine 16-Bit-Adresse.

Es gibt mehrere Varianten, diese an die Schreib- bzw. Leseadresse:

    out EEARH, ZH                   ;Adresse laden
    out EEARL, ZL

zu übergeben - auf jeden Fall enthält ZH das High-Byte und ZL das 
Low-Byte der Adresse.

Selbstverständlich funktioniert es auch, diese Adresse direkt 
einzutragen, allerdings sind die Register ZH und ZL nicht über OUT 
ansprechbar - dieser Befehl dient dem Preipheriezugriff.

Otto

von Hannes L. (hannes)


Lesenswert?

ANdy11 schrieb:
>>Das wird nicht gehen.
> Wieso denn nicht?
> das einzige was zählt ist doch, dass die Adresse im ZL steht (wenn man
> jetzt ZH vernachlässigt) oder?

Nein, der Z-Pointer ist bei EEPROM-Zugriff irrelevant. Er wurde in 
diesem Beispiel als normales oberes Register verwendet und etwas 
missverständlich kommentiert.

Welches Byte das EEPROM ausspuckt, wird dadurch bestimmt, welche Adresse 
zuvor in die EEP-Adressregister (EEARH:EEARL) geschrieben wurde. Über 
welches Arbeits-Register das erfolgte, ist dabei unwichtig. Wichtig für 
den Ablauf ist nur:

- Sicherstellen, dass das EEPROM mit dem letzten Schreiben fertig ist
- Adresse in Adressregister schreiben
- Das Steuerbit EERE im Steuerregister EECR setzen (Schalter für
  Start des Lesevorgangs)
- Ergebnis aus EEDR abholen.

Das Ermitteln der Adresse kann durch Berechnungen oder Konstanten 
erfolgen. Gibt man jeder Adresse einen eigenen Namen, so verwendet man 
natürlich diese Namen (Labels, hinter denen sich auch nur eine Zahl 
verbirgt, in diesem Fall die Adresse) auch zum Zuweisen.

Oben gab es einige Beispiele mit .DB
Beachte dabei bitte, dass es verschiedene Segmente für die verschiedenen 
Speicherarten gibt (.cseg, .dseg, .eseg). Am besten schaust Du Dir mal 
die betreffenden Kapitel im Datasheet etwas genauer an. Ich vermute da 
noch einige Missverständnisse bei Dir, was Speicherarten und deren 
Adressierungsarten betrifft.

...

von ANdy11 (Gast)


Lesenswert?

>- Sicherstellen, dass das EEPROM mit dem letzten Schreiben fertig ist
>- Adresse in Adressregister schreiben
>- Das Steuerbit EERE im Steuerregister EECR setzen (Schalter für
> Start des Lesevorgangs)
>- Ergebnis aus EEDR abholen.

1
ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
2
  mov ZL, r16            ;Ausgabe
3
  rcall Read_EEPROM
4
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden
5
6
7
8
Read_EEPROM:
9
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
10
                                     ;beendet ist
11
    rjmp Read_EEPROM                ;nein, nochmal prüfen
12
13
    out EEARL, ZL            ;adresse laden
14
    sbi EECR, EERE                  ;Lesevorgang aktivieren
15
ret

jetzt will ich doch nur eine Bestätigung
lg andy

von Otto (Gast)


Lesenswert?

In EEARH solltest Du auch einen Wert bzw. eine 0 schreiben - sonst 
könnte es passieren, das Du immer auf andere Adressen zugreifst.

Den Umweg über ZL kannst Du ebenfalls einsparen:

ldi R15,0
ldi R16,1
rcall read_eprom

read_eprom:
..
..
..
..
out EEAH, R15
out EEAL, R16

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> jetzt will ich doch nur eine Bestätigung

nein

ANdy11 schrieb:
> ldi r16,         ;niederwertigen Bits laden, lese Adresse 1 aus
>   mov ZL, r16            ;Ausgabe

ZL ist ein Register "R30" das kannst Du direkt laden
Also:
ldi r30, 0b00000001
ist das gleiche wie:
ldi ZL, 0b00000001
genauso kannst du schreiben:
ldi r16, 0b00000001
out EEARL, r16
und woher weißt Du, was in EEARH drin ist?
Der EEprom braucht eine 16Bit Adresse. Er benutzt das EEARH auch wenn Du 
es nicht extra ladest.
Woher weist Du das die Daten bei 0b00000001 stehen. Warum nimmst Du 
nicht das Beispiel mit den Label?
    ldi     ZL,low(daten)
    ldi     ZH,high(daten)
Dein Programm wird nicht schneller und auch nicht größer.
Der Assembler schreibt dann da sowieso wieder nur eine "Zahl" rein, aber 
die Richtige.

von ANdy11 (Gast)


Lesenswert?

Riiiiiiiiiiiiiiiiiiiiiiiiiiiiesiges Dankeschön

von Otto (Gast)


Lesenswert?

@MarioT:

> Warum nimmst Du nicht das Beispiel mit den Label?

es geht ANdy11 offenbar darum, bereits an bestimmte Adressen 
geschriebene (aktuelle) Daten wieder auszulesen - da nutzt kein Label.

Ob er jetzt direkt eine Zahl oder ein Define einträgt, ist für die 
Funktion egal, nicht aber für die Lesbarkeit.

von ANdy11 (Gast)


Lesenswert?

>es geht ANdy11 offenbar darum, bereits an bestimmte Adressen
>geschriebene (aktuelle) Daten wieder auszulesen - da nutzt kein Label.

naja die Daten werden am Anfang meines Programms ausgelesen, wie gesagt, 
nach abschalten der Spannungsversorgung sollen die Schwellwerte (Rotoer 
Linienverfolgung) noch beibehalten werden, also ins E²PROM gespeichert 
werden.

>..ktion egal, nicht aber für die Lesbarkeit.
Was heißt das denn jetzt wieder?

von Otto (Gast)


Lesenswert?

> nicht aber für die Lesbarkeit.
> Was heißt das denn jetzt wieder?

das heisst, dass Du selber nachhalten musst, an welcher Adresse welcher 
Wert drinsteht. Wenn Du sinnvolle Defines verwendest (z. B. 
Schwellwert), wäre der Code lesbarer.

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
>>..ktion egal, nicht aber für die Lesbarkeit.
> Was heißt das denn jetzt wieder?

Der Compieler übersetzt Dein Programm so das es der Prozessor versteht.
Also ob Du jetzt "Daten" als Label oder "Karl_August_Sucht_Seine_Daten" 
da hin schreibst ist dem Prozessor egal weil der Assembler immer wieder 
die gleiche "Zahl" draus macht. Wenn Du aber später mal oder jemand 
anderes das Programm sich ansieht kann er es besser lesen.

von ANdy11 (Gast)


Lesenswert?

asoo, jetzt weiß ich wieso das besser mit Labels zu machen ist, das gilt 
nämlich auch fürs schreiben, ich brauch einfach nur sagen schreibe in 
"Label" und lese von "Label"

aber das ist mir noch ein Rätsel:
 ldi     ZL,low(daten)
 ldi     ZH,high(daten)

Daten:
.db     0b10101010


woher weiß der Prozessor jetzt was er als High Bit und welches als Low 
bit nehmen soll, weil in Daten: steht nur ein Byte
dann würde doch drin stehen:
ZH: 10101010  ZL: 10101010
dh--> erstes Bit von der Adresse ZH ist null und somit wertet er nur das 
ZL aus oder wie ist das?

von Otto (Gast)


Lesenswert?

In ZH und ZL steht das High- ind Low-Byte der Adresse und nicht der 
Daten !

von Otto (Gast)


Lesenswert?

Nehmen wir mal an, Du hättest ganz viele (mehr als 256) Werte zu 
speichern, dann kommst Du mit einer 8-Bit-Adresse nicht mehr hin. Daher 
verwendet das EEPROM 16-Bit-Adressen, welche aus zwei Byte bestehen.

Hans:

.db 0x00

Franz:

.db 0x00

Kurt:

.db 0x00

..
..
..
..

Xaver:

.db 0x00

von ANdy11 (Gast)


Lesenswert?

Otto schrieb:
> In ZH und ZL steht das High- ind Low-Byte der Adresse und nicht der
> Daten !

naja im endeffekt interessiert mich ja am anfang nur die adresse, denn 
das lesen und schreiben gehen ja über andere befehle:

Lesen: in r16, EEDR

also hab ich gedacht in Daten:
wird die adresse festgelegt, und immer wenn ich eine bestimmte datei 
lesen will muss ich ZL und ZH die Daten hineinladen, also bekomme ich 
bei einlesen inr16, EEDR die Daten die ich haben möchte, so habe ich das 
verstanden

von Otto (Gast)


Lesenswert?

> Lesen: in r16, EEDR

ja - aber dieser Befehl liest die Daten aus der 16-Bit Adresse, die Du 
vorher übergeben hast.....

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> aber das ist mir noch ein Rätsel:
>  ldi     ZL,low(daten)
>  ldi     ZH,high(daten)
>
> Daten:
> .db     0b10101010

"Daten" ist die Adresse. Der Assembler sucht sich wenn das Programm 
übersetzt wird die Stelle wo die Daten (also das .db steht) und setzt 
die "Zahl" oben wo Daten steht wieder ein. Damit steht die Adresse im 
Registerpaar ZL und ZH danach übergibst Du es ja dem
    out     EEARH, ZH                   ; Adresse laden
    out     EEARL, ZL
EEARH und EEARL brauchst Du da das EEprom größer als 256 ist.

von ANdy11 (Gast)


Lesenswert?

>ja - aber dieser Befehl liest die Daten aus der 16-Bit Adresse, die Du
>vorher übergeben hast.....

also jetzt versteh ich gar nichts mehr

die Schritte sind ja die:
-Schau nach ob nicht geschrieben wird
-lege fest bei welcher Adresse (diese ist 16 Bit lang) die Daten 
eingelesen werden soll
-lese anschließend bei angegebener Adresse die 8 bit Daten heraus

von ANdy11 (Gast)


Lesenswert?

>   out     EEARH, ZH                   ; Adresse laden
>   out     EEARL, ZL
>EEARH und EEARL brauchst Du da das EEprom größer als 256 ist.

ja das stimmt schon, aber ZH und ZL sind jeweils 1 Byte groß und wir 
übergeben ihm mit daten sozusagen nur ein byte und das ist wo db steht
wie kann man mit einem byte 16 darstellen war zunächst mal meine andere 
frage
und dann habe ich gedacht, dass ich ihm mit

ldi     ZL,low(daten)
ldi     ZH,high(daten)

das selbe byte für ZL und ZH übergebe (ist ja auch logisch, denn beide 
haben (daten) umklammert also würde dann stehen:

EEARH ... High position höheres Byte(interessiert mich eher weniger, da 
sich da nur wegen den begrenzten 256byte nur eine adresse ausgeht): 
EEARH = 10101010

und EEARL = 10101010, das heißt die Adresse würde dann insgesamt so 
ausschauen:
10101010010101010 wobei das erste bit im High Byte 0 ist und somit die 
gesamte adresse 10101010 ist

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> die Schritte sind ja die:
> -Schau nach ob nicht geschrieben wird

Ein EEprom braucht zum schreiben ewig. Die Daten die ins eeprom 
geschrieben werden sollen, werden zum schreiben übergeben. Dann macht 
das der µC im hintergrund. Der Prozessor arbeitet inzwischen weiter. 
Damit der µC nicht durcheinanderkommt wenn Du jetzt vom EEprom wieder 
was willst muß man erst sehen ob er noch am schreiben ist.

ANdy11 schrieb:
> -lege fest bei welcher Adresse (diese ist 16 Bit lang) die Daten
> eingelesen werden soll

 ldi     R15,low(daten)
 ldi     R16,high(daten)

ANdy11 schrieb:
> -lese anschließend bei angegebener Adresse die 8 bit Daten heraus

EEPROM_read:
    sbic    EECR,EEWE
    rjmp    EEPROM_read                 ; nein, nochmal prüfen

    out     EEARH, R16                   ; Adresse laden
    out     EEARL, R15
    sbi     EECR, EERE                  ; Lesevorgang aktivieren
    in      Schwellwertleft, EEDR

von ANdy11 (Gast)


Lesenswert?

>ldi     R15,low(daten)
>ldi     R16,high(daten)

was mich noch irritiert sind die Klammern und low und high

kann man das nicht so schreiben?
1
;Lese SchwellwertLeft aus------------------------------------------------
2
  ldi ZL, MessergebnisERAMleft          ;niederwertigen Bits laden, lese Adresse 1 aus
3
  ldi ZH, NULL          ;Null für höhere Bits
4
  rcall Read_EEPROM
5
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden
6
7
8
Read_EEPROM:
9
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
10
                                     ;beendet ist
11
    rjmp Read_EEPROM                ;nein, nochmal prüfen
12
  
13
  out EEARH, ZH           ;adresse lesen
14
    out EEARL, ZL            ;adresse laden
15
    sbi EECR, EERE                  ;Lesevorgang aktivieren
16
ret
17
18
19
;Daten im EPROM definieren##################
20
.eseg
21
MessergebnisERAMleft:
22
  .db 0b00000001
23
MessergebnisERAMright:
24
  .db 0b00000010
25
MessergebnisERAMmiddle:
26
  .db 0b00000011
27
28
NULL:
29
  .db 0b00000000

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> was mich noch irritiert sind die Klammern und low und high
 also die Adresse ist z.B. Daten = 0b0010000010001001
das low mit Klammer lädt den low(also die kleineren 8Bit in das 
entsprechende Register
Also
ldi R15,low(daten)
ist also in R15 0b10001001 drin
ldi R16,high(daten)
ist also in R16 0b00100000 drin

von ANdy11 (Gast)


Lesenswert?

>das low mit Klammer lädt den low(also die kleineren 8Bit in das
>entsprechende Register
>Also
>ldi R15,low(daten)
>ist also in R15 0b10001001 drin
>ldi R16,high(daten)
>ist also in R16 0b00100000 drin

ABER in Daten ist nur eine 8 Bit lange Zahl zu finden und keine 16bit wo 
man unterscheiden muss, deswegen mein einwand vorher

von MarioT (Gast)


Lesenswert?

Du darfst die richtigen Daten nicht mit der Adresse wo die Daten stehen 
Verwechseln

von Thomas (kosmos)


Lesenswert?

ldi     ZL,low(daten)
ldi     ZH,high(daten)

oder man gibt die Daten direkt dezimal ein ohne ins binäre oder hex 
umrechnen zu müssen. Anstatt 0x10 und 0x0E zu verwenden

z.B.
ldi     ZL,low(3600)
ldi     ZH,high(3600)
oder
ldi temp, low(3600)
ldi temp2, high(3600)

von ANdy11 (Gast)


Lesenswert?

>Du darfst die richtigen Daten nicht mit der Adresse wo die Daten stehen
>Verwechseln

das tuhe ich nicht
aber die Adresse der Daten steht in Daten: .db 0b00000001 --> Adresse1 
wenn man dies im ZL hineinlädt, aber wieso lade ich jetzt das selbe im 
ZH rein?

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> das tuhe ich nicht
> aber die Adresse der Daten steht in Daten: .db 0b00000001 --> Adresse1
> wenn man dies im ZL hineinlädt, aber wieso lade ich jetzt das selbe im
> ZH rein?

machst Du nicht
durch das low und high mit den klammern steht in ZH dann .db 0b00000000

von ANdy11 (Gast)


Lesenswert?

ldi     ZL,low(daten)               ; Z-Zeiger laden
    ldi     ZH,high(daten)
    rcall   EEPROM_read                 ; Daten aus EEPROM lesen
    out     PORTB, r16

loop:
    rjmp loop

EEPROM_read:
    sbic    EECR,EEWE                   ; prüfe ob der vorherige 
Schreibzugriff
                                        ; beendet ist
    rjmp    EEPROM_read                 ; nein, nochmal prüfen

    out     EEARH, ZH                   ; Adresse laden--> diese steht 
jetzt in ZH und ZL, das problem ist aber es steht das selbe in beiden 
drinn
    out     EEARL, ZL
    sbi     EECR, EERE                  ; Lesevorgang aktivieren
    in      r16, EEDR                   ; Daten in CPU Register kopieren
    ret

; Daten im EEPROM definieren
.eseg
daten:
    .db     0b10101010





oder kann es sein, dass er die Adressierung automatisch übernimmt, das 
würde es nämlich erklären, ich glaub eher die Adressierung von Daten 
übernimmt er automatisch, aber was machen dann das .db drinn wenn es 
nicht die adressierung angibt?

von MarioT (Gast)


Lesenswert?

Das .db sagt nur dem Assembler, das das was danach kommt, so in den 
Speicher gehört. Damit er daraus nicht irgenwelchen Code versucht zu 
machen.

von Hannes L. (hannes)


Lesenswert?

Nur dass ich keinen AVR kenne, dessen EEPROM bis zur Adresse 3600 
reicht...

;-)

Die Adressen binär anzugeben ist großer Quatsch, das macht die Sache nur 
unnötig unübersichtlich. Man gibt Werte immer in dem Format an, das für 
den Zweck die höchste Aussagekraft hat. Bei Adressen ist das Dezimal 
oder Hexadezimal, bei Bitmustern (wenn jedes Bit eine andere Bedeutung 
hat, z.B. die Segmente von 7-Segment-Anzeigen) binär und bei Text 
(Buchstaben, Zeichen, Ziffern) in ASCII.

Deine penetrante Verwendung der Z-Register führt zu Missverständnissen. 
Der Z-Pointer ist für Datenzugriff auf Flash (LPM-Befehl) zwingend nötig 
und für indirekten Datenzugriff auf SRAM geeignet. Nimm also andere 
Register für den EEP-Zugriff, damit Du nicht in den Glauben verfällst, 
es ginge (wie bei LPM) nur mit dem Z-Pointer.

Die Funktionen LOW(x) und HIGH(x) sind keine ASM-Befehle, die der AVR 
abarbeitet, sondern Befehle des Preprozessors (also auf PC-Ebene), die 
das Aufbereiten von Zahlenwerten erleichtern sollen. LOW(x) extrahiert 
dabei den Low-Teil (also die unteren 8 Bit) von x, HIGH(x) extrahiert 
das High-Byte der Zahl. Das Ergebnis ist in beiden Fällen ein Byte mit 
dem Wertebereich 0 bis 255. Auch wenn Dich die Klammern stören, sie sind 
nötig, da eine Funktion syntaktisch Klammern verlangt.

Wenn Du (im Anfangsstadium) Probleme mit symbolischen Adressen hast, 
dann nimm doch in Gottes Namen erstmal numerische Adressen, also 
Dezimalzahlen, um die Arbeitsweise überhaupt erstmal zu verstehen. Auf 
symbolische Adressen kannst Du dann immer noch umstellen, wenn Du 
anfängst zu rätseln, welcher Parameter an welcher Adresse (Zahl) 
gespeichert ist. Du kannst symbolische EEP-Adressen einmal durch 
.DB-Zuweisungen im .ESEG definieren, aber auch durch ganz normale 
Konstantendefinition (.equ EEP_tempo=0, .equ eep_mess_links=1, .equ 
eep_mess_rechts=2, .equ eep_mess_mitte=3, usw...) im Deklarationsteil 
(Kopf) des Programms.

Mehr fällt mir jetzt nicht ein, ich habe aber sicher noch einige Punkte 
(an denen ich Missverständnisse Deinerseits vermute) vergessen.

...

von ANdy11 (Gast)


Lesenswert?

ok langsam gebe ich auf zu verstehen was ihr mir erlären wollt

eine frage hätt ich aber doch noch
wenn ich das hier in den Controller lade kann ich dann die richtigen 
Daten laden?
1
;Lese SchwellwertLeft aus------------------------------------------------
2
  ldi ZL, MessergebnisERAMleft          ;niederwertigen Bits laden, lese Adresse 1 aus
3
  ldi ZH, NULL          ;Null für höhere Bits
4
  rcall Read_EEPROM
5
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden
6
  ;------------------------------------------------------------------------
7
  ;Lese SchwellwertMiddle aus----------------------------------------------
8
  ldi ZL, MessergebnisERAMright          ;niederwertigen Bits laden, lese Adresse 2 aus
9
  ldi ZH, NULL          ;Null für höhere Bits
10
  rcall Read_EEPROM
11
  in Schwellwertmiddle, EEDR    ;Daten aus EPROM in Variable laden
12
  ;-------------------------------------------------------------------------
13
  ;Lese SchwellwertRechts aus----------------------------------------------
14
  ldi ZL, MessergebnisERAMmiddle          ;niederwertigen Bits laden, lese Adresse 3 aus
15
  ldi ZH, NULL          ;Null für höhere Bits
16
  rcall Read_EEPROM
17
  in Schwellwertright, EEDR    ;Daten aus EPROM in Variable laden
18
  ;-------------------------------------------------------------------------
19
20
21
22
Read_EEPROM:
23
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
24
                                     ;beendet ist
25
    rjmp Read_EEPROM                ;nein, nochmal prüfen
26
  
27
  out EEARH, ZH           ;adresse lesen
28
    out EEARL, ZL            ;adresse laden
29
    sbi EECR, EERE                  ;Lesevorgang aktivieren
30
ret
31
32
33
34
35
36
.eseg
37
MessergebnisERAMleft:
38
  .db 0b00000001  ;Adresse 1
39
MessergebnisERAMmiddle:
40
  .db 0b00000010  ;Adresse 2
41
MessergebnisERAMright:
42
  .db 0b00000011  ;Adresse 3
43
44
NULL:
45
  .db 0b00000000

von Thomas (kosmos)


Lesenswert?

ja dem Adresszähler fürs EEPROM gibt man ne kleinere Adresse, aber für 
16Bit Berechnungen kann man halt bis 65535 reinladen.

von Otto (Gast)


Lesenswert?

Nein - hier musst Du wieder mit high() und low() arbeiten !

von ANdy11 (Gast)


Lesenswert?

>ja dem Adresszähler fürs EEPROM gibt man ne kleinere Adresse, aber für
>16Bit Berechnungen kann man halt bis 65535 reinladen.

ich kann mir immer noch nicht vorstellen wie das aussieht wenn ich mit 
16 bit rechen, aber das ist ein anderes Thema

>Nein - hier musst Du wieder mit high() und low() arbeiten !
ich bitte dich noch einmal um eine Erklärung wieso das so ist
wenn ich sage

ldi ZL, high(MessergebnisERAMright)
ldi ZH, low(MessergebnisERAMright)

was steht dann in ZL und ZH?

von Otto (Gast)


Lesenswert?

.eseg

die 1. Adresse ist 0000 high = 00, low =00
die 2. Adresse ist 0000 high = 00, low =01
...
die n. Adresse ist 0100 high = 01, low =00 (nur ein Beispiel!)

Dies hier:

MessergebnisERAMleft:
  .db 0b00000001  ;Adresse 1
MessergebnisERAMmiddle:
  .db 0b00000010  ;Adresse 2
MessergebnisERAMright:
  .db 0b00000011  ;Adresse 3

zeigt, dass Du Adresse und Daten verwechselst, da Du als Kommentar 
Aresse 1-3 geschrieben hast.

Der Inhalt ist vollkommen beliebig !

von MarioT (Gast)


Lesenswert?

ANdy11 schrieb:
> MessergebnisERAMright
in dem Wort "MessergebnisERAMright" steht nicht "0b00000011" drin 
sondern nur an welcher Stelle im EEProm das steht.

von ANdy11 (Gast)


Lesenswert?

Otto schrieb:
> MessergebnisERAMleft:
>   .db 0b00000001  ;Adresse 1
> MessergebnisERAMmiddle:
>   .db 0b00000010  ;Adresse 2
> MessergebnisERAMright:
>   .db 0b00000011  ;Adresse 3
>
> zeigt, dass Du Adresse und Daten verwechselst, da Du als Kommentar
> Aresse 1-3 geschrieben hast.
>
> Der Inhalt ist vollkommen beliebig !

MarioT schrieb:
> in dem Wort "MessergebnisERAMright" steht nicht "0b00000011" drin
> sondern nur an welcher Stelle im EEProm das steht.
>
>
>
>
>
>     Beitrag melden | Bearbeiten | Löschen |


ich glaube so langsam habe ich es begriffen, sowie ich das im moment 
versteh is, dass MessergebnisERAMright die Adresse schon ist, wenn das 
so ist, dann könnte ich theoretisch/nein es wäre sogar 100 * besser nach 
dem db ein register aufschreiben, indem die daten hineingespeichert 
werden, dh beim daten schreiben muss ich ins register bsplsweise r16 die 
daten ablegen, dann speichere ich die daten mit der adressierung 
High(Mess...) und Low(Mess...) und beim neustart kriege ich die daten 
indem ich ihm sage du die adresse ist high low von Mess... ´, der schaut 
sich das ergebnis an, ladet es in EEDR und ich bekomme es dann heraus

von ANdy11 (Gast)


Lesenswert?

aber wenn ich schreibe:
1
;Daten im EPROM definieren##################
2
.eseg
3
SchwellwertERAMleft:  ;Adresse 1
4
  .db ERAMregister
5
SchwellwertERAMmiddle:  ;Adresse 2
6
  .db ERAMregister  
7
SchwellwertERAMright:  ;Adresse 3
8
  .db ERAMregister  
9
10
11
WeissERAMlinks:      ;Adresse 4
12
  .db ERAMregister
13
WeissERAMrechts:    ;Adresse 5
14
  .db ERAMregister
15
WeissERAMmitte:      ;Adresse 6
16
  .db ERAMregister
17
;###########################################

dann sagt er unexpected defreister
und wenn ich r16 schreibe dann sagt er unexpected register

jetzt frage ich: wie kann ich sonst festlegen wie daten gespeichert 
werden, indem man dieses Register verändert ausser das ganze händisch zu 
machen sowie vorher, es muss doch irgendeinen grund geben wieso ich das 
.db habe, als erste habe ich gedacht das dient zur adressierung, dann 
war das logischere die Daten, jedoch sind die nicht variable , was mache 
ich jetzt=
?

von MarioT (Gast)


Lesenswert?

.eseg

TEXT_BEGRUESSUNG:
.db "UVR 1611Ausgabe auf LCDSpeichern auf SD01.09.2009"

welche_Daten_ins_LCD:
.db 17 ,5 ,1 ,12

Eingang_Text:
.db "Kollektor Solar-VL  Solar-RL  W",0b11100001,"rmet.SekPuffer.o"

Die Daten Stehen im EEProm
Jetzt üergebe ich die Adresse an r15, r16 z.B.
ldi     r15,low(Eingang_Text)
ldi     r16,high(Eingang_Text)
danach gebe es dem EEProm
    out     EEARH, r16                   ; Adresse laden
    out     EEARL, r15
Dann holt man das erste Byte
ist in dem Fall "K"
dann addiere ich eins dazu und hole das zweite Byte "o"
usw.

von Otto (Gast)


Lesenswert?

Hinter ".db" dürfen nur Konstanten folgen, welche als Initialwerte z. B. 
zusammen mit dem Flashen in das EEPROM geschrieben werden.

Den gewünschten (aktuellen) Inhalt der EEPROM-Zellen musst Du über die 
Schreibroutine in das EEPROM Schreiben.

von Thomas (kosmos)


Lesenswert?

@Andy(11): Angenommen du möchtest in deinem Programm einen veränderbaren 
Wert durch eine Konstante teilen, dann ist es doch bequemer die 
Konstante dezimal statt binär anzugeben. Die Aufteilung also High=1110 
Low=00010000 erledigt also der Assembler.

Genauso ist es wenn du im Programm Daten aus einer bestimmten EEPROM 
Adresse holen möchtest z.B. dort wo eine Kennlinie losgeht

Dann kann man eben im Programm direkt die Stelle dem Adresszähler 
übergeben und der Assembler kümmert sich um den Rest.
also
ldi ZL, high(513)
ldi ZH, low(513)

statt
ldi ZL, high(MessergebnisERAMright)
ldi ZH, low(MessergebnisERAMright)

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.