一、简介
非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。
NVS适合存储一些小数据,如果对象占用空间比较大,使用负载均衡的FAT文件系统。
如果NVS分区被截断,比如更改分区表布局的时候,应该擦除分区内容。可以使用 idf.py erase_flash 命令擦除flash上全部的内容。
NVS 的操作对象为键值对,其中键是 ASCII 字符串,当前支持最大键长为 15 个字符,值可以为以下几种类型:
整数型: uint8_t、int8_t、uint16_t、int16_t、uint32_t、int32_t、uint64_t 和 int64_t;
字符型: 以 结尾的字符串;
二进制数据: 可变长度的二进制数据 (BLOB)。
ESP-IDF 编程指南——非易失性存储库
二、API说明
以下 NVS 接口位于 nvs_flash/include/nvs_flash.h。
2.1 nvs_flash_init

2.2 nvs_flash_erase

2.3 nvs_open

2.4 读取函数
esp_err_t nvs_get_i8 (nvs_handle_t handle, const char* key, int8_t* out_value);
esp_err_t nvs_get_u8 (nvs_handle_t handle, const char* key, uint8_t* out_value);
esp_err_t nvs_get_i16 (nvs_handle_t handle, const char* key, int16_t* out_value);
esp_err_t nvs_get_u16 (nvs_handle_t handle, const char* key, uint16_t* out_value);
esp_err_t nvs_get_i32 (nvs_handle_t handle, const char* key, int32_t* out_value);
esp_err_t nvs_get_u32 (nvs_handle_t handle, const char* key, uint32_t* out_value);
esp_err_t nvs_get_i64 (nvs_handle_t handle, const char* key, int64_t* out_value);
esp_err_t nvs_get_u64 (nvs_handle_t handle, const char* key, uint64_t* out_value);

//这两个的长度需要特殊操作
esp_err_t nvs_get_str (nvs_handle_t handle, const char* key, char* out_value, size_t* length);
esp_err_t nvs_get_blob(nvs_handle_t handle, const char* key, void* out_value, size_t* length);

2.5 写入函数
esp_err_t nvs_set_i8 (nvs_handle_t handle, const char* key, int8_t value);
esp_err_t nvs_set_u8 (nvs_handle_t handle, const char* key, uint8_t value);
esp_err_t nvs_set_i16 (nvs_handle_t handle, const char* key, int16_t value);
esp_err_t nvs_set_u16 (nvs_handle_t handle, const char* key, uint16_t value);
esp_err_t nvs_set_i32 (nvs_handle_t handle, const char* key, int32_t value);
esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, uint32_t value);
esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int64_t value);
esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, uint64_t value);
esp_err_t nvs_set_str (nvs_handle_t handle, const char* key, const char* value);

//用来存储大二进制数据的函数(比如说结构体)
esp_err_t nvs_set_blob(nvs_handle_t handle, const char* key, const void* value, size_t length);

2.6 nvs_commit

2.7 nvs_close

