mikrocontroller.net

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


Autor: Andy (Gast)
Datum:

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

ldi zl, low(data)
ldi zh, high(data)
;...

read_eeprom:

  sbic EECR, EEWE      ; Ist der EEPROM bereit?
  rjmp read_eeprom    ; Nein,... dann nochmal prüfen

  out EEARH, ZH
  out EEARL, ZL      ; EEPROM-Adresse laden

  sbi EECR, EERE      ; ... und auslesen
  
  in byte, EEDR    ; Befehl ins "byte"-Register laden

  inc position      ; Den Positionszeiger um 1 erhöhen

  adiw zl:zh, 1      ; Z-Pointer um 1 erhöhen
  
  ret
  

  .eseg          ; --> EEPROM
  
  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!

Autor: H.Joachim Seifert (crazyhorse)
Datum:

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

Autor: Stefan K. (stefan1971)
Datum:

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

Autor: Martin Vogel (oldmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
Bei mir laufen die beiden Subroutinen sauber.
;-------------------- Eintrag in EEprom schreiben -------------------------
 
Write_EProm:  SBIC  EECR, EEWE  ; Schreibvorgang beendet
    RJMP  Write_EProm
    OUT  EEARH, XH
    OUT   EEARL, XL
    OUT  EEDR, Buf_Reg
    ADIW  XH:XL,1
    IN  S_Merker, SReg
    CLI      ; Interrupts sperren
    SBI  EECR, EEMWE  ; Schreiben vorbereiten
    SBI  EECR, EEWE  ; schreiben
    OUT  SReg, S_Merker  ; SReg wieder herstellen
    RET
 
;-------------------- Eintrag aus EEProm lesen --------------------------
Read_EProm:  SBIC  EECR, EEWE
    RJMP  Read_EProm
    OUT  EEARH, ZH
    OUT  EEARL, ZL
    SBI  EECR, EERE
    IN   Buf_Reg, EEDR
    ADIW  ZH:ZL, 1
                  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.
         LDI      ZL,LOW(Wert_in Eprom)  ; X-Pointer auf Speicherzeile
         LDI      ZH,HIGH(Wert_in Eprom)
      
Go_Read:  RCALL  Read_EProm
  CPI  Buf_Reg, ';'      ; Byte_Cnt = 0 ?         
  BREQ  End_Read_Adress
  RCALL  irgendwas_EPromwert  ; Daten in Buf_Reg
  RJMP  Go_Read           ; nächsten Wert
End_Read_Adress: .....
Gruß oldmax

Autor: Ka Suh (kasuh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum muss man eigentlich in "Write_EProm" das Status-Register sichern?

Autor: Gastofatz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um die Wirkung von 'cli' wieder rückgängig zu machen.

Autor: Andy (Gast)
Datum:

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

Autor: Ka Suh (kasuh)
Datum:

Bewertung
0 lesenswert
nicht 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
  IN  S_Merker, SReg
und
  OUT  SReg, S_Merker
in  Write_EProm sind m. E. nicht nötig, oder liege ich da falsch?

Autor: Ungast (Gast)
Datum:

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

Autor: Ka Suh (kasuh)
Datum:

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

Autor: Gastofatz (Gast)
Datum:

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

Besser kann mans nicht beschreiben :-)

Autor: Ka Suh (kasuh)
Datum:

Bewertung
0 lesenswert
nicht 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:
 Write_EProm:
     SBIC  EECR, EEWE     ; Warten bis vorheriger Schreibvorgang beendet
     RJMP  Write_EProm
     OUT  EEARH, XH       ; Ausgabe-Adresse setzen
     OUT  EEARL, XL

     SBI  EECR, EERE      ; Prüfen ob Wert geändert wird
     IN   temp, EEDR
     cp   temp, Buf_Reg
     breq Write_EPrm_end

     OUT  EEDR, Buf_Reg
     IN   S_Merker, SReg
     CLI                  ; Interrupts sperren
     SBI  EECR, EEMWE     ; Schreiben vorbereiten
     SBI  EECR, EEWE      ; schreiben
     OUT  SReg, S_Merker  ; SReg wieder herstellen
   Write_EPrm_end:
     ADIW XH:XL,1
     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?

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.