当前位置: 首页 > news >正文

ESP32的系统存储

1. ESP32 中的分区表(Partition Table)

作用:
将 Flash 划分为多个区域,便于管理程序和数据。
支持多种类型的分区:app(程序)、data(数据)、自定义类型等。

分区名类型  子类型大小    说明
nvs        datanvs0x6000非易失存储
phy_initdataphy0x1000PHY 初始化数据(通常不用)
factoryappfactory1M默认启动程序

 OTA 分区表(partitions_two_ota.csv):
 新增 ota data:记录当前 OTA 程序信息
 多个 app 分区:ota_0、ota_1 等,支持固件升级

 自定义分区:
 类型可自定义(0x40–0xFE)
 使用 esp_partition_find_first()获取分区指针
 使用 esp_partition_write/read() 进行读写

操作自定义分区的 API 示例

#include "esp_partition.h"#define USER_PARTITION_TYPE    0x40
#define USER_PARTITION_SUBTYPE 0x01const esp_partition_t *partition = esp_partition_find_first(USER_PARTITION_TYPE, USER_PARTITION_SUBTYPE, NULL);// 擦除
esp_partition_erase_range(partition, 0, 4096);// 写入
esp_partition_write(partition, 0, "hello", 5);// 读取
char buf[1024];
esp_partition_read(partition, 0, buf, 5);

2. ESP32 中的 NVS(Non-Volatile Storage)

概念:
 键值对存储,掉电不丢失
 支持命名空间(namespace)隔离不同模块的键名

 常用 API:

nvs_open()        // 打开命名空间
nvs_set_str()     // 写入字符串
nvs_get_str()     // 读取字符串
nvs_set_blob()    // 写入二进制数据
nvs_get_blob()    // 读取二进制数据
nvs_commit()      // 提交写入
nvs_close()       // 关闭句柄

使用流程:
1. 初始化 nvs_flash_init()
2. 打开命名空间 nvs_open()
3. 读写数据
4. 提交并关闭

完整使用流程示例

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "nvs_flash.h"
#include <string.h>
#include "esp_log.h"#define NAME_SPACE_WIFI1 "wifi1"
#define NAME_SPACE_WIFI2 "wifi2"#define NVS_SSID_KEY     "ssid"
#define NVS_PASSWORD_KEY "password"// 修正后的读取函数
esp_err_t nvs_blob_read(const char* namespace_name, const char* key, void* buffer, size_t maxlen)
{nvs_handle_t nvs_handle;esp_err_t err;// 打开命名空间err = nvs_open(namespace_name, NVS_READONLY, &nvs_handle);if (err != ESP_OK) {ESP_LOGE("NVS", "打开命名空间失败: %s", esp_err_to_name(err));return err;}// 第一步:获取数据长度size_t length = 0;err = nvs_get_blob(nvs_handle, key, NULL, &length);if (err != ESP_OK) {ESP_LOGE("NVS", "获取数据长度失败: %s", esp_err_to_name(err));nvs_close(nvs_handle);return err;}// 检查缓冲区是否足够if (length > 0 && length <= maxlen) {// 第二步:实际读取数据err = nvs_get_blob(nvs_handle, key, buffer, &length);if (err != ESP_OK) {ESP_LOGE("NVS", "读取数据失败: %s", esp_err_to_name(err));}} else {ESP_LOGE("NVS", "缓冲区太小或数据长度为0: 需要%d字节,但只有%d字节", length, maxlen);err = ESP_FAIL;}nvs_close(nvs_handle);return err;
}void app_main(void)
{nvs_handle_t nvs_handle1;esp_err_t ret;// 初始化 NVSret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_LOGI("NVS", "NVS 需要擦除重建");nvs_flash_erase();ESP_ERROR_CHECK(nvs_flash_init());} else if (ret != ESP_OK) {ESP_LOGE("NVS", "NVS 初始化失败: %s", esp_err_to_name(ret));return;}ESP_LOGI("NVS", "=== 开始写入 NVS 数据 ===");// 命名空间1 - 存储 WiFi 配置ret = nvs_open(NAME_SPACE_WIFI1, NVS_READWRITE, &nvs_handle1);if (ret == ESP_OK) {// 注意:使用 nvs_set_blob 时,长度应该包含字符串终止符nvs_set_blob(nvs_handle1, NVS_SSID_KEY, "wifi_esp32", strlen("wifi_esp32") + 1);nvs_set_blob(nvs_handle1, NVS_PASSWORD_KEY, "12345678", strlen("12345678") + 1);nvs_commit(nvs_handle1);nvs_close(nvs_handle1);ESP_LOGI("NVS", "命名空间 %s 写入完成", NAME_SPACE_WIFI1);}// 命名空间2 - 存储另一个 WiFi 配置ret = nvs_open(NAME_SPACE_WIFI2, NVS_READWRITE, &nvs_handle1);if (ret == ESP_OK) {// 修正:使用正确的字符串长度nvs_set_blob(nvs_handle1, NVS_SSID_KEY, "helloworld", strlen("helloworld") + 1);nvs_set_blob(nvs_handle1, NVS_PASSWORD_KEY, "87654321", strlen("87654321") + 1);nvs_commit(nvs_handle1);nvs_close(nvs_handle1);ESP_LOGI("NVS", "命名空间 %s 写入完成", NAME_SPACE_WIFI2);}vTaskDelay(pdMS_TO_TICKS(1000));ESP_LOGI("NVS", "=== 开始读取 NVS 数据 ===");// 读取并打印所有配置char read_buffer[64];// 读取命名空间1的SSIDmemset(read_buffer, 0, sizeof(read_buffer));if (nvs_blob_read(NAME_SPACE_WIFI1, NVS_SSID_KEY, read_buffer, sizeof(read_buffer)) == ESP_OK) {ESP_LOGI("NVS", "namespace:%s, key:%s -> value:%s", NAME_SPACE_WIFI1, NVS_SSID_KEY, read_buffer);}// 读取命名空间1的密码memset(read_buffer, 0, sizeof(read_buffer));if (nvs_blob_read(NAME_SPACE_WIFI1, NVS_PASSWORD_KEY, read_buffer, sizeof(read_buffer)) == ESP_OK) {ESP_LOGI("NVS", "namespace:%s, key:%s -> value:%s", NAME_SPACE_WIFI1, NVS_PASSWORD_KEY, read_buffer);}// 读取命名空间2的SSIDmemset(read_buffer, 0, sizeof(read_buffer));if (nvs_blob_read(NAME_SPACE_WIFI2, NVS_SSID_KEY, read_buffer, sizeof(read_buffer)) == ESP_OK) {ESP_LOGI("NVS", "namespace:%s, key:%s -> value:%s", NAME_SPACE_WIFI2, NVS_SSID_KEY, read_buffer);}// 读取命名空间2的密码memset(read_buffer, 0, sizeof(read_buffer));if (nvs_blob_read(NAME_SPACE_WIFI2, NVS_PASSWORD_KEY, read_buffer, sizeof(read_buffer)) == ESP_OK) {ESP_LOGI("NVS", "namespace:%s, key:%s -> value:%s", NAME_SPACE_WIFI2, NVS_PASSWORD_KEY, read_buffer);}ESP_LOGI("NVS", "=== 演示完成 ===");
}