三、编程流程
1. 配置分区表
配置分区表: 我们也可以使用默认的分区表。默认分区表中nvs大小是24k(0x6000),可以根据自己需要对nvs空间进行修改。
2. 初始化NVS Flash
使用 nvs_flash_init(),如果 Flash 满了或者希望清空原来的数据,就使用 nvs_flash_erase() 清空。
3. 打开NVS,配置句柄
对NVS空间进行操作的时候,是使用句柄实现的。
同时,为了尽可能减少键值对的冲突,NVS引入了命名空间的概念,不同命名空间下的key捕获产生冲突。
同时也要在这里配置对NVS空间进行操作的权限,分为读和读写两种。
nvs_handle_t handle;nvs_open('namespace1', NVS_READWRITE, &handle);
4. 读写操作
按照不同的数据类型,对数据进行get和set操作
调用中使用nvs_get_*,nvs_set_*和nvs_commit()功能函数。
5. 关闭NVS
nvs_close(handle);
四、应用实例
4.1 单变量读写
使用 esp-idfexamplesstoragenvs_rw_value 中的例程
#include // Initialize NVS esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { // NVS partition was truncated and needs to be erased // Retry nvs_flash_init ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK( err ); // Open printf('n'); printf('Opening Non-Volatile Storage (NVS) handle... '); nvs_handle_t my_handle; err = nvs_open('storage', NVS_READWRITE, &my_handle); if (err != ESP_OK) { printf('Error (%s) opening NVS handle!n', esp_err_to_name(err)); } else { printf('Donen'); // Read printf('Reading restart counter from NVS ... '); int32_t restart_counter = 0; // value will default to 0, if not set yet in NVS err = nvs_get_i32(my_handle, 'restart_counter', &restart_counter); switch (err) { case ESP_OK: printf('Donen'); printf('Restart counter = %dn', restart_counter); break; case ESP_ERR_NVS_NOT_FOUND: printf('The value is not initialized yet!n'); break; default : printf('Error (%s) reading!n', esp_err_to_name(err)); } // Write printf('Updating restart counter in NVS ... '); restart_counter++; err = nvs_set_i32(my_handle, 'restart_counter', restart_counter); printf((err != ESP_OK) ? 'Failed!n' : 'Donen'); // Commit written value. // After setting any values, nvs_commit() must be called to ensure changes are written // to flash storage. Implementations may write to storage at other times, // but this is not guaranteed. printf('Committing updates in NVS ... '); err = nvs_commit(my_handle); printf((err != ESP_OK) ? 'Failed!n' : 'Donen'); // Close nvs_close(my_handle); } printf('n'); // Restart module for (int i = 10; i >= 0; i--) { printf('Restarting in %d seconds...n', i); vTaskDelay(1000 / portTICK_PERIOD_MS); } printf('Restarting now.n'); fflush(stdout); esp_restart();} 查看打印: 4.2 字符串及数组读写 初始化后 #include 'nvs_flash.h'void main(void){ ... ESP_ERROR_CHECK(nvs_flash_init()); ...} 写入 void NvsWriteDataToFlash(void){ nvs_handle handle; // 写入一个整形数据,一个字符串,WIFI信息以及版本信息 static const char *NVS_CUSTOMER = 'customer data'; static const char *DATA2 = 'String'; static const char *DATA3 = 'blob_wifi'; static const char *DATA4 = 'blob_version'; // 要写入的字符串 char str_for_store[32] = 'i am a string.'; // 要写入的WIFI信息 wifi_config_t wifi_config_to_store = { .sta = { .ssid = 'store_ssid:hello_kitty', .password = 'store_password:1234567890', }, }; // 要写入的版本号 uint8_t version_for_store[4] = {0x01, 0x01, 0x01, 0x00}; printf('set size:%urn', sizeof(wifi_config_to_store)); ESP_ERROR_CHECK( nvs_open( NVS_CUSTOMER, NVS_READWRITE, &handle) ); ESP_ERROR_CHECK( nvs_set_str( handle, DATA2, str_for_store) ); ESP_ERROR_CHECK( nvs_set_blob( handle, DATA3, &wifi_config_to_store, sizeof(wifi_config_to_store)) ); ESP_ERROR_CHECK( nvs_set_blob( handle, DATA4, version_for_store, 4) ); ESP_ERROR_CHECK( nvs_commit(handle) ); nvs_close(handle);} 读出 void NvsReadDataFromFlash(void){ esp_err_t err; nvs_handle handle; static const char *NVS_CUSTOMER = 'customer data'; static const char *DATA2 = 'String'; static const char *DATA3 = 'blob_wifi'; static const char *DATA4 = 'blob_version'; uint32_t str_length = 32; char str_data[32] = {0}; wifi_config_t wifi_config_stored; uint8_t version[4] = {0}; uint32_t version_len = 4; memset(&wifi_config_stored, 0x0, sizeof(wifi_config_stored)); uint32_t wifi_len = sizeof(wifi_config_stored); ESP_ERROR_CHECK( nvs_open(NVS_CUSTOMER, NVS_READWRITE, &handle) ); ESP_ERROR_CHECK ( nvs_get_str(handle, DATA2, str_data, &str_length) ); ESP_ERROR_CHECK ( nvs_get_blob(handle, DATA3, &wifi_config_stored, &wifi_len) ); ESP_ERROR_CHECK ( nvs_get_blob(handle, DATA4, version, &version_len) ); printf('[data1]: %s len:%urn', str_data, str_length); printf('[data2]: %drn', value); printf('[data3]: ssid:%s passwd:%srn', wifi_config_stored.sta.ssid, wifi_config_stored.sta.password); nvs_close(handle);}

上一篇:ESP32学习笔记(24)——OTA(空中升级)接口使用(原生API)
下一篇:ESP32学习笔记(22)——ADC接口使用
推荐阅读最新更新时间:2026-03-19 23:44
- LTC2945IUD-1 在 -48V 系统中使用低侧检测进行电源监控的典型应用
- 用于 24V 汽车应用的 LTC4367IDD 过压电源保护控制器的典型应用
- LTC2635-HZ12 四通道、12 位数模转换器的典型应用
- 使用 ROHM Semiconductor 的 BU4821 的参考设计
- 使用 Analog Devices 的 AD9625 的参考设计
- LT1307CS8 高压反激式转换器的典型应用电路
- AD7858L 3V 至 5V 单电源、200ksps、8 通道、12 位采样 ADC 的典型应用
- AND8337/D、1.2V、1.5V DC 至 DC 单路输出电源参考设计
- DER-713 - 使用 InnoSwitch3-EP PowiGaN 和 MinE-CAP 的 65 W 高功率密度适配器
- LDK120C11R 1.1V低压降稳压器典型应用(可调版)电路

【Follow me第三季第3期】代码
【Follow me第三季第3期】XIAO ESP32S3任务代码提交
Follow me第三季第3期源代码
现代雷达系统的信号设计
MCP6C02T-050H/Q8B
BFR340T






京公网安备 11010802033920号