使用Arduino开发ESP32(05):EEPROM使用演示

目的

EEPROM可以在不使用文件和文件系统的情况下用来固化一些数据,常见的比如用来保存SSID或是Password,保存用户名及密码,保存用户设置等数据,可以实现更复杂的应用。

EEPROM使用说明

基础说明

  • Arduino core for the ESP32中的EEPROM是在flash中开辟的存储区域;
  • 调用#include <EEPROM.h>来使用EEPROM;
  • EEPROM库中默认已经定义了一个名为EEPROM的对象,一般情况下直接使用该对象即可,如果有需要用户也可以在flash中自定义新的EEPROM对象,使用方法参考文后链接;
  • 默认的EEPROM对象大小为4096字节,用户操作地址为0~4095;
  • 使用EEPROM时,首先调用EEPROM.begin(size),size为需要读写的数据字节最大地址+1,取值1~4096;
  • 使用EEPROM.write(addr,data)来写数据,参数分别为地址&数据,写数据后需要通过EEPROM.commit()EEPROM.end()将数据保存到EEPROM;
  • 使用EEPROM.read(addr)来读数据;
  • 还有更多的读写数据方法可以参考文后链接;

写数据

使用下面代码测试向EEPROM写入数据:

/*
该代码向EEPROM写入4096字节数据
*/
#include <EEPROM.h>

void setup() 
{
  Serial.begin(115200);
  Serial.println("");
  Serial.println("Start write");

  EEPROM.begin(4096); //申请操作到地址4095(比如你只需要读写地址为100上的一个字节,该处也需输入参数101)
  for(int addr = 0; addr<4096; addr++)
  {
    int data = addr%256; //在该代码中等同于int data = addr;因为下面write方法是以字节为存储单位的
    EEPROM.write(addr, data); //写数据
  }
  EEPROM.commit(); //保存更改的数据
  // EEPROM.end(); //同EEPROM.commit();

  Serial.println("End write");
}

void loop() 
{
}

在这里插入图片描述

读数据

使用下面代码测试从EEPROM读取数据:

/*
该代码从EEPROM读取4096字节数据
*/
#include <EEPROM.h>

void setup() 
{
  Serial.begin(115200);
  Serial.println("");
  Serial.println("Start read");

  EEPROM.begin(4096); //申请操作到地址4095(比如你只需要读写地址为100上的一个字节,该处也需输入参数101)
  for(int addr = 0; addr<4096; addr++)
  {
    int data = EEPROM.read(addr); //读数据
    Serial.print(data);
    Serial.print(" ");
    delay(2);
    if((addr+1)%256 == 0) //每读取256字节数据换行
    {
      Serial.println("");
    }
  }

  Serial.println("End read");
}

void loop() 
{
}

在这里插入图片描述

注意事项

当你需要分多次写EEPROM时,切记之后每次EEPROM.begin(size);中输入的size必须大于等于之前每次输入的值。简单点的话可以每次写入时这里都输入你可能会用到的最大值,比如如果对时间和内存要求不高的话这里可以写死4096。
可以用下面代码看看如果不这么做会出现的问题:

#include <EEPROM.h>

void setup()
{
  Serial.begin(115200);
  Serial.println("");

  //////////第一次写入
  Serial.println("申请操作到地址9");
  Serial.println("向地址0~9分别写入数据0~9然后提交");
  EEPROM.begin(10);
  for (int addr = 0; addr < 10; addr++)
  {
    EEPROM.write(addr, addr);
  }
  EEPROM.commit();
  Serial.println("");

  //////////读取第一次写入后状态
  Serial.println("申请操作到地址14");
  Serial.println("读取并打印地址0~14上数据");
  EEPROM.begin(15);
  for (int addr = 0; addr < 15; addr++)
  {
    int data = EEPROM.read(addr);
    Serial.print(data);
    Serial.print(" ");
  }
  Serial.println("");
  Serial.println("");

  //////////第二次写入
  Serial.println("申请操作到地址4");
  Serial.println("向地址2和3写入数据77然后提交");
  EEPROM.begin(5);
  EEPROM.write(2, 77);
  EEPROM.write(3, 77);
  EEPROM.commit();
  Serial.println("");

  //////////读取第二次写入后状态
  Serial.println("申请操作到地址14");
  Serial.println("读取并打印地址0~14上数据");
  EEPROM.begin(15);
  for (int addr = 0; addr < 15; addr++)
  {
    int data = EEPROM.read(addr);
    Serial.print(data);
    Serial.print(" ");
  }
  Serial.println("");
  Serial.println("");
}

void loop()
{
}

在这里插入图片描述
从上面可以看到第一次写入时size为10,相当于操作可以操作到地址9,第二次写入时可以size为5,可以操作到地址4,第二次写入提交后地址0~7上的数据符合我们操作,但原先地址8和9上的数据被莫名其妙改变了,这并不是我们所期望的。
这个问题产生原因如下:

  1. 对EEPROM的操作以4字节为单位,比如上面中第一次size写10时,程序自动将size转成了12处理,第二次size写5时,程序自动将size转成了8处理;
  2. 每次EEPROM.begin(size)时程序会建立一个size长度的缓存,然后从EEPROM地址0开始依次读取size个数据到缓存,你之后的readwrite操作的都是这个缓存;
  3. 当你使用commitend时,程序会将上面的缓存依次从地址0开始写入EEPROM;
  4. 问题就出在上面那步,因为ESP32的EEPROM并非真正的EEPROM,只是从flash上划了一个扇区用,所以读写都只能按扇区(4096字节)来,那么在写入的时候从地址0开始的size个数数据时ok的,但后面4096-size个数据就可能会被改变;

可以看到第二次写操作时程序其实是将EEPROM中地址0-7的数据读取到一个缓存中,然后我们修改了这个缓存中地址2和3的值,最后将修改后的缓存写回EEPROM地址0-7,根据上面原因地址7之后的数据就完全不受控了。

总结

EEPROM的使用比较简单,更多内容可以参考如下:
https://github.com/espressif/arduino-esp32/tree/master/libraries/EEPROM

扫描二维码关注公众号,回复: 8727515 查看本文章
发布了66 篇原创文章 · 获赞 176 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/Naisu_kun/article/details/86690493