mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik EEProm schreiben und auslesen


Autor: SchwinneZ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

habe mir ein Programm geschrieben, welches 10 Werte über einen Taster 
abfrägt und im EEProm speichert.
Ist der Taster gedrückt wird 0xFF gespeichert, ist er nicht gedrückt 
0x00.
Nachdem 10 Messwerte aufgenommen wurden sollen diese wieder über eine 
LED ausgegeben werden.
0xFF = LED_an und 0x00=LED_aus

Hier ist der ProgrammCode

.include "m8def.inc"

.def temp = r16
.def temp1= r17
.def temp2 =r21
.def sreg_save = r18
.def data      = r19
.def zaehler   = r20
.equ AN=0xFF
.equ AUS=0x00


.cseg
.org 0
 
    ldi     temp, low(RAMEND)            ; Stackpointer initialisieren
    out     SPL, temp                    
    ldi     temp, high(RAMEND)
    out     SPH, temp     

  ldi     temp, 0b01100000             ;Eingänge und Ausgänge konfigurieren
  out     DDRD, temp
   
    ldi     ZL,low(daten)               ; der Z-Zeiger wird hier exclusiv
    ldi     ZH,high(daten)              ; für die Datenadressierung 
    ldi     zaehler, 0x00

  
Main:
  sbic    PinD, 3
  rjmp    SubMain
    
  sbi     PortD,6
  rcall   Wait
  sbic    PinD, 2
  ldi     data, AN
  sbis    PinD, 2
  ldi     data, AUS
  cbi     PortD,6
  rcall   Wait
  rcall   EEPROM_write
  adiw    ZL,1                        ; Zeiger erhöhen
  inc     zaehler
  cpi     zaehler, 10
  breq    SubMain
  rjmp    Main

SubMain:
  ldi    zaehler, 0x00        ;Zähler zurücksetzten
Main2:
  ldi     ZL,low(daten)              ; Zeiger zurücksetzen
  ldi     ZH,high(daten)
  rcall   EEPROM_read
  cpi     data, AN
  breq    LED_An
  rjmp    LED_Aus

Main3:
    adiw    ZL,1                        ; Zeiger erhöhen
    inc     zaehler
    cpi     zaehler, 10
    brne    Main2                     ; wenn ungleich, springen
    rjmp    loop

LED_An:
  sbi     PortD,5
  rcall   Wait
  rjmp    Main3

LED_Aus:
  cbi     PortD,5
  rcall   Wait
  rjmp    Main3

loop:
  rjmp loop

Wait:
  ldi     temp,0x40
Wait1:
  ldi     temp1,0xFF  
Wait2:
  ldi     temp2,0xFF
Wait3:
  dec     temp2
  brne    Wait3
  dec     temp1
  brne    Wait2
  dec     temp
  brne    Wait1
  ret

EEPROM_write:
    sbic    EECR, EEWE                  ; prüfe ob der letzte Schreibvorgang beendet ist
    rjmp    EEPROM_write                ; wenn nein, nochmal prüfen
 
    out     EEARH, ZH                   ; Adresse schreiben
    out     EEARL, ZL                   ; 
    out     EEDR,data                   ; Daten  schreiben
    in      sreg_save,sreg              ; SREG sichern
    cli                                 ; Interrupts sperren, die nächsten
                                        ; zwei Befehle dürfen NICHT
                                        ; unterbrochen werden
    sbi     EECR,EEMWE                  ; Schreiben vorbereiten
    sbi     EECR,EEWE                   ; Und los !
    out     sreg, sreg_save             ; SREG wieder herstellen
    ret

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      data, EEDR                   ; Daten in CPU Register kopieren
    ret
    
.eseg
daten:
  .db 0

Mein Problem ist, dass beide Routinen, also das Erfassen der Messwerte 
und speichern im EEPROM, als auch die Ausgabe über die Led EINZELN 
funktionieren. Das Programm das beides macht funktioniert nicht.
Die Werte werden dann zwar aufgenommen und gespeichert aber die Ausgabe 
funktioniert nicht.
Ich vermute das mein Fehler irgendwo dort liegt wo ich den ZPointer noch 
mal auf das Daten-Label setzte.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke mal, du hast dich selbst mit diesen vielen Sprüngen verwirrt. 
Sowas nennt man Spaghetticode, wenn da einen Haufen Sprünge kreuz und 
quer durch das Programm führen und Spaghetticode wird zu Recht verpönt. 
Jetzt weißt du auch warum

Zu deinem Problem:

...

Main3:
    adiw    ZL,1                        ; Zeiger erhöhen
    inc     zaehler
    cpi     zaehler, 10
    brne    Main2                     ; wenn ungleich, springen

Wenn der Zähler noch nicht bei 10 angelangt ist, gehts weiter bei Main2.
Was passiert dort?

Main2:
  ldi     ZL,low(daten)              ; Zeiger zurücksetzen
  ldi     ZH,high(daten)
  rcall   EEPROM_read

Autsch, damit zeigt dein Z-Pointer immer an den Anfang des 
Datenbereichs.
Das erhöhen war völlig für die Katz.

Autor: SchwinneZ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oooops, das war dumm von mir. Bin noch Anfänger auf dem Gebiet, von 
daher der verwirrte Code.
Das lustige an der ganzen Sache war das ich mir den Teil vom Code in dem 
die Ausgabe erfolgt rauskopiert habe. Und genau die 2 Zeilen
Main2:
  ldi     ZL,low(daten)              ; Zeiger zurücksetzen
  ldi     ZH,high(daten)

in die Submain verschoben hab.
Kein Wunder das dann die Ausgabe einzeln funktioniert hat xD

Danke

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.