Forum: Mikrocontroller und Digitale Elektronik ASM: eeprom schreiben über Stack (Atmega8)


von Axel H. (mf-futzi)


Lesenswert?

Hallo an alle,

habe mir zur Steuerung meiner Gartenbewässerung ein ASM-Programm 
geschrieben. Durch 2 Schwimmersensoren wird ein Vorratstank überwacht.Im 
LCD werden dann die Zustände (ein/aus) einer Tauchpumpe und eines 
Hauswasserwerkes angezeigt bzw gesteuert.  Sind beide ausgeschaltet wird 
die aktuelle Uhrzeit mit Datum angezeigt. Im Hintergrund läuft ein 
Zähler, der die Gesamtlaufzeit der Tauchpumpe zählt. Soweit funktioniert 
alles einwandfrei.

Nun zu meiner Frage:
Die Gesamtlaufzeit speichere ich auf dem SRAM mit den Variablen CntMin, 
CntStd und CntTage ab. Nun möchte ich diese Werte gerne in das Eeprom 
schreiben, damit sie bei einem Stromausfall erhalten bleiben. Im Moment 
mache ich das so:

EEPROM_writeMin:

        lds     temp2, CntTotMin  ; Zählerstand Minuten

        sbic    EECR,EEWE
        rjmp    EEPROM_writeSek

        ldi     temp1, high(0)    ; Adresse
        out     EEARH, temp1
        ldi     temp1, low(0)    ; Adresse
        out     EEARL, temp1

        out     EEDR, temp2    ; Minuten ins Eeprom

        cli
        sbi     EECR, EEMWE
        sbi     EECR, EEWE
        sei

  ret

Das gleiche Unterprogramm habe ich für Stunden und Tage geschrieben:

EEPROM_writeStd:

EEPROM_writeTage:

Ich erhöhe jeweils nur die Adresse um 1 und verwende ensprechend die 
Variablen CntTotStd bzw CntTotTage.

So wie ich das mache ist das sicherlich sehr "unelegant" ;-) (3x das 
gleiche Programm!)

Man müsste das doch auch über den Stack machen können, aber ich weis 
einfach nicht wie.

Also nach meiner Vorstellung in einer Schleife etwa so:
Adresse_1 auf den Stack (?)
CntMin in Stack laden
in eeprom schreiben

Adresse um 1 erhöhen
CntStd in den Stack laden
in eeprom schreiben

...usw.

Wäre schön, wenn mir jemand dabei einen Tipp geben könnte.

Axel

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Mit dem Stack meinst Du sicherlich nicht den im Controller. Ansonsten 
schreibt man sich verändernde Werte in ein Array im SRAM 
(aufeinanderfolgende Speicherzellen) und schreibt / liest diese über 
indirekte Adressierung über X, Y oder Z-Register.

ldi XH, high(array)
ldi XL, low(array)

ld  Temp, X+

...

eeprom-routine, die den Wert aus Temp wegspeichert

...

von Axel H. (mf-futzi)


Lesenswert?

Hallo  Travel Rec.,

danke für die Antwort, aber leider weis ich im Moment noch nicht, wie 
sich ständig ändernde Werte in ein array schreiben lassen. (Mache mit 
asm erst seit kurzer Zeit). Ich habe hier im Forum gesucht, aber fast 
nur Beiträge in "C" gefunden.
Also ich will natürlich keinen fertigen Code. Vielleicht kann mir jemand 
in groben Worten die Reihenfolge erklären, wie man das macht.


Danke für die Unterstützung

von Uwe (Gast)


Lesenswert?

Hi!
So könnte man es auch schreiben:

EEPROM_writeCNT:

        ldi     XH, high(0)    ; Adresse
        ldi     XL, low(0)    ; Adresse
        lds     temp2, CntTotMin  ; Zählerstand Minuten
        rcall   EEWR
        lds     temp2, CntTotStd  ; Zählerstand Stundem
        rcall   EEWR
        lds     temp2, CntTotTage  ; Zählerstand Tage
        rcall   EEWR
        ret

EEWR:   sbic    EECR,EEWE
        rjmp    EEWR
        out     EEARH, XH
        out     EEARL, XL
        out     EEDR, temp2    ; Minuten ins Eeprom
        cli
        sbi     EECR, EEMWE
        sbi     EECR, EEWE
        sei
        adiw    XL,1           ;Adresse+1
        ret

Man kann es auch über den Stack machen, halte ich aber für aufwendiger.

Viel Erfolg, Uwe

von Axel H. (mf-futzi)


Lesenswert?

Hallo Uwe,

