一、简介

非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。

NVS适合存储一些小数据,如果对象占用空间比较大,使用负载均衡的FAT文件系统。

如果NVS分区被截断,比如更改分区表布局的时候,应该擦除分区内容。可以使用 idf.py erase_flash 命令擦除flash上全部的内容。

NVS 的操作对象为键值对,其中键是 ASCII 字符串,当前支持最大键长为 15 个字符,值可以为以下几种类型:

  • 整数型: uint8_tint8_tuint16_tint16_tuint32_tint32_tuint64_tint64_t
  • 字符型:\0 结尾的字符串;
  • 二进制数据: 可变长度的二进制数据 (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-idf\examples\storage\nvs_rw_value 中的例程

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"void app_main(void)
{// Initialize NVSesp_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_initESP_ERROR_CHECK(nvs_flash_erase());err = nvs_flash_init();}ESP_ERROR_CHECK( err );// Openprintf("\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("Done\n");// Readprintf("Reading restart counter from NVS ... ");int32_t restart_counter = 0; // value will default to 0, if not set yet in NVSerr = nvs_get_i32(my_handle, "restart_counter", &restart_counter);switch (err) {case ESP_OK:printf("Done\n");printf("Restart counter = %d\n", 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));}// Writeprintf("Updating restart counter in NVS ... ");restart_counter++;err = nvs_set_i32(my_handle, "restart_counter", restart_counter);printf((err != ESP_OK) ? "Failed!\n" : "Done\n");// 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" : "Done\n");// Closenvs_close(my_handle);}printf("\n");// Restart modulefor (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:%u\r\n", 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:%u\r\n", str_data, str_length);printf("[data2]: %d\r\n", value);printf("[data3]: ssid:%s passwd:%s\r\n", wifi_config_stored.sta.ssid, wifi_config_stored.sta.password);nvs_close(handle);
}

• 由 Leung 写于 2021 年 6 月 8 日

• 参考:【ESP32-IDF】04-2 存储-NVS
    ESP32 学习日志(5)——NVS
    ESP32_学习笔记(一)NVS的操作(存储和读取大数组)(为什么存入数据成功,读取却为零的原因)

ESP32学习笔记(23)——NVS(非易失性存储)接口使用相关推荐

  1. ESP32学习笔记(7)——SmartConfig接口使用(ESP-Touch和AirKiss)

    一.概述 SmartConfig是TI开发的一种配置技术,用于将新的Wi-Fi设备连接到Wi-Fi网络.它使用移动应用程序将网络凭据从智能手机或平板电脑广播到未配置的Wi-Fi设备. 该技术的优点是设 ...

  2. ESP32学习笔记(50)——ESP-WIFI-MESH接口使用

    一.ESP-WIFI-MESH简介 1.1 概述 ESP-WIFI-MESH是建立在Wi-Fi协议之上的网络协议.ESP-WIFI-MESH允许分布在大范围物理区域内(室内和室外)的许多设备(以下称为 ...

  3. 【Computer Organization笔记23】非易失性存储:磁表面存储设备,磁盘的访问过程,RAID技术

    本次笔记内容: P45 计算机组成原理(45) P46 计算机组成原理(46) 我的计组笔记汇总:计算机组原理成笔记 视频地址:计算机组成原理 清华大学刘卫东 全58讲 国家精品课程 1080P 更完 ...

  4. ESP32学习笔记(22)——ADC接口使用

    一.概述 ESP32 集成了 2 个 12 位逐次逼近模数转换器 (SARADC),支持 18 个测量通道(模拟使能引脚). 支持以下通道: ADC1: 8通道:GPIO32 - GPIO39 ADC ...

  5. ESP32学习笔记(5)——WiFi接口使用(STA和AP模式)

    一.概述 Wi-Fi 库支持配置及监控 ESP32 Wi-Fi 连网功能. 支持配置: 基站模式(即 STA 模式或 Wi-Fi 客户端模式),此时 ESP32 连接到接入点 (AP). AP 模式( ...

  6. ESP32学习笔记(45)——DAC接口使用

    一.概述 ESP32 有两个 8 位 DAC(数模转换器) 通道,分别连接 GPIO25(通道 1) 和 GPIO26(通道 2). DAC 驱动器允许将这些通道设置为任意电压. ESP-IDF 编程 ...

  7. ESP32学习笔记(41)——SNTP接口使用

    一.SNTP简介 简单网络时间协议(Simple Network Time Protocol),由 NTP 改编而来,主要用来同步因特网中的计算机时钟. SNTP 协议是用来同步本地的时间到 unix ...

  8. ESP32学习笔记(20)——SPI(从机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

  9. ESP32学习笔记(19)——SPI(主机)接口使用

    一.SPI简介 SPI(Serial Peripheral Interface) 协议是由摩托罗拉公司提出的通讯协议,即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在 ADC.LCD ...

最新文章

  1. 是否保证Python列表的元素保持按插入顺序排列?
  2. python入门指南bl-入门 第一个python可视化程序 基于pyqt5
  3. 第十篇 Form表单
  4. SQL Server开发人员应聘常见问题妙解
  5. apache_php_tomcat基于主机名的多虚拟主机整合笔记
  6. 做科研没人带,发不了文章怎么办?
  7. LDAP 中 CN, OU, DC 的含义
  8. 搭建Redis服务器
  9. 计算机系统维护是学什么,《计算机系统维护》教学大纲.doc
  10. Python语法入门
  11. [转] 虚拟机VMware3种网络模式(桥接、nat、Host-only)的工作原理
  12. python查看数据大小_python 监控文件大小
  13. cvThreshold() 阈值化
  14. opencv3中camshift详解(二)camshift原理介绍
  15. 西门子dcs系统组态手册下载_PLC/DCS/HMI 知识普及
  16. 密封橡胶圈尺寸缺陷视觉检测系统
  17. 信息系统集成监理费收取标准_信息工程监理取费参考标准.doc
  18. 武昌职业学院与湖北美和易思教育科技有限公司校企签约揭牌仪式隆重举行
  19. RS法计算Hurst指数
  20. CF909B Segments

热门文章

  1. 初识Python必看基础知识~ 续(3)
  2. 有生之年转ta系列 2.6 伽马校正
  3. BB8700 bowser net
  4. 西电捷通TISec解决方案保障配电网通信安全
  5. 绘画新手怎么把人物骨骼画好
  6. 小程序华为手机canvas不显示问题
  7. 数开头的成语有哪些_一至十数字开头的成语有哪些?
  8. MT4自定义指标导入方法
  9. 2020-09-05:虚拟内存知道么?什么时候使用虚拟内存?虚拟内存除了扩大内存还有什么用?
  10. Windows 域之 组、OU