mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik EEPROM Problem unter Assembler


Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Tutorial steht folgendes coding:
.include "m8def.inc"
 
; hier geht die Programmsektion los
.cseg
 
    ldi     r16, low(RAMEND)            ; Stackpointer initialisieren
    out     SPL, r16                    
    ldi     r16, high(RAMEND)
    out     SPH, r16                    
 
    ldi     r16, 0xFF
    out     DDRB, r16                   ; Port B Ausgang
 
    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
    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

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:
  sbic    EECR,EEWE                   ; prüfe ob der vorherige Schreibzugriff
                                        ; fertig
    rjmp    EEPROM_read                 ; wenn nicht, dann nochmnal
 
    out     EEARH, ZH                   ; Adresse laden
    out     EEARL, ZL    
    sbi     EECR, EERE                  ; Lesevorgang = 1
  
    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

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Adresse des Bytes steht im Z-Zeiger

Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
;Lese Werte von vorheriger Messung aus und speichere diese in 
;die Schwellwerte rein
  ldi r16, 0b00000000
  out ZH, r16            ;vernachlässigbar, da nur 1 byte drinnen

  ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
  out ZL, r16

  sbic EECR,EEWE                  ;prüfe ob der vorherige Schreibzugriff
                                     ;beendet ist
    rjmp EEPROM_read                ;nein, nochmal prüfen
 
    out EEARH, ZH                   ;Adresse laden
    out EEARL, ZL    
    sbi EECR, EERE                  ;Lesevorgang aktivieren
  
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
;******************************************************************************
;Lese Werte von vorheriger Messung aus und speichere diese in 
;die Schwellwerte rein


  ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
  mov ZL, r16            ;Ausgabe
  rcall Read_EEPROM
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden

;*****************************Hauptprogramm************************************
Hauptprogramm:

UP:
Read_EEPROM:
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
                                     ;beendet ist
    rjmp Read_EEPROM                ;nein, nochmal prüfen
 
    out EEARH, ZH                   ;Adresse laden
    out EEARL, ZL    
    sbi EECR, EERE                  ;Lesevorgang aktivieren
ret

wenn ich komiliere funktioniert das

Autor: MarioT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ANdy11 schrieb:
> was sagt denn das .db aus?
http://www.mikrocontroller.net/articles/AVR-Tutori...
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.

Autor: ANdy11 (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuch macht kluch

Autor: ANdy11 (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Otto (Gast)
Datum:

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

Autor: Hannes Lux (hannes)
Datum:

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

...

Autor: ANdy11 (Gast)
Datum:

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

ldi r16, 0b00000001        ;niederwertigen Bits laden, lese Adresse 1 aus
  mov ZL, r16            ;Ausgabe
  rcall Read_EEPROM
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden



Read_EEPROM:
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
                                     ;beendet ist
    rjmp Read_EEPROM                ;nein, nochmal prüfen

    out EEARL, ZL            ;adresse laden
    sbi EECR, EERE                  ;Lesevorgang aktivieren
ret


jetzt will ich doch nur eine Bestätigung
lg andy

Autor: Otto (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Riiiiiiiiiiiiiiiiiiiiiiiiiiiiesiges Dankeschön

Autor: Otto (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: Otto (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: Otto (Gast)
Datum:

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

Autor: Otto (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Lesen: in r16, EEDR

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

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
;Lese SchwellwertLeft aus------------------------------------------------
  ldi ZL, MessergebnisERAMleft          ;niederwertigen Bits laden, lese Adresse 1 aus
  ldi ZH, NULL          ;Null für höhere Bits
  rcall Read_EEPROM
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden


Read_EEPROM:
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
                                     ;beendet ist
    rjmp Read_EEPROM                ;nein, nochmal prüfen
  
  out EEARH, ZH           ;adresse lesen
    out EEARL, ZL            ;adresse laden
    sbi EECR, EERE                  ;Lesevorgang aktivieren
ret


;Daten im EPROM definieren##################
.eseg
MessergebnisERAMleft:
  .db 0b00000001
MessergebnisERAMright:
  .db 0b00000010
MessergebnisERAMmiddle:
  .db 0b00000011

NULL:
  .db 0b00000000

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: Thomas O. (kosmos)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: Hannes Lux (hannes)
Datum:

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

...

Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?
;Lese SchwellwertLeft aus------------------------------------------------
  ldi ZL, MessergebnisERAMleft          ;niederwertigen Bits laden, lese Adresse 1 aus
  ldi ZH, NULL          ;Null für höhere Bits
  rcall Read_EEPROM
  in Schwellwertleft, EEDR    ;Daten aus EPROM in Variable laden
  ;------------------------------------------------------------------------
  ;Lese SchwellwertMiddle aus----------------------------------------------
  ldi ZL, MessergebnisERAMright          ;niederwertigen Bits laden, lese Adresse 2 aus
  ldi ZH, NULL          ;Null für höhere Bits
  rcall Read_EEPROM
  in Schwellwertmiddle, EEDR    ;Daten aus EPROM in Variable laden
  ;-------------------------------------------------------------------------
  ;Lese SchwellwertRechts aus----------------------------------------------
  ldi ZL, MessergebnisERAMmiddle          ;niederwertigen Bits laden, lese Adresse 3 aus
  ldi ZH, NULL          ;Null für höhere Bits
  rcall Read_EEPROM
  in Schwellwertright, EEDR    ;Daten aus EPROM in Variable laden
  ;-------------------------------------------------------------------------



Read_EEPROM:
  sbic EECR,EEWE                  ;prüfe ob ein vorheriger Schreibzugriff
                                     ;beendet ist
    rjmp Read_EEPROM                ;nein, nochmal prüfen
  
  out EEARH, ZH           ;adresse lesen
    out EEARL, ZL            ;adresse laden
    sbi EECR, EERE                  ;Lesevorgang aktivieren
ret





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

NULL:
  .db 0b00000000

Autor: Thomas O. (kosmos)
Datum:

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

Autor: Otto (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein - hier musst Du wieder mit high() und low() arbeiten !

Autor: ANdy11 (Gast)
Datum:

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

Autor: Otto (Gast)
Datum:

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

Autor: MarioT (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

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

Autor: ANdy11 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aber wenn ich schreibe:
;Daten im EPROM definieren##################
.eseg
SchwellwertERAMleft:  ;Adresse 1
  .db ERAMregister
SchwellwertERAMmiddle:  ;Adresse 2
  .db ERAMregister  
SchwellwertERAMright:  ;Adresse 3
  .db ERAMregister  


WeissERAMlinks:      ;Adresse 4
  .db ERAMregister
WeissERAMrechts:    ;Adresse 5
  .db ERAMregister
WeissERAMmitte:      ;Adresse 6
  .db ERAMregister
;###########################################

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=
?

Autor: MarioT (Gast)
Datum:

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

Autor: Otto (Gast)
Datum:

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

Autor: Thomas O. (kosmos)
Datum:

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

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.