1.NVS是什么以及作用是什么?
NVS总的来说,就是非易失性存储,类似MCU EEPROM 表和键值相对应,表为句柄。利用句柄找对应的key值
NVS用于在flash 中存储字符串,将字符串转换成数值存储,比如ESP要存储wifi的名字和密码,以及每次上电连上上一次的WIFI,以及改变WIFI后保存相关信息。
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
void setup() {
//01 初始化nvs flash
esp_err_t err = nvs_flash_init(); // 初始化 NVS 分区
//02 如果nvs flash 满了就清空 如果失败可调用“nvs_flash_erase()”擦除NVS,然后再次初始化。
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase()); // 擦除 nvs 分区
err = nvs_flash_init();
}
ESP_ERROR_CHECK(err);
//03 打开nvs,配置句柄
printf("\n");
printf("Opening Non-Volatile Storage (NVS) handle... ");
nvs_handle my_handle; //配置 my_handle 名字的空间名 一个表
/* nvs_open
* 对表的属性进行赋属性,获取NVS空间的操作句柄
* 打开一个表
* 第一个形参为一个字符串,可称为表名。
* 第二个是读写模式,可选读写或者只读
* 第三个是当前打开的表的句柄
*/
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");
//04 读操作
printf("Reading restart counter from NVS ... ");
int32_t restart_counter = 0;
// 如果没有在nvs中设置,则值默认为0
/* nvs_get_i32
* 读取函数: 利用表去找对应的值
* 打开一个表
* 第一个是表的句柄
* 第二个是键值
* 第三个则是对应的变量的指针
*/
err = nvs_get_i32(my_handle, "restart_counter", &restart_counter); //读取函数
switch (err) {
case ESP_OK:
printf("Done\n");
printf("Restart counter = %ld\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));
}
//05 写操作
printf("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");
//06 提交修改
printf("Committing updates in NVS ... ");
err = nvs_commit(my_handle);
printf((err != ESP_OK) ? "Failed!\n" : "Done\n");
//07 关闭nvs
nvs_close(my_handle);
}
printf("\n");
// 定时重启模块
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();
}
void app_main()
{
printf("main");
setup();
}
NVS相关API使用方法如下:
(1)初始化
调用“nvs_flash_init();”,如果失败可调用“nvs_flash_erase()”擦除NVS,然后再次初始化。
(2)打开一个表
nvs_open("List", NVS_READWRITE, &my_handle);
这个API第一个形参为一个字符串,可称为表名。第二个是读写模式,可选读写或者只读,第三个是当前打开的表的句柄。
如此声明:“nvs_handle my_handle; ”。后面对表里面的键值进行读写,都需要输入键值所在表的句柄。
(3)读写
读:
vs_get_i8(my_handle, "nvs_i8", &nvs_i8);
读写不同的数据类型需要调用不同的API,类似的API有:“nvs_get_i16”,“nvs_get_u32”等等
形参方面,第一个是表的句柄,第二个是键值,第三个则是对应的变量的指针,如“nvs_i8”是个“int8_t”类型的变量。
写:
nvs_set_i8(my_handle, "nvs_i8", nvs_i8);
基本跟读差不多,注意的是第三个形参变成了对应的变量,而不是变量的指针。
(4)提交与关闭
提交:
nvs_commit(my_handle);
关闭:
nvs_close(my_handle);