ESP32 没有物理 EEPROM ,Arduino 核心通过Flash 模拟 EEPROM 实现数据掉电保存,使用官方自带的EEPROM.h库即可,无需额外安装。
方式一:Preferences 库(⭐ 推荐)
官方推荐,基于 NVS,更稳定、不易磨损。
cpp
#include <Preferences.h>
Preferences preferences;
void setup() {
Serial.begin(115200);
// 打开命名空间(类似分区)
preferences.begin("my-app", false); // false = 读写模式
// === 写入数据 ===
preferences.putInt("counter", 42);
preferences.putFloat("voltage", 3.3);
preferences.putString("ssid", "MyWiFi");
preferences.putBool("flag", true);
// === 读取数据 ===
int counter = preferences.getInt("counter", 0); // 默认值 0
float voltage = preferences.getFloat("voltage", 0.0);
String ssid = preferences.getString("ssid", "");
bool flag = preferences.getBool("flag", false);
Serial.printf("counter=%d, voltage=%.2f, ssid=%s, flag=%d\n",
counter, voltage, ssid.c_str(), flag);
preferences.end();
}
void loop() {}
注意事项
- EEPROM 写入有寿命限制(约 10 万次/扇区),频繁写入用 Preferences
EEPROM.commit()忘了调 = 数据没存上,这是最常见的坑- Preferences 适合存配置,EEPROM 适合兼容老 Arduino 代码
核心知识点
- 模拟 EEPROM 大小最大4096 字节(推荐使用 512 字节足够日常存储)
- 必须先
EEPROM.begin(大小)初始化 - 写入后必须
EEPROM.commit()才会真正保存到 Flash - 支持存储:int、float、String、结构体等任意数据
完整示例代码(通用版)
包含基础读写 、字符串读写 、浮点数读写,直接复制可用
cpp
#include <EEPROM.h>
// 定义模拟EEPROM大小(单位:字节),最大4096
#define EEPROM_SIZE 512
// 存储地址定义(每个地址存1字节,不同数据要错开地址,避免覆盖)
#define ADDR_INT 0 // int类型地址
#define ADDR_FLOAT 4 // float类型地址(int占4字节,所以从4开始)
#define ADDR_STR 8 // 字符串地址
void setup() {
Serial.begin(115200);
// 1. 初始化EEPROM
EEPROM.begin(EEPROM_SIZE);
Serial.println("EEPROM初始化完成");
// ============== 写入数据(只需要执行一次,注释掉后重启仍能读取) ==============
writeInt(ADDR_INT, 12345); // 写入int
writeFloat(ADDR_FLOAT, 3.14159); // 写入float
writeString(ADDR_STR, "ESP32 EEPROM"); // 写入字符串
EEPROM.commit(); // 关键:提交保存!
Serial.println("数据写入完成");
// ============== 读取数据 ==============
int readInt = readInt(ADDR_INT);
float readFloat = readFloat(ADDR_FLOAT);
String readStr = readString(ADDR_STR);
Serial.print("读取到int:");
Serial.println(readInt);
Serial.print("读取到float:");
Serial.println(readFloat);
Serial.print("读取到字符串:");
Serial.println(readStr);
}
void loop() {
// 主循环无需操作
}
// ------------------- 工具函数:任意类型读写 -------------------
// 写入int(4字节)
void writeInt(int address, int value) {
EEPROM.write(address, value & 0xFF);
EEPROM.write(address + 1, (value >> 8) & 0xFF);
EEPROM.write(address + 2, (value >> 16) & 0xFF);
EEPROM.write(address + 3, (value >> 24) & 0xFF);
}
// 读取int
int readInt(int address) {
int value = 0;
value |= EEPROM.read(address);
value |= EEPROM.read(address + 1) << 8;
value |= EEPROM.read(address + 2) << 16;
value |= EEPROM.read(address + 3) << 24;
return value;
}
// 写入float(4字节)
void writeFloat(int address, float value) {
byte* p = (byte*)&value;
for (int i = 0; i < 4; i++) {
EEPROM.write(address + i, *(p + i));
}
}
// 读取float
float readFloat(int address) {
float value = 0;
byte* p = (byte*)&value;
for (int i = 0; i < 4; i++) {
*(p + i) = EEPROM.read(address + i);
}
return value;
}
// 写入字符串(最大32字节,可修改)
void writeString(int address, String str) {
int len = str.length();
for (int i = 0; i < len; i++) {
EEPROM.write(address + i, str[i]);
}
// 写入结束符
EEPROM.write(address + len, '\0');
}
// 读取字符串
String readString(int address) {
String str = "";
char ch;
int i = 0;
// 读取到结束符为止
while ((ch = EEPROM.read(address + i)) != '\0' && i < 32) {
str += ch;
i++;
}
return str;
}
极简版代码(只读写单字节)
适合存储开关状态、数字 0-255
cpp
#include <EEPROM.h>
#define EEPROM_SIZE 512
#define ADDR 0
void setup() {
Serial.begin(115200);
EEPROM.begin(EEPROM_SIZE);
// 写入(0-255)
EEPROM.write(ADDR, 100);
EEPROM.commit(); // 必须提交
// 读取
byte val = EEPROM.read(ADDR);
Serial.print("读取值:");
Serial.println(val);
}
void loop() {}
重要使用规则
-
地址不能重叠
- int/float 占 4 字节
- char/byte 占 1 字节
- 字符串根据长度分配
-
必须 commit
EEPROM.write()只是写入缓存- 必须调用
EEPROM.commit()才会保存到 Flash
-
Flash 寿命
- 模拟 EEPROM 擦写寿命约 10 万次
- 不要在
loop()里频繁写入
-
清空 EEPROM
cpp
// 清空所有数据(写入0)
void clearEEPROM() {
for (int i = 0; i < EEPROM_SIZE; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
}
总结
- ESP32 用 Flash 模拟 EEPROM,库文件
EEPROM.h - 流程:
begin()→write()→commit()→read() - 支持 int/float/String/ 结构体存储
- 地址规划好,避免数据覆盖,commit 是保存关键