das ist ja toll und für mich ein guter Ansatz! Für meine 3 Werte ins 
Eeprom zu schreiben sicherlich ausreichend. Ich muss mir deine 
Codezeilen morgen mal genau ansehen, und in Befehlcodes des Atmega8 
nachlesen, was da genau passiert.

Vielen Dank erstmal. Ich melde mich nochmal, wenn's geklappt hat.

von Axel H. (mf-futzi)


Lesenswert?

Hallo Uwe,

das hat super geklappt. Auf die gleiche Weise werde ich das mit dem 
Eeprom-lesen machen (in der Init in meinem Programm).

Nochmal um sicher zu gehen: Wenn ich das EEprom-Schreiben jede Minute 1x 
aufrufe, dann muss ich damit rechnen, dass der eeprom nach 69 Tagen 
nicht mehr beschreibbar ist? (100.000 /60/24 = 69,4)

Und wenn ich dann jede Stunde 1x schreibe, dann hält er immerhin 11 
Jahre (100.000/24/356 = 11,7)


 Ist das so richtig?

von crazy horse (Gast)


Lesenswert?

so krass, wie im Datenblatt angegeben ist es nicht - das sind 
garantierte Lösch/Schreibzyklen, in der Praxis hält es länger. Aber im 
Prinzip schon, minütlich diesselbe Zelle schreiben geht nicht lange gut 
:-)
Alternativen:
-seltener Schreiben (evtl. hat sich auch gar nichts gändert?, vorher 
prüfen)
-Variablen im RAM halten, Spannung vor dem Regler überwachen, bei 
drohendem Ausfall schnell noch ins Eeprom schreiben
-Speicherzellen wechseln
-ext. FRAM dran

von Axel H. (mf-futzi)


Lesenswert?

Hallo crazy horse,

ich bin's nochmal mit meinem EEprom. Auf diese Möglichkeiten bin ich gar 
nicht gekommen. ;-)

> -seltener Schreiben (evtl. hat sich auch gar nichts gändert?, vorher
> prüfen)

OK. Also das bekomme ich selber hin.

> -Variablen im RAM halten, Spannung vor dem Regler überwachen, bei
> drohendem Ausfall schnell noch ins Eeprom schreiben.

Das heisst, ich muss die Eingangsspannung des 7805 überwachen. So etwas 
habe ich bis jetzt noch nicht gemacht. Brauche ich da noch eine externe 
Beschaltung und in einen freien pin einlesen? Diese Spannung muß ich 
doch sicher mit einem Wert vergleichen?

Wie gesagt, ich will keinen fertigen Code, sondern nur die Richtung, wie 
ich vorgehen muss.

Axel

von Axel H. (mf-futzi)


Lesenswert?

Hallo,

