EEPROM per direkter Adresse ansprechen

Gast #920655
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.
Gast #920691
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
#920714
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
#920728
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. ;-)
Gast #920851
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
Gast #921807
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 :)
#921931
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.
Gast #922932
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
#922959
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. ;)
#922975
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
};
Gast #922976
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...
Gast #922990
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!

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