Forum: Compiler & IDEs EEPROM per direkter Adresse ansprechen


von Tim Schneider (Gast)


Lesenswert?

Hallo,

ich habe vor über einen I2C Temperaturfühler mit nem ATMega8 etwa jede 
Stunde die aktuelle Temperatur zu messen und anschliessend die Werte im 
EEPROM abzuspeichern.

Dazu würde ich gerne das EEPROM, das beim Mega 8 ja 512 Byte groß ist 
direkt per Adresse ansprechen. Ich habs mir so gedacht, dass ich an 
EEPROM Adresse 0x00 die aktuelle Position speichere an der der "Pointer" 
steht. An dieser Position speichere ich dann die Temperatur als Byte (1 
Grad Auflösung reicht absolut in einem Bereich von 0 bis 50 Grad). 
Anschließend wird der "Zähler" an Adresse 0x00 um 1 erhöht so dass der 
Controller nach einem Reset weiß wo die letzte Temperatur geschrieben 
wurde.

Also:
Volle Stunde erreicht -> Temperatur per I2C lesen -> aktuellen Zähler 
Wert aus dem EEPROM lesen -> Wert an diese Stelle schreiben -> Zähler im 
EEPROm erhöhen.

Ist das soweit ok? Und wenn ja, wie spreche ich das EEPROM mit absoluten 
Adressen an? Im AVR-GCC Tutorial wird immer mit Variablennamen und 
Pointern auf diese gearbeitet - niemals jedoch direkt.

Wäre über Hilfe sehr dankbar.

von Oliver (Gast)


Lesenswert?

Eine Lösung (steht auch im Tutorial):
Leg ein 512 byte großes Array ins EEPROM. Auf Index 0 speichertts du die 
aktuelle Datenposition. Dann kannst du über den Arrayindex direkt auf 
jede einzelne Speicherposition des Arrays, und damit des EEPROMS, 
zugreifen.

Oliver

von Peter D. (peda)


Lesenswert?

Tim Schneider wrote:

> Volle Stunde erreicht -> Temperatur per I2C lesen -> aktuellen Zähler
> Wert aus dem EEPROM lesen -> Wert an diese Stelle schreiben -> Zähler im
> EEPROm erhöhen.

Kann man machen, bewirkt aber eine höhere Schreibzyklenbelastung für die 
erste Adresse.
Man kann aber auch den EEPROM durchsuchen, bis 0xFF drinsteht, daß ist 
dann das erste freie Byte.


> Ist das soweit ok? Und wenn ja, wie spreche ich das EEPROM mit absoluten
> Adressen an?

Z.B. so, wie im Datenblatt beschrieben:
Adreßregister laden, Datenregister laden,Schreibimpuls setzen, warten 
bis Schreiben fertig.


Peter

von Stefan E. (sternst)


Lesenswert?

Tim Schneider wrote:

> Also:
> Volle Stunde erreicht -> Temperatur per I2C lesen -> aktuellen Zähler
> Wert aus dem EEPROM lesen -> Wert an diese Stelle schreiben -> Zähler im
> EEPROm erhöhen.
>
> Ist das soweit ok?

Du möchtest anscheinend das Schreiben auf das EEPROM verteilen, damit es 
länger hält. Aber was ist bei deinem Szenario mit EEPROM-Speicherzelle 
0? Was nützt es, das Schreiben der Daten zu verteilen, wenn jedes 
Daten-Schreiben ein zusätzliches Adressen-Schreiben auf immer die selbe 
Speicherzelle erzeugt?

> wie spreche ich das EEPROM mit absoluten Adressen an?

/* EEPROM-Speicherzelle 42 auslesen */
data = eeprom_read_byte((uint8_t*)42);
/* EEPROM-Speicherzelle 42 beschreiben */
eeprom_write_byte((uint8_t*)42,99);

@ Peter Dannegger:
> Man kann aber auch den EEPROM durchsuchen, bis 0xFF drinsteht, daß ist
> dann das erste freie Byte.

Das funktioniert aber nur max 512 Resets lang. ;-)

von Tim Schneider (Gast)


Lesenswert?

Hallo,

danke soweit schonmal für die Antworten :)
Auf die simple Idee ein 512 Byte großes Array anzulegen bin ich bisher 
garnicht gekommen...das ist darüber dann natürlich sehr einfach auf die 
einzelnen Speicherzellen zuzugreifen.

Ja irgendwie MUSS ich mir wohl oder übel die letze Schreibposition 
merken. An Adresse 0 den aktuellen Zähler mitzuschreiben ist wohl 
betrachtet auf die Lebensdauer der Speicherzellen wirklich suboptimal.

Alternativ könnte ich mir vorstellen immer ein 0xFF an die übernächste 
Position mitzuziehen. Das würde dann die Schreibzugriffe besser 
verteilen. Oder halteben ein externes EEPROM mit mehr Speicher nehmen. 
Das will ich aber möglichst vermeiden wegen dem Energieverbrauch. Ein 
externes EEPROM zieht zwar nicht viel Strom aber doch immer noch etwas. 
Im Batteriebetrieb macht sich das bemerkbar denke ich.

VG

von Oliver (Gast)


Lesenswert?

Bei ATMEL gibt es eine AppNote, in der ein Verfahren zu gleichmässigen 
Auslastung des EEPROMS beschrieben ist. Hab die Nummer gerade nicht 
griffbereit, musst halt mal suchen.

Oliver

von Stefan E. (sternst)


Lesenswert?

Du könntest z.B. auch zwei EEPROM-Bytes pro Datenbyte nehmen. Eines 
davon als Zähler, und dann erst beim Überlauf des Zählers zur nächsten 
2er-Gruppe springen. In EEPROM-Byte 0 könnte dann die Adresse der gerade 
aktuellen 2er-Gruppe stehen.

