|

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

VorhabenSyntaxErläuterung
Library einbinden#include <EEPROM.h>
Größe des EEPROM-Speichers ermittelnuint16_t g = EEPROM.length()Angabe in Byte-Größe
Byte lesenuint8_t b = EEPROM.read(address)Der Speicherwert von adress wird gelesen
Byte schreibenEEPROM.write(address, value)Der Wert value (0..255) wird in adress geschrieben, braucht ca 3.3ms
Byte aktualisierenEEPROM.update(address, value)Nur falls sich der Wert in der Speicherzelle geändert hat wird er aktualisiert, das spart Schreibzyklen.
Block lesenEEPROM.get(address, data)Ein ganzer Block wird aus dem EEPROM gelesen und in data gespeichert (Call by Reference)
Block schreiben/aktualisierenEEPROM.put(address, data)Ein ganzer Block wird in das EEPROM geschrieben, dabei wird die update-Methode verwendet.
EEPROM als ARRAY verwendenuint8_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() {}