AVR-EEPROM mit Arduino nutzen 🚧
- Der EEPROM-Speicher bei den AVR-Arduinos (UNO,MEGA usw.) ist ein byteweise organisierter nicht flüchtiger Speicher.
- Die Speicher-Bytes können ca. 100000 mal neu beschrieben werden.
- Schreiben braucht ca. 3,3ms.
- Speicherzellen, die noch nie beschrieben wurden haben als Wert 255 (Init-Wert nach Produktion).
- Arduino UNO, Nano 1 ki Byte
- Arduino Mega 4 ki Byte
API-Befehlsübersicht
| Vorhaben | Syntax | Erläuterung |
|---|---|---|
| Library einbinden | #include <EEPROM.h> | |
| Größe des EEPROM-Speichers ermitteln | uint16_t g = EEPROM.length() | Angabe in Byte-Größe |
| Byte lesen | uint8_t b = EEPROM.read(address) | Der Speicherwert von adress wird gelesen |
| Byte schreiben | EEPROM.write(address, value) | Der Wert value (0..255) wird in adress geschrieben, braucht ca 3.3ms |
| Byte aktualisieren | EEPROM.update(address, value) | Nur falls sich der Wert in der Speicherzelle geändert hat wird er aktualisiert, das spart Schreibzyklen. |
| Block lesen | EEPROM.get(address, data) | Ein ganzer Block wird aus dem EEPROM gelesen und in data gespeichert (Call by Reference) |
| Block schreiben/aktualisieren | EEPROM.put(address, data) | Ein ganzer Block wird in das EEPROM geschrieben, dabei wird die update-Methode verwendet. |
| EEPROM als ARRAY verwenden | uint8_t value = EEPROM[address] EEPROM[address] = value | Das EEPROM kann als Array adressiert werden. |
Beispiel: EEPROM auslesen
#include <EEPROM.h>
void setup() {
Serial.begin(115200);
byte b;
Serial.print(F("Groesse des EEPROM-Speichers: "));
Serial.println(EEPROM.length());
Serial.println(F("Speicherzellen abweichend von 255:"));
bool jungfrau = true; // noch keine Zelle != 255
for(int i=0;i<EEPROM.length();i++){ // gehe alle Zellen durch
b = EEPROM.read(i); // Lesen
if(b!=255){ // Zelle wurde beschrieben
jungfrau=false;
Serial.print(i);
Serial.print(F("\t"));
Serial.println(b);
}
}
if(jungfrau){
Serial.println(F("Alle Speicherzellen haben 255!"));
}
}
void loop() {}
Wie funktioniert EEPROM.get(address, data) und EEPROM.put(address, data) genau?
Die EEPROM.h anschauen und staunen (Pointer-Voodoo-> 1.1d 🚧 C Datentypen für Arduino):
//Functionality to 'get' and 'put' objects to and from EEPROM.
template< typename T > T &get( int idx, T &t ){
EEPtr e = idx;
uint8_t *ptr = (uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e;
return t;
}
template< typename T > const T &put( int idx, const T &t ){
EEPtr e = idx;
const uint8_t *ptr = (const uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ );
return t;
}
Es wird einfach byteweise zwischen EEPROM und RAM kopiert. Beispiele siehe 🔗 docs.arduino.cc/learn/built-in-libraries/eeprom/ . ToDo Ablauf visualisieren..
Betriebszähler long neustarts mit get/put realisieren
#include <EEPROM.h>
uint32_t neustarts = 0; // soll die Anzahl der µC Starts zählen
void setup() {
Serial.begin(115200);
EEPROM.get(0,neustarts); // lies die ersten 4 Bytes
if(neustarts==0xFFFFFFFF){ // wenn noch nie EEPROM beschrieben wurde
neustarts=1;
Serial.println(F("Erster Neustart"));
}
else {
neustarts++;
Serial.print(F("Neustart-Nr. "));
Serial.println(neustarts);
}
EEPROM.put(0,neustarts); // neustarts schreiben
byte b;
for(int i=0;i<EEPROM.length();i++){ // gehe alle Zellen durch
b = EEPROM.read(i); // Lesen
if(b!=255){ // Zelle wurde beschrieben
Serial.print(i);
Serial.print(F("\t"));
Serial.println(b);
}
}
}
void loop() {}