3. VFS 与 SPIFFS 文件系统

 VFS(虚拟文件系统):
 提供统一接口,屏蔽底层文件系统差异
 通过 esp_vfs_register() 注册驱动
 支持多个挂载点,路径最长匹配

SPIFFS(SPI Flash File系统):
 轻量级文件系统,适用于 SPI NOR Flash
 不支持目录,路径为扁平结构
 使用前需在分区表中定义data, spiffs类型分区使用流程:

// 配置并挂载
esp_vfs_spiffs_conf_t conf = {.base_path = "/spiffs",.partition_label = NULL,.max_files = 5,.format_if_mount_failed = true
};
esp_vfs_spiffs_register(&conf);// 使用标准 C 文件操作
FILE* f = fopen("/spiffs/hello.txt", "w");
fprintf(f, "Hello World!");
fclose(f);// 卸载
esp_vfs_spiffs_unregister(conf.partition_label);

🧩 总结对比:

存储方式适用场景特点
分区表程序分区、OTA、自定义数据硬件划分,直接读写
NVS配置信息、键值对数据轻量、命名空间隔离
SPIFFS文件存储(如网页、日志)支持文件操作,挂载到 VFS

思维导图如下,仅供参考

http://www.dtcms.com/a/485815.html

相关文章:

  • HTML应用指南:利用GET请求获取全国领克经销商门店位置信息
  • 零基础OSS组件(Java)
  • 中国亚健康产业:多元创新下的健康新生态
  • 从物联网到工业控制:48元明远智睿2351核心板的多场景适配之路
  • MedHELM评估医疗大模型:设计理念、技术细节与应用影响
  • 江协科技STM32课程笔记(三)—定时器TIM(输出比较)
  • 网站建设可行性分析报告模板支付宝小程序搭建
  • 精通网站开发书籍做游戏网站赚钱么
  • Linux 网络分析终极武器:Tcpdump 深度指南!
  • 制造业流程自动化提升生产力的全面分析
  • 主流的 MCU 开发语言为什么是 C 而不是 C++?
  • 3-AI-应用开发
  • 知识图谱增强的AI记忆觉醒革命:从Anthropic Claude 4.5看智能体的未来演进
  • Spring Boot 3零基础教程,yml配置文件,笔记13
  • 三步对接gpt-5-pro!地表强AI模型实测
  • [AI学习:SPIN -win-安装SPIN-工具过程 SPIN win 电脑安装=accoda 环境-第二篇:解决报错]
  • h5美食制作网站模板下载电子商务网站前台业务系统主要是
  • uniapp 提取 安卓平台软件包名称 公钥 证书MD5指纹
  • Redis 事务机制:Pipeline、ACID、Lua脚本
  • 【实时Linux实战系列】在实时系统中安全地处理浮点运算
  • 基于仿真和运行时监控的自动驾驶安全分析
  • Java-Spring入门指南(二十七)Android Studio 第一个项目搭建与手机页面模拟器运行
  • Highcharts 绘制之道(2):高级绘图技术与连通关系
  • 学习笔记——GPU训练
  • 数据结构——二叉搜索树Binary Search Tree(介绍、Java实现增删查改、中序遍历等)
  • 网站个人主页怎么做wordpress 网银支付
  • 网站建设常州青之峰陕西西安网站设计公司
  • FTP 抓包分析实战,命令、被动主动模式要点、FTPS 与 SFTP 区别及真机取证流程
  • Linux下的权限与文件
  • 《算法闯关指南:优选算法--二分查找》--19.x的平方根,20.搜索插入位置