also irgendwie ist in meinem Programm der Wurm drin :-(

Ich habe mein Programm im Moment so geschrieben, dass zu jeder vollen 
Stunde der eeprom mit den aktuellen Daten beschrieben wird.

In Ponyprog drücke ich nun die Taste 'Read Data Memory (Eeprom)', um zu 
überprüfen, ob die Daten nun im eeprom stehen. Beim Lesen tritt ein 
Reset des uC auf. Ist das korekt? Das ist mir noch nie aufgefallen. Oder 
mache ich da einen Fehler?

von Axel H. (mf-futzi)


Lesenswert?

Hallo,

habe gerade einen Beitrag gefunden 'Schreibzugriffe minimieren' : 
http://www.mikrocontroller.net/articles/Speicher#EEPROM

Somit ist das klar.

Kann mir noch jemand sagen, ob es normal ist, dass beim Lesen des 
Atmega8 Eeproms durch Ponyprog ein Reset ausgelöst wird?

Vielen Dank

von Uwe (Gast)


Lesenswert?

Hi!
Ja, es ist normal.

MFG Uwe

von Axel H. (mf-futzi)


Angehängte Dateien:

Lesenswert?

Hallo an alle,

ich habe mich nun doch entschlossen, das eeprom nur bei einem 
Spannungsabfall zu beschreiben. Dazu habe ich diese Seite gefunden:

http://www.mikrocontroller.net/articles/Speicher

Ich bin mir aber nicht sicher, wie ich meinen Atmega8 richtig an dieser 
Schaltung anschließe. Ich würde das so machen:

Vin = Spannung vom Netzteil
Gnd = Gnd (Pin8)
N_Power_fail = Anschluß uC externer Interrupt (Pin4/Int0)
Vcc = Spannung uC (Pin7)

Das bedeutet aber, daß im Normalbetrieb der gesamte Strom über die Diode 
1N4148 läuft. An 3 uC-Augängen habe ich Transistoren BC547 
angeschlossen. Ist die Diode ausreichend oder wäre es sinnvoll, eine 
Diode mit größerem Stromfluß zu verwenden?

von butrus (Gast)


Lesenswert?

Würde es nicht sicherer eine FRAM zu benutzen?

von Axel H. (mf-futzi)


Lesenswert?

hallo,

> Würde es nicht sicherer eine FRAM zu benutzen?

also ich habe in meiner Steuerung nur ca. 10-15 byte zu speichern 
(veränderbare Einstellungen und Einschaltdauer der Pumpe). Und da der 
Atmega8 einen ausreichend grossen Eeprom hat, würde ich den auch gerne 
nutzen.

Axel

von Axel H. (mf-futzi)


Lesenswert?

Hallo an alle,

ich habe nun die Schaltung nach obiger Abbildung in mein Projekt 
eingebaut. Technisch funktioniert die Schaltung, d.h. nachdem ich den 
Netzstecker ziehe wird der Interrupt INT0 ausgelöst und die Daten ins 
EEprom geschrieben. Das Problem: Mit dem Wert des Elkos komme ich nicht 
aus. Ich habe nun noch nachträglich 2 Elkos mit je 1000 uF hinzugefügt, 
aber die letzten 2-3 byte werden nicht zuverlässig geschrieben.

Meine Schaltung enthält den Atmega8L (2,7-5,5V) mit ext. Quarz 3,6864 
MHz. Am Anschluss Vcc habe ich nur den uC angeschlossen. Andere 
Verbraucher werden separat versorgt.

Natürlich könnte ich noch einen weiteren Elko einlöten, um die letzten 
bytes noch zuverlässig zu schreiben, finde ich aber Verschwendung.

Nun meine Frage(n): Wonach sind die Werte der Widerstände R1 und R3 
bemessen (je 100k)? Ist durch geringere Werte der Widerstände eine 
frühere Auslösung des Interrupts zu erreichen? Wie müssten die bemessen 
werden?



Ich bitte nochmal um Euere Hilfe

von Ekschperde (Gast)


Lesenswert?

> Mit dem Wert des Elkos komme ich nicht
> aus. Ich habe nun noch nachträglich 2 Elkos mit je 1000 uF hinzugefügt,

Nimm halt einen Goldcap :-)

von Axel H. (mf-futzi)


Lesenswert?

Hallo,

> Nimm halt einen Goldcap :-)

Ich müsste mir zwar erst einen besorgen, aber das könnte ich tun.

Aber ich wollte meine Schaltung nach diesem Artikel hier im Netz 
nachbauen. Oder stimmt der nicht mehr?

von Falk B. (falk)


Lesenswert?

@Axel Hüser (mf-futzi)

>EEprom geschrieben. Das Problem: Mit dem Wert des Elkos komme ich nicht
>aus. Ich habe nun noch nachträglich 2 Elkos mit je 1000 uF hinzugefügt,
>aber die letzten 2-3 byte werden nicht zuverlässig geschrieben.

Na dann lies mal den Artikel, miss die Stromaufnahme und rechne.

Der AVR braucht je nach Typ 5..10ms/Byte zum schreiben. Macht bei 10..15 
Byte zwischen 75..150ms. Schon ne ganze Weile.

Und schau dir mal die zweite Lösung mit grossem Pufferelko VOR dem 
Spannungsregler an.

>Nun meine Frage(n): Wonach sind die Werte der Widerstände R1 und R3
>bemessen (je 100k)?

Pi mal Daumen, sind reine Signale, dort geht es nicht um Leistung.

> Ist durch geringere Werte der Widerstände eine
>frühere Auslösung des Interrupts zu erreichen?

Nein.

MFG
Falk

von Axel H. (mf-futzi)


Lesenswert?

Hallo Falk,

danke für deine Antwort. Dann werd ich meine Platine doch mit dem 
separaten LP2950 erweitern müssen. (da wirds richtig eng auf der 
Platine)

Ich bin halt von dem Beispiel ausgegangen: für 32 Byte Speicherung wird 
rechnerisch ein Elko mit 48,9 uF benötigt. Bei 5-facher Sicherheit 
ergibt sich dann ein Wert von 250 uF. Mit meinen 15 byte wäre ich dann 
auf der sicheren Seite gewesen (hab aber nicht die Werte des 
Beispieltyps ATiny2313 mit dem Atmega8 verglichen).

Axel

von Axel H. (mf-futzi)


Lesenswert?

Hallo, ich bin's nochmal.

Ich hab mir heute doch einen Golcap besorgt, weil platzsparender.

Ich hab bis jetzt noch keine Erfahrung mit diesen Bauteilen. Muss ich 
die vorhandenen Elkos entfernen oder kann ich den Goldcap parallel zu 
den Elkos dazulöten? (mit richtiger Polung natürlich)



Axel

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.