> 文章列表 > 【ESP-IDF】介绍NVS

【ESP-IDF】介绍NVS

【ESP-IDF】介绍NVS

ESP-IDF是一款由乐鑫科技(Espressif Systems)开发的面向ESP32和ESP32-S系列芯片的开发框架,NVS(Non-Volatile Storage)是其中的一项功能。

NVS是一种用于在嵌入式系统中保存持久化数据的键值存储库。在ESP-IDF中,NVS提供了一种简单且有效的方法来在ESP32芯片上保存和读取配置信息、状态数据、用户设置等应用程序数据,以便在设备重新启动或断电后能够恢复状态。

NVS在ESP-IDF中具有以下特点和优点:

  1. 非易失性:NVS中的数据在芯片断电或重新启动后仍然保持不变,不会丢失,适合保存需要长期存储的数据。
  2. 键值对存储:NVS使用简单的键值对(Key-Value)结构来保存数据,方便进行读取和写入操作。
  3. 分区管理:NVS将数据存储在不同的分区中,可以根据需要创建多个独立的NVS分区,用于不同的数据类型或应用场景,实现数据隔离和管理。
  4. API丰富:ESP-IDF提供了丰富的NVS API,包括读取、写入、删除、遍历等操作,方便开发者进行数据的处理和管理。

学习和使用ESP-IDF中的NVS可以带来以下好处:

  1. 持久化数据存储:NVS允许开发者将配置信息、状态数据等持久化保存在芯片中,即使设备断电或重新启动,数据也能够得到保留,从而避免了数据丢失的情况。
  2. 简单高效的数据管理:NVS提供了简单易用的API,可以方便地进行数据的读取、写入、删除等操作,减少了开发复杂性和提高了代码效率。
  3. 数据隔离和管理:NVS支持多个分区的管理,可以将不同类型的数据存储在不同的分区中,实现数据隔离和管理,便于维护和升级。
  4. 节省存储空间:NVS采用了紧凑的键值对结构,可以高效地利用芯片内部的存储空间,避免了使用外部存储器的成本和复杂性。

因此,学习和使用ESP-IDF中的NVS可以帮助开发者在ESP32和ESP32-S系列芯片上实现持久化数据存储,并简化数据管理和提高应用程序的稳定性和效率。

如何使用NVS

简单来说,我们可以把nvs比喻成一个“U盘”,那接下来我们就开始对这个“U盘”进行操作吧!

接下来我们做一个简单的演示,代码如下:

#include <stdio.h>
#include "nvs_flash.h"
void app_main(void)
{// 对“U盘”进行初始化nvs_flash_init();char *bilibili_name_space = "BiliBili";nvs_handle_t bilibili_handle;// 创建一个句柄来打卡它nvs_open(bilibili_name_space, NVS_READWRITE, &bilibili_handle);// 创建初始变量counter_val记录ESP32重启次数uint32_t counter_val = 0;// 创建初始变量counter_val的key,可以将其比喻成文件名char *counter_key = "counter";// 查看是否存在counter_val(因为我们的counter_val是uint32_t类型,所以下面我们要用nvs_get_u32())nvs_get_u32(bilibili_handle, counter_key, &counter_val);counter_val = counter_val + 1;// 设置counter_valnvs_set_u32(bilibili_handle, counter_key, counter_val);// 提交执行nvs_commit(bilibili_handle);// 关闭窗口(句柄)nvs_close(bilibili_handle);// 退出“U盘”nvs_flash_deinit();
}

对于上述代码,我们可以这样形象的理解

当我执行nvs_flash_init()的时候,相当于插入了“U盘”

【ESP-IDF】介绍NVS

当我执行nvs_open(bilibili_name_space , NVS_READWRITE, &bilibili_handle)时,相当于新建bilibili_name_space文件夹,并进入其中,其中这个文件夹是NVS_READWRITE即可读可写的,而bilibili_handle就相当于这个窗口,我接下来所有的操作都需要通过这个窗口(句柄)进行操作

【ESP-IDF】介绍NVS

【ESP-IDF】介绍NVS

当我运行nvs_get_u32(bilibili_handle, counter_key, &counter_val)时,其实就是相当于打开名字为:counter_key的文件,而文件内的值就是counter_val

nvs_set_u32(bilibili_handle, counter_key, counter_val)就是设置文件里的内容

【ESP-IDF】介绍NVS

nvs_commit(bilibili_handle),就是提交执行,nvs_close(bilibili_handle)就是关闭窗口(句柄),nvs_flash_deinit()就是退出“U盘”。

优化代码后:

#include <stdio.h>
#include "esp_log.h"
#include "nvs_flash.h"
void app_main(void)
{// 对“U盘”进行初始化nvs_flash_init();char *bilibili_name_space = "BiliBili";nvs_handle_t bilibili_handle;// 创建一个句柄来打卡它nvs_open(bilibili_name_space, NVS_READWRITE, &bilibili_handle);// 创建初始变量counter_val记录ESP32重启次数uint32_t counter_val = 0;// 创建初始变量counter_val的key,可以将其比喻成文件名char *counter_key = "counter";// 查看是否存在counter_val(因为我们的counter_val是uint32_t类型,所以下面我们要用nvs_get_u32())nvs_get_u32(bilibili_handle, counter_key, &counter_val);ESP_LOGI("NVS", "KEY:VALUE %s:%lu", counter_key, counter_val);// 设置counter_valnvs_set_u32(bilibili_handle, counter_key, ++counter_val);// 提交执行nvs_commit(bilibili_handle);// 关闭窗口(句柄)nvs_close(bilibili_handle);// 退出“U盘”nvs_flash_deinit();
}

接下来我们来测试一下这段代码:
可以看到,第1次为1,第2次为2,但是按理来说,第一次应该为0,第二次才是1,这是由于ESP-IDF太快了,在打印之前它就重启了一遍,所以才会被记录成1。

【ESP-IDF】介绍NVS

【ESP-IDF】介绍NVS

这里我们可以通过给几秒的延时来避免这种情况发生,如下:

【ESP-IDF】介绍NVS

这里我们重点注意一下这行代码:

nvs_set_u32(bilibili_handle, counter_key, ++counter_val);

在这里++counter_val 是用于对 counter_val 变量进行自增操作。++ 运算符是 C 语言中的自增运算符,用于将变量的值加一,并返回加一后的结果。

在这段代码中,++counter_val 表示先将 counter_val 的值加一,然后将加一后的值作为参数传递给 nvs_set_u32() 函数。这样可以确保在将 counter_val 的值写入 NVS 存储之前,先对其进行自增操作,从而实现每次写入 NVS 存储时计数器的值增加一的效果。

需要注意的是,自增运算符有前缀形式和后缀形式,即 ++counter_valcounter_val++。前缀形式的 ++counter_val 先对变量进行自增操作,然后返回自增后的值;而后缀形式的 counter_val++ 先返回变量的值,然后再对变量进行自增操作。在这里使用前缀形式的 ++counter_val 是因为需要将自增后的值传递给 nvs_set_u32() 函数,而不是传递自增前的值。

如何把NVS删掉

直接把ESP格式化就好了

  1. 打开ESP-IDF Terminal

【ESP-IDF】介绍NVS

![\\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zKZ3JaD7-1681699998245)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/bb6652b7-0236-42c9-941b-4684efac74b0/Untitled.png)\\]](https://img-blog.csdnimg.cn/09ca893cfdc045e789c03a51e555a72a.png)
  1. 输入idf.py erase-flash
    【ESP-IDF】介绍NVS