The EEPROM library only provides functions to read and write one byte at a time from the internal EEPROM.
I wrote some functions to read / write integers and strings which I thought could be useful to others, too.
NOTE: every time you run this example, the entire eeprom is overwritten with byte 0xFF.
// // EEPROM utility functions with usage example // // This example defines some utility functions // to write byte arrays, integers and strings // to eeprom and read them back. // // Some usage examples are provided. #include <EEPROM.h> // // Absolute min and max eeprom addresses. // Actual values are hardware-dependent. // // These values can be changed e.g. to protect // eeprom cells outside this range. // const int EEPROM_MIN_ADDR = 0; const int EEPROM_MAX_ADDR = 511; // // Initialize eeprom memory with // the specified byte. // Default value is 0xFF. // void eeprom_erase_all(byte b = 0xFF) { int i; for (i = EEPROM_MIN_ADDR; i <= EEPROM_MAX_ADDR; i++) { EEPROM.write(i, b); } } // // Dump eeprom memory contents over serial port. // For each byte, address and value are written. // void eeprom_serial_dump_column() { // counter int i; // byte read from eeprom byte b; // buffer used by sprintf char buf[10]; for (i = EEPROM_MIN_ADDR; i <= EEPROM_MAX_ADDR; i++) { b = EEPROM.read(i); sprintf(buf, "%03X: %02X", i, b); Serial.println(buf); } } // // Dump eeprom memory contents over serial port in tabular form. // Each printed row shows the value of bytesPerRow bytes // (by default 16). // void eeprom_serial_dump_table(int bytesPerRow = 16) { // address counter int i; // row bytes counter int j; // byte read from eeprom byte b; // temporary buffer for sprintf char buf[10]; // initialize row counter j = 0; // go from first to last eeprom address for (i = EEPROM_MIN_ADDR; i <= EEPROM_MAX_ADDR; i++) { // if this is the first byte of the row, // start row by printing the byte address if (j == 0) { sprintf(buf, "%03X: ", i); Serial.print(buf); } // read current byte from eeprom b = EEPROM.read(i); // write byte in hex form sprintf(buf, "%02X ", b); // increment row counter j++; // if this is the last byte of the row, // reset row counter and use println() // to start a new line if (j == bytesPerRow) { j = 0; Serial.println(buf); } // else just print the hex value with print() else { Serial.print(buf); } } } // // Returns true if the address is between the // minimum and maximum allowed values, // false otherwise. // // This function is used by the other, higher-level functions // to prevent bugs and runtime errors due to invalid addresses. // boolean eeprom_is_addr_ok(int addr) { return ((addr >= EEPROM_MIN_ADDR) && (addr <= EEPROM_MAX_ADDR)); } // // Writes a sequence of bytes to eeprom starting at the specified address. // Returns true if the whole array is successfully written. // Returns false if the start or end addresses aren't between // the minimum and maximum allowed values. // When returning false, nothing gets written to eeprom. // boolean eeprom_write_bytes(int startAddr, const byte* array, int numBytes) { // counter int i; // both first byte and last byte addresses must fall within // the allowed range if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) { return false; } for (i = 0; i < numBytes; i++) { EEPROM.write(startAddr + i, array[i]); } return true; } // // Reads the specified number of bytes from the specified address into the provided buffer. // Returns true if all the bytes are successfully read. // Returns false if the star or end addresses aren't between // the minimum and maximum allowed values. // When returning false, the provided array is untouched. // // Note: the caller must ensure that array[] has enough space // to store at most numBytes bytes. // boolean eeprom_read_bytes(int startAddr, byte array[], int numBytes) { int i; // both first byte and last byte addresses must fall within // the allowed range if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) { return false; } for (i = 0; i < numBytes; i++) { array[i] = EEPROM.read(startAddr + i); } return true; } // // Writes an int variable at the specified address. // Returns true if the variable value is successfully written. // Returns false if the specified address is outside the // allowed range or too close to the maximum value // to store all of the bytes (an int variable requires // more than one byte). // boolean eeprom_write_int(int addr, int value) { byte *ptr; ptr = (byte*)&value; return eeprom_write_bytes(addr, ptr, sizeof(value)); } // // Reads an integer value at the specified address. // Returns true if the variable is successfully read. // Returns false if the specified address is outside the // allowed range or too close to the maximum vlaue // to hold all of the bytes (an int variable requires // more than one byte). // boolean eeprom_read_int(int addr, int* value) { return eeprom_read_bytes(addr, (byte*)value, sizeof(int)); } // // Writes a string starting at the specified address. // Returns true if the whole string is successfully written. // Returns false if the address of one or more bytes // fall outside the allowed range. // If false is returned, nothing gets written to the eeprom. // boolean eeprom_write_string(int addr, const char* string) { // actual number of bytes to be written int numBytes; // we'll need to write the string contents // plus the string terminator byte (0x00) numBytes = strlen(string) + 1; return eeprom_write_bytes(addr, (const byte*)string, numBytes); } // // Reads a string starting from the specified address. // Returns true if at least one byte (even only the // string terminator one) is read. // Returns false if the start address falls outside // or declare buffer size os zero. // the allowed range. // The reading might stop for several reasons: // - no more space in the provided buffer // - last eeprom address reached // - string terminator byte (0x00) encountered. // The last condition is what should normally occur. // boolean eeprom_read_string(int addr, char* buffer, int bufSize) { // byte read from eeprom byte ch; // number of bytes read so far int bytesRead; // check start address if (!eeprom_is_addr_ok(addr)) { return false; } // how can we store bytes in an empty buffer ? if (bufSize == 0) { return false; } // is there is room for the string terminator only, // no reason to go further if (bufSize == 1) { buffer[0] = 0; return true; } // initialize byte counter bytesRead = 0; // read next byte from eeprom ch = EEPROM.read(addr + bytesRead); // store it into the user buffer buffer[bytesRead] = ch; // increment byte counter bytesRead++; // stop conditions: // - the character just read is the string terminator one (0x00) // - we have filled the user buffer // - we have reached the last eeprom address while ( (ch != 0x00) && (bytesRead < bufSize) && ((addr + bytesRead) <= EEPROM_MAX_ADDR) ) { // if no stop condition is met, read the next byte from eeprom ch = EEPROM.read(addr + bytesRead); // store it into the user buffer buffer[bytesRead] = ch; // increment byte counter bytesRead++; } // make sure the user buffer has a string terminator // (0x00) as its last byte if ((ch != 0x00) && (bytesRead >= 1)) { buffer[bytesRead - 1] = 0; } return true; } // // A pair of functions to show how long it takes to work with eeprom. // int start_time; int stop_time; void start_timing() { start_time = millis(); } void print_elapsed() { stop_time = millis(); Serial.print("Time elapsed (ms): "); Serial.println(stop_time - start_time); } // // SETUP // const int BUFSIZE = 50; char buf[BUFSIZE]; void setup() { int i; Serial.begin(115200); Serial.println("Erasing eeprom..."); start_timing(); eeprom_erase_all(); print_elapsed(), delay(1000); Serial.println("Dumping eeprom contents..."); eeprom_serial_dump_table(); delay(1000); strcpy(buf, "Arduino eeprom utility functions."); Serial.println("Saving string to eeprom..."); start_timing(); eeprom_write_string(100, buf); print_elapsed(); delay(1000); Serial.println("Dumping eeprom contents..."); eeprom_serial_dump_table(); delay(1000); // erase buffer for (i = 0; i < BUFSIZE; i++) { buf[i] = 0; } Serial.println("Reading string from eeprom..."); start_timing(); eeprom_read_string(100, buf, BUFSIZE); print_elapsed(); Serial.print("String read: '"); Serial.print(buf); Serial.println("'"); } // // LOOP // void loop() { }
=============
Many thanks to the original author of this. It saved me a lot of work!
I created a library in order to use this. I made the following two files from the above code and stored them in a new folder 'EepromUtil' in the libraries subdirectory of my Arduino folder. Then (after restarting the IDE) I was able to access the methods like so, e.g.:
#include <EepromUtil.h> #include <EEPROM.h> void setup() { EepromUtil::eeprom_erase_all(); EepromUtil::eeprom_write_int(8, 123); }
The two files are EepromUtil.h and EepromUtil.cpp:
EepromUtil.h:
// // Eeprom utilites library // // From https://playground.arduino.cc/Code/EepromUtil // #include <Arduino.h> #include <EEPROM.h> class EepromUtil { public: static void eeprom_erase_all(); static boolean eeprom_read_bytes(int startAddr, byte array[], int numBytes); static boolean eeprom_write_int(int addr, int value); static boolean eeprom_read_int(int addr, int* value); static boolean eeprom_write_string(int addr, char* string); static boolean eeprom_read_string(int addr, char* buffer, int bufSize); static boolean eeprom_write_bytes(int startAddr, const byte* array, int numBytes); private: static boolean eeprom_is_addr_ok(int addr); };
EepromUtil.cpp:
// // Eeprom utilites library // // From https://playground.arduino.cc/Code/EepromUtil // #include "EepromUtil.h" // // Absolute min and max eeprom addresses. // Actual values are hardware-dependent. // // These values can be changed e.g. to protect // eeprom cells outside this range. // const int EEPROM_MIN_ADDR = 0; const int EEPROM_MAX_ADDR = 1023; void EepromUtil::eeprom_erase_all() { char b = 0xff; int i; for (i = EEPROM_MIN_ADDR; i <= EEPROM_MAX_ADDR; i++) { EEPROM.write(i, b); } } // // Returns true if the address is between the // minimum and maximum allowed values, // false otherwise. // // This function is used by the other, higher-level functions // to prevent bugs and runtime errors due to invalid addresses. // boolean EepromUtil::eeprom_is_addr_ok(int addr) { return ((addr >= EEPROM_MIN_ADDR) && (addr <= EEPROM_MAX_ADDR)); } // // Writes a sequence of bytes to eeprom starting at the specified address. // Returns true if the whole array is successfully written. // Returns false if the start or end addresses aren't between // the minimum and maximum allowed values. // When returning false, nothing gets written to eeprom. // boolean EepromUtil::eeprom_write_bytes(int startAddr, const byte* array, int numBytes) { // counter int i; // both first byte and last byte addresses must fall within // the allowed range if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) { return false; } for (i = 0; i < numBytes; i++) { EEPROM.write(startAddr + i, array[i]); } return true; } // // Reads the specified number of bytes from the specified address into the provided buffer. // Returns true if all the bytes are successfully read. // Returns false if the star or end addresses aren't between // the minimum and maximum allowed values. // When returning false, the provided array is untouched. // // Note: the caller must ensure that array[] has enough space // to store at most numBytes bytes. // boolean EepromUtil::eeprom_read_bytes(int startAddr, byte array[], int numBytes) { int i; // both first byte and last byte addresses must fall within // the allowed range if (!eeprom_is_addr_ok(startAddr) || !eeprom_is_addr_ok(startAddr + numBytes)) { return false; } for (i = 0; i < numBytes; i++) { array[i] = EEPROM.read(startAddr + i); } return true; } // // Writes an int variable at the specified address. // Returns true if the variable value is successfully written. // Returns false if the specified address is outside the // allowed range or too close to the maximum value // to store all of the bytes (an int variable requires // more than one byte). // boolean EepromUtil::eeprom_write_int(int addr, int value) { byte *ptr; ptr = (byte*)&value; return eeprom_write_bytes(addr, ptr, sizeof(value)); } // // Reads an integer value at the specified address. // Returns true if the variable is successfully read. // Returns false if the specified address is outside the // allowed range or too close to the maximum vlaue // to hold all of the bytes (an int variable requires // more than one byte). // boolean EepromUtil::eeprom_read_int(int addr, int* value) { return eeprom_read_bytes(addr, (byte*)value, sizeof(int)); } // // Writes a string starting at the specified address. // Returns true if the whole string is successfully written. // Returns false if the address of one or more bytes // fall outside the allowed range. // If false is returned, nothing gets written to the eeprom. // boolean EepromUtil::eeprom_write_string(int addr, char* string) { // actual number of bytes to be written int numBytes; // we'll need to write the string contents // plus the string terminator byte (0x00) numBytes = strlen(string) + 1; return eeprom_write_bytes(addr, (const byte*)string, numBytes); } // // Reads a string starting from the specified address. // Returns true if at least one byte (even only the // string terminator one) is read. // Returns false if the start address falls outside // or declare buffer size os zero. // the allowed range. // The reading might stop for several reasons: // - no more space in the provided buffer // - last eeprom address reached // - string terminator byte (0x00) encountered. // The last condition is what should normally occur. // boolean EepromUtil::eeprom_read_string(int addr, char* buffer, int bufSize) { // byte read from eeprom byte ch; // number of bytes read so far int bytesRead; // check start address if (!eeprom_is_addr_ok(addr)) { return false; } // how can we store bytes in an empty buffer ? if (bufSize == 0) { return false; } // is there is room for the string terminator only, // no reason to go further if (bufSize == 1) { buffer[0] = 0; return true; } // initialize byte counter bytesRead = 0; // read next byte from eeprom ch = EEPROM.read(addr + bytesRead); // store it into the user buffer buffer[bytesRead] = ch; // increment byte counter bytesRead++; // stop conditions: // - the character just read is the string terminator one (0x00) // - we have filled the user buffer // - we have reached the last eeprom address while ( (ch != 0x00) && (bytesRead < bufSize) && ((addr + bytesRead) <= EEPROM_MAX_ADDR) ) { // if no stop condition is met, read the next byte from eeprom ch = EEPROM.read(addr + bytesRead); // store it into the user buffer buffer[bytesRead] = ch; // increment byte counter bytesRead++; } // make sure the user buffer has a string terminator // (0x00) as its last byte if ((ch != 0x00) && (bytesRead >= 1)) { buffer[bytesRead - 1] = 0; } return true; }