mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 16f877a EEprom lesen/schreiben


Autor: Martin Geissmann (hb9tzw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Leider komme ich schon wieder nicht weiter bei einem Problem. Ich 
versuche Daten ins EEprom zu schreiben und beim Start die gespeicherten 
Daten wieder in die Variablen auszulesen. Wahrscheinlich habe ich Fehler 
im Code, denn während der Rest meines Programms in Picbasic Pro 
geschrieben ist, habe ich mich bei den EEprom-Routinen mit Assembler 
versuchen müssen, weil die Picbasic-Befehle auch nicht funktionierten. 
Es scheint ab und zu etwas ins EEprom geschrieben zu werden, jedoch nur 
unregelmässig und nicht das was geschrieben werden sollte. Das 
ausgelesene EEprom sieht dann etwa so aus:

86 10 00 00 00 58 00 00
FF FF 00 FF FF FF FF FF
86 10 00 00 00 58 00 00
FF FF 00 FF FF FF FF FF
86 10 00 00 00 58 00 00
FF FF 00 FF FF FF FF FF
... (die restlichen Zeilen sind genauso)

Ich habe zum Beispiel eine Routine wie folgt:

write_band:
    EEADR = $08
    Eedata = band
    asm
        bsf     status, RP0     ; Bank1
        bcf     intcon, GIE     ; Disable INTs
        bsf     eecon1, WREN    ; Enable Write
        movlw   055h            ;
        movwf   eecon2          ; 55h must be written to EECON2
        movlw   0AAh            ;  to start write sequence
        movwf   eecon2          ; Write AAh
        bsf     eecon1, WR      ; Set WR bit begin write
        bsf     intcon, GIE     ; Enable INTs
    endasm
    delayms 10
    Return

Diese sollte ins EEprom schreiben und wird aufgerufen, sobald die 
Variable "band" geändert wird.

Am Anfang des Programms steht dann die dazugehörige Leseroutine, die 
einmal beim Start aufgerufen wird:

asm
    bcf     status, RP0     ; Bank0
    movlw   0x08            ; Read address 8 in EEPROM space
    Movwf   eeadr           ; Address to read
    bsf     status, RP0     ; Bank1
    bsf     eecon1, RD      ; EE Read
    bcf     status, RP0     ; Bank0
    movf    eedata, W       ; W = EEDATA
endasm
band = eedata 'band ist eine bit-variable.

Ich kenne mich mit Assembler nicht gross aus, habe mich einfach an die 
Anweisungen in den Microchip-Papieren gehalten. Ich habe auch 
DWord-Variablen die im EEprom gespeichert werden sollen, dort führe ich 
diese Routinen einfach 4 Mal nacheinander aus für die 4 Bytes in einem 
DWord. Dass mein Code vielleicht nicht optimal ist kann gut sein, wie 
gesagt ich habe noch kaum Assembler programmiert.

Gibt es aber Fehler, die ich einfach nicht erkenne?

Gruss
Martin

Autor: Erhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Martin,

nach dem Befehl "bsf eecon1,wr" schreibst du "btfsc  eecon1,wr" und dann 
"goto  $-1".

Du verläßt die Schreibroutine erst, wenn die Speicherzelle auch wirklich 
beschrieben ist.

Autor: Martin Geissmann (hb9tzw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Erhard

Vielen Dank für die Hilfe!

Die Write-Routine sieht also jetzt so aus:

write_band:
    EEADR = $08
    Eedata = band
    asm
        bsf     status, RP0     ; Bank1
        bcf     intcon, GIE     ; Disable INTs
        bsf     eecon1, WREN    ; Enable Write
        movlw   055h            ;
        movwf   eecon2          ; 55h must be written to EECON2
        movlw   0AAh            ;  to start write sequence
        movwf   eecon2          ; Write AAh
        bsf     eecon1, WR      ; Set WR bit begin write
        btfsc   eecon1, WR      ; Wait for write to complete
        goto    $-1
        bsf     intcon, GIE     ; Enable INTs
    endasm
    delayms 10
    Return

Was bedeutet das "goto $-1" genau? D.h. auf welche Adresse verweist $-1?

Das Problem ist jetzt, nachdem ich diese beiden Zeilen bei jeder 
Write-Routine eingefügt habe, dass der Pic auf gar keine Eingabe mehr 
reagiert, keinen Taster und auch den Encoder nicht. Woran könnte das 
liegen?

Gruss
Martin

Autor: Dieter Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die special function register (SFR) EECON1 und EECON2 liegen auf der 
Registerbank 3, um die anzusprechen muss vorher noch STATUS,RP1 gesetzt 
werden (danach natürlich wieder zurücksetzen).

Beispiel:

    asm
        bsf     status, RP0     ; Bank1
        bcf     intcon, GIE     ; Disable INTs
        bsf     eecon1, WREN    ; Enable Write
        movlw   055h            ;
        bsf     status, RP1     ; Bank3
        movwf   eecon2          ; 55h must be written to EECON2
        movlw   0AAh            ;  to start write sequence
        movwf   eecon2          ; Write AAh
        bcf     status, RP1     ; Bank1
        bsf     eecon1, WR      ; Set WR bit begin write
        bsf     intcon, GIE     ; Enable INTs
    endasm

Autor: Martin Geissmann (hb9tzw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Vielen Dank auch dir Dieter für die Antwort. Funktionieren tat es nur 
mit dieser Änderung leider nach wie vor nicht, aber du hast mich auf das 
Problem aufmerksam gemacht.

Ich habe mir dann das mit den Bänken mal genauer überlegt und habe 
gemerkt, dass z.B. eecon1 auch auf Bank3 ist, und den Code entsprechend 
angepasst:

asm
    bsf   status, RP0          ; gehe auf Bank1
    bcf   intcon, GIE          ; lösche dort Bit GIE
    bsf   status, RP1          ; gehe auf Bank3
    bsf   eecon1, WREN         ; setze dort Bit WREN
    movlw 055h                 ;
    movwf eecon2               ; schreibe 55h in eecon2
    movlw 0AAh                 ;
    movwf eecon2               ; schreibe AAh in eecon2
    bsf   eecon1, WR           ; bleibe auf Bank3 weil eecon1 auch dort 
ist
    bcf   status, RP1          ; gehe wieder auf Bank1
    bsf   intcon, GIE          ; setze dort WIE wieder
endasm

Ebenso beim Lesen, dort sind eeadr auf Bank2 und eedata auf Bank3, dann 
muss es so heissen:

asm
    bcf     status, RP0     ;
    bsf      status, RP1     ; Bank2
    movlw   0x00            ; Read address 0 in EEPROM space
    Movwf   eeadr           ; Address to read
    bsf     status, RP0     ; Bank3
    bsf     eecon1, RD      ; EE Read
    bcf     status, RP0     ; Bank2
    movf    eedata, W       ; W = EEDATA
    bcf     status, RP1     ;
    bsf     status, RP0     ; kehre wieder zu Bank1 zurück
endasm

Nun scheint das ganze auch tatsächlich zu funktionieren! Ich war mir der 
ganzen Bank-Sache einfach gar nicht bewusst, aber jetzt leuchtet es mir 
ein. Ich möchte nach wie vor nicht mein ganzes Programm in Assembler 
schreiben, aber vielleicht verliert es ja doch einmal den "Buch mit 7 
Siegeln"-Status.

Danke an alle.

Gruss
Martin

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.