查询了很多资料,反复尝试总出现各种错误。目前针对结构体参数存储数据到EEPROM进行了尝试和总结,以便学习使用。
废话少说:直接代码并注解!【首发于头条,转发于此,更多资源关注,久爱物联网】
【重点】
1、写要提交,方法不能遗漏!EEPROM.end();或EEPROM.commit();必具其一,建议前者
2、内存空间申请大小必须大于结构体数据长度(4的倍数) 如:EEPROM.begin(128);
3、存储地址不能重叠,且有效利用!!寸土是金!上一数据地址+1开始
/*****************************************************
调用#include <EEPROM.h>来使用EEPROM;
使用EEPROM时,首先调用EEPROM.begin(size),size为需要读写的数据字节最大地址+1,取值4~4096;
使用EEPROM.write(addr,data)来写数据,参数分别为地址&数据,写数据后需要通过EEPROM.commit()或EEPROM.end()将数据保存到EEPROM;
使用EEPROM.read(addr)来读数据;
*久爱物联网(jiuaiiot)* 注意事项 *
当你需要分多次写EEPROM时,切记之后每次EEPROM.begin(size);中输入的size必须大于等于之前每次输入的值。
简单点的话可以每次写入时这里都输入你可能会用到的最大值,比如如果对时间和内存要求不高的话这里可以写死4096。
你每次操作EEPROM,根据你输入的size,会建立一个size大小的缓存并从EEPROM地址0开始读取size长度数据到该缓存,你之后的读写操作是对这个缓存的操作。
当你提交写入的时候,程序才会把缓存中的数据写入EEPROM,但是EEPROM的写入是以扇区为单位的(4096字节)
那么在写入的时候从地址0开始的size个数数据时ok的,但后面4096-size个数据就可能会被改变(我目前遇到的就是后面的数据都变255了)。
这应该是这个库的一个逻辑bug。因为ESP8266的EEPROM并非真正的EEPROM,只是从flash上划了一个扇区用,所以读写都只能按扇区来。
******************************************************/
//引用头文件
#include <EEPROM.h>
//定义一个写和读的通用方法
#define EEPROM_write(address,p) { int i = 0;byte *pp = (byte*)&(p);for(;i<sizeof(p);i++) EEPROM.write(address+i,pp[i]);EEPROM.end();}
#define EEPROM_read(address,p) { int i = 0;byte *pp = (byte*)&(p);for(;i<sizeof(p);i++) pp[i]=EEPROM.read(address+i);}
//注意事项 写的结尾一定要有EEPROM.end();或EEPROM.commit();目的就是提交保存操作否则不保存成功
//测试2个结构体不同的存储地地址
struct config_type
{//sizeof(config_type)=72
int date1;
float date2;
char date3[64];
}cfgtype;//声明别名cfgtype
//结构体2
struct config_jiuai
{//sizeof(config_jiuai)=128
char jiuai[128];
}cfgjiuai;//声明别名cfgjiuai
void eeprom_test() {
Serial.println(sizeof(cfgtype));//72
cfgtype.date1 = 6266;
cfgtype.date2 = 3.14;
strcpy(cfgtype.date3, "{\"fuwuhao\":\"jiuaiiot\",\"tel\":\"180***77\"}");// 标准json字符串;赋值方法strcpy()
EEPROM.begin(128);//申请内存空间
EEPROM_write(0, cfgtype); //写入到0地址的结构体变量
//-------结构体1写结束-------------
EEPROM.begin(256);//申请空间必须大于结构体长度,4的倍数
sprintf(cfgjiuai.jiuai,"{\"tel\":\"%s\",\"mode\":%d,\"automode\":%d}","180***66",1,0);
//赋值方法 标准json格式
Serial.println(sizeof(cfgjiuai));
EEPROM_write(129, cfgjiuai);//写地址128+1 结构体2
//EEPROM.commit(); //上方法中提交
Serial.println("write ok!");
//-----------结构体1读------------
config_type readback;//结构体变量(读)
EEPROM.begin(128);//申请内存空间
EEPROM_read(0, readback); //从地址0读取数据
Serial.print("data1:");
Serial.println(readback.date1);//打印数据1
Serial.print("data2:");
Serial.println(readback.date2);
Serial.print("data3:");
Serial.println(readback.date3);//打印数据3
//------------结构体2读----------------
EEPROM.begin(256);//申请空间
config_jiuai jiuai1;//申请变量
EEPROM_read(129, jiuai1);//读数据
Serial.print("jiuai:");
Serial.println(jiuai1.jiuai);//打印数据
Serial.println("read eeprom over!");
}
void setup() {
Serial.begin(9600);//波特率9600和115200均可
eeprom_test();//读和写
}
void loop() {
//欢迎关注 订阅,学习开发板即将发布!
}
学习2种赋值方法:strcpy() 和 sprintf()
更多学习实践,全部实践后的总结。更多精彩敬请关注!!有惊喜哦