EEProm schreiben und auslesen

Gast #1292543
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
1
.include "m8def.inc"
2

3
.def temp = r16
4
.def temp1= r17
5
.def temp2 =r21
6
.def sreg_save = r18
7
.def data      = r19
8
.def zaehler   = r20
9
.equ AN=0xFF
10
.equ AUS=0x00
11

12

13
.cseg
14
.org 0
15
 
16
    ldi     temp, low(RAMEND)            ; Stackpointer initialisieren
17
    out     SPL, temp                    
18
    ldi     temp, high(RAMEND)
19
    out     SPH, temp     
20

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

28
  
29
Main:
30
  sbic    PinD, 3
31
  rjmp    SubMain
32
    
33
  sbi     PortD,6
34
  rcall   Wait
35
  sbic    PinD, 2
36
  ldi     data, AN
37
  sbis    PinD, 2
38
  ldi     data, AUS
39
  cbi     PortD,6
40
  rcall   Wait
41
  rcall   EEPROM_write
42
  adiw    ZL,1                        ; Zeiger erhöhen
43
  inc     zaehler
44
  cpi     zaehler, 10
45
  breq    SubMain
46
  rjmp    Main
47

48
SubMain:
49
  ldi    zaehler, 0x00        ;Zähler zurücksetzten
50
Main2:
51
  ldi     ZL,low(daten)              ; Zeiger zurücksetzen
52
  ldi     ZH,high(daten)
53
  rcall   EEPROM_read
54
  cpi     data, AN
55
  breq    LED_An
56
  rjmp    LED_Aus
57

58
Main3:
59
    adiw    ZL,1                        ; Zeiger erhöhen
60
    inc     zaehler
61
    cpi     zaehler, 10
62
    brne    Main2                     ; wenn ungleich, springen
63
    rjmp    loop
64

65
LED_An:
66
  sbi     PortD,5
67
  rcall   Wait
68
  rjmp    Main3
69

70
LED_Aus:
71
  cbi     PortD,5
72
  rcall   Wait
73
  rjmp    Main3
74

75
loop:
76
  rjmp loop
77

78
Wait:
79
  ldi     temp,0x40
80
Wait1:
81
  ldi     temp1,0xFF  
82
Wait2:
83
  ldi     temp2,0xFF
84
Wait3:
85
  dec     temp2
86
  brne    Wait3
87
  dec     temp1
88
  brne    Wait2
89
  dec     temp
90
  brne    Wait1
91
  ret
92

93
EEPROM_write:
94
    sbic    EECR, EEWE                  ; prüfe ob der letzte Schreibvorgang beendet ist
95
    rjmp    EEPROM_write                ; wenn nein, nochmal prüfen
96
 
97
    out     EEARH, ZH                   ; Adresse schreiben
98
    out     EEARL, ZL                   ; 
99
    out     EEDR,data                   ; Daten  schreiben
100
    in      sreg_save,sreg              ; SREG sichern
101
    cli                                 ; Interrupts sperren, die nächsten
102
                                        ; zwei Befehle dürfen NICHT
103
                                        ; unterbrochen werden
104
    sbi     EECR,EEMWE                  ; Schreiben vorbereiten
105
    sbi     EECR,EEWE                   ; Und los !
106
    out     sreg, sreg_save             ; SREG wieder herstellen
107
    ret
108

109
EEPROM_read:
110
    sbic    EECR,EEWE                   ; prüfe ob der vorherige Schreibzugriff
111
                                        ; beendet ist
112
    rjmp    EEPROM_read                 ; nein, nochmal prüfen
113
 
114
    out     EEARH, ZH                   ; Adresse laden
115
    out     EEARL, ZL    
116
    sbi     EECR, EERE                  ; Lesevorgang aktivieren
117
    in      data, EEDR                   ; Daten in CPU Register kopieren
118
    ret
119
    
120
.eseg
121
daten:
122
  .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.
#1292558
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.
Gast #1292572
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren