Forum: Mikrocontroller und Digitale Elektronik EEProm schreiben und auslesen


von SchwinneZ (Gast)


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.

von Karl H. (kbuchegg)


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.

von SchwinneZ (Gast)


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

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.