Forum: Mikrocontroller und Digitale Elektronik Problem mit EEPROM (ATMega8)


von Andy (Gast)


Lesenswert?

Hi,

ich versuch gerade ne Funktion zum auslesen von einem ATMega8 EEPROM zu 
bauen (ich weiß im AVR-Tutorial stehen welche).

Hier ist das Ding:
1
.cseg
2
;...
3
4
ldi zl, low(data)
5
ldi zh, high(data)
6
;...
7
8
read_eeprom:
9
10
  sbic EECR, EEWE      ; Ist der EEPROM bereit?
11
  rjmp read_eeprom    ; Nein,... dann nochmal prüfen
12
13
  out EEARH, ZH
14
  out EEARL, ZL      ; EEPROM-Adresse laden
15
16
  sbi EECR, EERE      ; ... und auslesen
17
  
18
  in byte, EEDR    ; Befehl ins "byte"-Register laden
19
20
  inc position      ; Den Positionszeiger um 1 erhöhen
21
22
  adiw zl:zh, 1      ; Z-Pointer um 1 erhöhen
23
  
24
  ret
25
  
26
27
  .eseg          ; --> EEPROM
28
  
29
  data: .db "Hi"

Nun müsste ja eigenltich "H" und dann "i" in char stehen. Bei mit kommt 
aber immer 0xFF.

Könnt ihr mir helfen? Ich bin am verzweifeln!

von H.Joachim S. (crazyhorse)


Lesenswert?

Programm sieht richtig aus, warum dann 'H' und 'i' drinstehen sollten, 
ergibt sich daraus nicht.
Wie kommst du darauf, dass das drin stehen müsste? Bzw. - dein Problem 
wird eher beim Schreiben liegen.

von Stefan K. (stefan1971)


Lesenswert?

Hallo Andy,

folgendes fällt mir dazu ein:

- Hast Du das EEPROM denn auch programmiert? Also nicht nur Dein 
Programm ins Flash schreiben (HEX-File), sondern auch die EEP-Datei ins 
EEPROM.
- Evtl. während der Routine die Interrupts sperren, also direkt nach 
"read_eeprom:" ein CLI und vor dem ret ein SEI einfügen.

Grüße, Stefan

von Martin V. (oldmax)


Lesenswert?

Hi
Bei mir laufen die beiden Subroutinen sauber.
1
;-------------------- Eintrag in EEprom schreiben -------------------------
2
 
3
Write_EProm:  SBIC  EECR, EEWE  ; Schreibvorgang beendet
4
    RJMP  Write_EProm
5
    OUT  EEARH, XH
6
    OUT   EEARL, XL
7
    OUT  EEDR, Buf_Reg
8
    ADIW  XH:XL,1
9
    IN  S_Merker, SReg
10
    CLI      ; Interrupts sperren
11
    SBI  EECR, EEMWE  ; Schreiben vorbereiten
12
    SBI  EECR, EEWE  ; schreiben
13
    OUT  SReg, S_Merker  ; SReg wieder herstellen
14
    RET
15
 
16
;-------------------- Eintrag aus EEProm lesen --------------------------
17
Read_EProm:  SBIC  EECR, EEWE
18
    RJMP  Read_EProm
19
    OUT  EEARH, ZH
20
    OUT  EEARL, ZL
21
    SBI  EECR, EERE
22
    IN   Buf_Reg, EEDR
23
    ADIW  ZH:ZL, 1
24
                  RET
Du solltest so Namen wie Byte vermeiden. Auch ich hab öfters Probleme 
mit der Namensgebung, aber oft genug bin ich auch mit solche 
"reservierten" Wörtern auf die Nase gefallen. Das Adressregister wird 
außerhalb der EEProm- Zugriffe gesetzt. Z.B.
1
         LDI      ZL,LOW(Wert_in Eprom)  ; X-Pointer auf Speicherzeile
2
         LDI      ZH,HIGH(Wert_in Eprom)
3
      
4
Go_Read:  RCALL  Read_EProm
5
  CPI  Buf_Reg, ';'      ; Byte_Cnt = 0 ?         
6
  BREQ  End_Read_Adress
7
  RCALL  irgendwas_EPromwert  ; Daten in Buf_Reg
8
  RJMP  Go_Read           ; nächsten Wert
9
End_Read_Adress: .....
Gruß oldmax

von Ka S. (kasuh)


Lesenswert?

Warum muss man eigentlich in "Write_EProm" das Status-Register sichern?

von Gastofatz (Gast)


Lesenswert?

Um die Wirkung von 'cli' wieder rückgängig zu machen.

von Andy (Gast)


Lesenswert?

schäm OMG! Ich habe beim flashen in PonnyProg das EEPROM-File immer in 
den Flashspeicher gebrannt.
Tut mir für den (unnötigen) Datenmüll leid den ich mit diesem Thread 
erzeugt habe.

von Ka S. (kasuh)


Lesenswert?

Ka Suh schrieb:
> Warum muss man eigentlich in "Write_EProm" das Status-Register sichern?

Gastofatz schrieb:
> Um die Wirkung von 'cli' wieder rückgängig zu machen.

Verstehe ich immer noch nicht. CLI macht man doch mit SEI rückgängig.
Das Status-Register zwischenspeichern kenne ich bisher nur innerhalb 
Interruptroutinen

Die Zeilen
1
  IN  S_Merker, SReg
und
1
  OUT  SReg, S_Merker
in  Write_EProm sind m. E. nicht nötig, oder liege ich da falsch?

von Ungast (Gast)


Lesenswert?

Ka Suh schrieb:
> Verstehe ich immer noch nicht. CLI macht man doch mit SEI rückgängig.
> Das Status-Register zwischenspeichern kenne ich bisher nur innerhalb
> Interruptroutinen

Mit dem Speichern und Zurückschreiben des SREG wird erreicht, dass die 
Routine aufgerufen werden kann, egal ob grade Interrupts aktiv sind oder 
nicht.

Wenn die Routine einfach mit SEI die interrupts wieder einschalten 
würde, könnte man sie nur noch aus Programmteilen mit gerade aktiven 
Interrupts heraus anspringen.

von Ka S. (kasuh)


Lesenswert?

Besten Dank, jetzt habe ich es verstanden. Anders ausgedrückt:

Interrupts werden nur dann wieder eingeschaltet,
wenn sie es vorher auch waren (und nicht wie bei SEI immer).

von Gastofatz (Gast)


Lesenswert?

>Interrupts werden nur dann wieder eingeschaltet,
>wenn sie es vorher auch waren (und nicht wie bei SEI immer).

Besser kann mans nicht beschreiben :-)

von Ka S. (kasuh)


Lesenswert?

Die Anzahl der Schreibzyklen auf eine EEPROM-Zelle ist bekanntlich 
begrenzt. Ist dies für den vorliegenden Anwendungsfall relevant, kann 
man die Schreibroutine verbessern, indem man vor dem Schreiben prüft, ob 
sich der zu schreibende Wert vom Zellinhalt unterscheidet und nur im 
Fall der Ungleichheit schreibt. Z.B. so:
1
 Write_EProm:
2
     SBIC  EECR, EEWE     ; Warten bis vorheriger Schreibvorgang beendet
3
     RJMP  Write_EProm
4
     OUT  EEARH, XH       ; Ausgabe-Adresse setzen
5
     OUT  EEARL, XL
6
7
     SBI  EECR, EERE      ; Prüfen ob Wert geändert wird
8
     IN   temp, EEDR
9
     cp   temp, Buf_Reg
10
     breq Write_EPrm_end
11
12
     OUT  EEDR, Buf_Reg
13
     IN   S_Merker, SReg
14
     CLI                  ; Interrupts sperren
15
     SBI  EECR, EEMWE     ; Schreiben vorbereiten
16
     SBI  EECR, EEWE      ; schreiben
17
     OUT  SReg, S_Merker  ; SReg wieder herstellen
18
   Write_EPrm_end:
19
     ADIW XH:XL,1
20
     RET

Ein ausgeklügelteres, wenn auch aufwändigeres Verfahren ist in der 
Appnote AVR101 zu finden. Beispielcode ist aber in C.

Kann da jemand den Code in Assembler vorzeigen?

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.