共计 2335 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
在嵌入式开发中,参数持久化存储是一个基础但关键的需求。传统方案通常使用 EEPROM,但在 ESP32 开发中,这种方案存在明显不足:

- 有限的擦写次数 :典型 EEPROM 仅有 10 万次擦写寿命,频繁更新的参数会快速耗尽寿命
- 小容量限制 :ESP32 模拟 EEPROM 通常只有几百字节空间,难以存储复杂配置
- 管理不便 :需要手动处理地址分配,增加维护成本
- 缺乏结构 :只能存储原始字节,缺乏数据组织形式
技术选型
ESP32 支持两种主流文件系统解决方案:
SPIFFS 特点
- 专为 SPI NOR Flash 优化的轻量级文件系统
- 静态磨损均衡机制
- 最大支持 4MB 分区
- 已被证明的稳定性
LittleFS 优势
- 更现代的设计
- 动态磨损均衡
- 更好的目录支持
- 更快的挂载速度
推荐选择 :对于大多数参数存储场景,SPIFFS 已经足够。如果需要频繁写入或更大容量,建议使用 LittleFS。
核心实现
1. 文件系统初始化
#include "SPIFFS.h"
void setup() {Serial.begin(115200);
if(!SPIFFS.begin(true)) {Serial.println("SPIFFS 挂载失败");
return;
}
// 检查配置文件是否存在
if(!SPIFFS.exists("/config.json")) {createDefaultConfig();
}
}
2. 参数序列化设计
推荐使用 JSON 格式存储结构化参数:
{
"wifi_ssid": "MyNetwork",
"wifi_pwd": "password123",
"sensor_interval": 60,
"threshold": 25.5
}
3. 原子写入实现
为防止写入过程中断电导致数据损坏,采用临时文件 + 重命名策略:
void saveConfig(const char *jsonStr) {File tempFile = SPIFFS.open("/config.tmp", "w");
if(!tempFile) {Serial.println("临时文件创建失败");
return;
}
tempFile.print(jsonStr);
tempFile.close();
// 原子操作:重命名替换
if(SPIFFS.rename("/config.tmp", "/config.json")) {Serial.println("配置保存成功");
} else {Serial.println("重命名失败");
SPIFFS.remove("/config.tmp");
}
}
完整代码示例
#include <ArduinoJson.h>
#include "SPIFFS.h"
struct Config {char wifiSSID[32];
char wifiPWD[64];
int sensorInterval;
float threshold;
} config;
bool loadConfig() {File file = SPIFFS.open("/config.json", "r");
if(!file) return false;
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, file);
file.close();
if(error) {Serial.print("JSON 解析错误:");
Serial.println(error.c_str());
return false;
}
strlcpy(config.wifiSSID, doc["wifi_ssid"], sizeof(config.wifiSSID));
strlcpy(config.wifiPWD, doc["wifi_pwd"], sizeof(config.wifiPWD));
config.sensorInterval = doc["sensor_interval"];
config.threshold = doc["threshold"];
return true;
}
bool saveConfig() {DynamicJsonDocument doc(1024);
doc["wifi_ssid"] = config.wifiSSID;
doc["wifi_pwd"] = config.wifiPWD;
doc["sensor_interval"] = config.sensorInterval;
doc["threshold"] = config.threshold;
File tempFile = SPIFFS.open("/config.tmp", "w");
if(!tempFile) return false;
serializeJson(doc, tempFile);
tempFile.close();
if(!SPIFFS.rename("/config.tmp", "/config.json")) {SPIFFS.remove("/config.tmp");
return false;
}
return true;
}
性能优化
- 碎片化预防 :
- 避免频繁创建 / 删除文件
-
保持文件大小相对固定
-
内存管理 :
- 使用适当大小的 JSON 缓冲区
-
及时关闭文件句柄
-
读写速度 :
- 典型 4MB SPIFFS 写入速度约 100KB/s
- 读取速度可达 500KB/s
常见问题解决
文件系统挂载失败
- 检查分区表配置
- 尝试格式化:
SPIFFS.format() - 确认 Flash 模式设置正确
电源波动防护
- 使用 UPS 电容保证干净关机
- 实现写操作超时检测
- 添加校验和机制
线程安全
- 使用互斥锁保护文件操作
- 避免多任务同时写入
进阶扩展
考虑将本方案与 OTA 升级结合:
- 在 OTA 前备份配置
- 升级后自动恢复
- 实现配置版本兼容
通过文件系统存储参数,不仅解决了 EEPROM 的限制,还为未来功能扩展提供了坚实基础。
正文完