von Stefan E. (sternst)


Lesenswert?

Oliver wrote:
> Bei ATMEL gibt es eine AppNote, in der ein Verfahren zu gleichmässigen
> Auslastung des EEPROMS beschrieben ist. Hab die Nummer gerade nicht
> griffbereit, musst halt mal suchen.

101

von Tim Schneider (Gast)


Lesenswert?

@Stefan Ernst:

Deine Methode mit den zwei EEPROM Bytes pro Datenbyte ist aber nur 
einsetzbar wenn man ein einziges Datenbyte speichern will. Mir geht es 
ja darum mögichst viele Datenbytes gleichzeitig im EEPROM zu halten.
Ich denke ich komme nicht wirklich daran vorbei eine Speicherzelle immer 
wieder als "Zeiger" zu nutzen.

Das Applicaton Note 101 hab ich jetzt schon 5 mal durchgelesen aber es 
irgendwie immer noch nicht gecheckt :-D Vielleicht ist es einfach schon 
zu spät :)

von Stefan E. (sternst)


Lesenswert?

Tim Schneider wrote:

> Das Applicaton Note 101 hab ich jetzt schon 5 mal durchgelesen aber es
> irgendwie immer noch nicht gecheckt :-D Vielleicht ist es einfach schon
> zu spät :)

Du packst in das EEPROM zwei Ringpuffer (Funktion ist dir bekannt?), 
einen für die Daten und den anderen für einen Zähler. Beide laufen 
synchron. Wenn du ein Datenbyte in den Daten-Ringpuffer schreibst, 
schreibst du gleichzeitig in den Zähler-Ringpuffer einen fortlaufenden 
Wert. Dieser Zählerwert hat mit dem Datenbyte nichts zu tun. Er dient 
nur dazu, die aktuelle Position in den Ringpuffern zu markieren. Nach 
einem Reset findest du diese Position wieder, indem du im 
Zähler-Ringpuffer nach dem größten Wert suchst. Kritisch ist dabei ein 
Zählerüberlauf. Damit das auch direkt danach funktioniert, muss der 
Zähler-Ringpuffer beim Überlauf einmal komplett genullt werden.

von Markus Berend (Gast)


Lesenswert?

Ah, so einfach kanns also sein, leider schließe ich daraus, dass 
natürlich nur die Hälfte das EEPROMS zur Datenspeicherung genutzt werden 
kann. Das wären beim MEGA8 dann 256 bytes...könnte eventuell reichen :)
Danke für die Erklärung soweit :-p

von Nico E. (masta79)


Lesenswert?

Ich würde es einfach so machen, wenn du die Temperatur schreibst, dann 
schreib dahinter noch 0xFF, nach einem Reset findest du somit immer die 
zuletzt genutzte Position. Dann führst du im Programm noch einen Counter 
mit, damit du nicht jedesmal suchen musst.

Natürlich musst du dann noch aufpassen das du bei Byte 512 nicht 
versucht 513 mit 0xFF zu beschreiben, aber das ist ja recht easy.

Damit verteilst du die Schreibzugriffe über den ganzen EEPROM bereich. 
Bei 24 Werten pro Tag sollte sich die "Abnutzung" in Grenzen halten. ;)

von Stefan E. (sternst)


Lesenswert?

Auch ne gute Idee. Funktioniert aber natürlich nur dann, wenn die 
abzulegenden Daten niemals selber 0xFF sind.

PS: Hmm, das ist dann wohl auch das, was Peter Dannegger gemeint haben 
könnte. Ich habe ihn da wohl falsch verstanden. ;-)

von Nico E. (masta79)


Lesenswert?

Ok, 0xFF darf es dann natürlich nicht geben. Je nachdem wie genau du die 
Temperaturen willst kannst Du das natürlich "anpassen" ;) So genau sind 
die Sensoren sowieso nicht. ;)

Aber das wäre das einzige was mir einfällt um EEPROM-schonend zu 
arbeiten und trotzdem den ganzen Bereich zu nutzen.

Grundlegenden würde ich das halt so aufbauen (Nur runtergetippt, keine 
Garantie ;)):
1
uint16_t current_pos = 0;
2
3
while(eeprom_read_byte((uint8_t*)current_pos) == 0xFF) {
4
  if(++current_pos == 512) {
5
    current_pos = 0;
6
    break;
7
  };
8
};
9
10
while(1){
11
  uint8_t value = get_temp();
12
13
  eeprom_write_byte((uint8_t*)current_pos, (value == 0xFF ? 0xFE : value));
14
  eeprom_write_byte((uint8_t*)(current_pos==511 ? 0 : current_pos+1), 0xFF);
15
16
  if(++current_pos == 512)
17
    current_pos=0;
18
19
  sleep(1hour);
20
};

von John Conner (Gast)


Lesenswert?

Warum macht ihr euch überhaupt Gedanken darüber, den EEPROM-Speicher 
"gleichmäßig" auszunutzen? Ein Blick ins Datenblatt verrät, das das 
EEPROM 100000 Schreibzyklen verträgt. In der Praxis werden es sogar noch 
mehr sein. Wenn also die Werte alle Stunde gespeichert werden müssen, so 
sind das pro Jahr(!) nur 8760 Schreibzugriffe. Damit wäre das EEPROM 
frühestens nach etwa 11 1/2 Jahren am Ende...

von Tim Schneider (Gast)


Lesenswert?

@John Connor: Daran habe ich auch schon gedacht aber es ist ja auch mal 
prinzipiell gut sich über solche Dinge Gedanken zu machen!
Ich werde die Variante mit dem 0xFF mitziehen anwenden. So wird bei 
dieser Problemstellung der EEPROM optimal genutzt!

Danke an alle hier im Board!

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.