ESP32-NVS保存

ESP32-NVS保存

1. 简介

1.NVS是什么?

  • NVS = Non-Volatile Storage(非易失性储存)
  • 掉电不丢失,专门存键值对(key-value),比如配置,参数,计数,WIFI密码等
  • 比之间写Flash安全,简单。
  • 支持类型:intstringblob(二进制数据:结构体,数组)

2. 常用函数

1.必要添加的头文件

c 复制代码
#include "nvs_flash.h"
#include "nvs.h"

2.初始化NVS

整个程序只需要执行一次

必须在使用NVS前使用,通常放到app_main()最开头

c 复制代码
//初始化 NVS 闪存
esp_err_t err = nvs_flash_init();
if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
	//如果NVS分区满了/版本不匹配,先擦除再初始化
	ESP_ERROR_SHECK(nvs_flash_erase());
	err == nvs_flash_init();
}
ESP_ERROR_CHECK(err); //检测是否初始化成功

3.打开NVS句柄

在读写数据前必须先打开一个NVS命名空间(namespace)

c 复制代码
nvs_open(const char* namespace_name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle)

参数

  • namespace_name:命名空间,名字顺便起。
  • open_mode :打开方式,
    • NVS_READWRITE:读写
    • NVS_READONLY:只读
  • out_handle:句柄

例如

c 复制代码
nvs_hanle_t my_handle;

//打开命名空间"storage",读写模式
err = nvs_open("storage",NVS_READWRITE,&my_handle);
if(err != ESP_OK){
	printf("打开NVS失败!(%s)\n",esp_err_to_name(err));
	return ;
}

4.写入数据

1.整型数据

将值写入到键中,并保存在MVS里面

c 复制代码
esp_err_t nvs_set_x(nvs_handle_t handle, const x* key, int8_t value);
  • nvs_set_x:中的x为值的数据类型,如:i8,u8,str,blob等
  • handle: 句柄
  • key :键
  • value:值

int8_t

c 复制代码
esp_err_t nvs_set_i8 (nvs_handle_t handle, const char* key, int8_t value);

uint8_t

c 复制代码
esp_err_t nvs_set_u8 (nvs_handle_t handle, const char* key, int8_t value);

int16_t

c 复制代码
esp_err_t nvs_set_i16 (nvs_handle_t handle, const char* key, int8_t value);

uint16_t

c 复制代码
esp_err_t nvs_set_u16 (nvs_handle_t handle, const char* key, int8_t value);

int32_t

c 复制代码
esp_err_t nvs_set_i32 (nvs_handle_t handle, const char* key, int8_t value);

uint32_t

c 复制代码
esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, int8_t value);

int64_t

c 复制代码
esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int8_t value);

uint64_t

c 复制代码
esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, int8_t value);

例子

c 复制代码
static void nvs_save_dat(const char *dat, const u8 num)
{
    nvs_handle_t nvs_handle;
    // 参数 :地址空间  打开方式 句柄
    nvs_open("dat_cfg", NVS_READWRITE, &nvs_handle); //打开句柄
    //参数 :句柄 键 值
    nvs_set_u8(nvs_handle, "dat", num); //填入数据
    nvs_commit(nvs_handle); //提交数据
    nvs_close(nvs_handle); //关闭句柄
}

2.字符串数据

c 复制代码
esp_err_t nvs_set_str (nvs_handle_t handle, const char* key, const char* value);

例子

c 复制代码
static void nvs_save_wifi(const char *ssid, const char *pwd)
{
    nvs_handle_t nvs_handle;
    nvs_open("wifi_cfg", NVS_READWRITE, &nvs_handle);
    nvs_set_str(nvs_handle, "ssid", ssid);
    nvs_set_str(nvs_handle, "pwd", pwd);
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
}

3. 二进制数据

包括:结构体,数组

c 复制代码
esp_err_t nvs_set_blob(nvs_handle_t handle, const char* key, const void* value, size_t length);

例子

c 复制代码
// 定义一个结构体
typedef struct {
    int temperature;
    float humidity;
} config_t;

config_t cfg = {25, 60.5};

// 写入 blob(二进制对象)
err = nvs_set_blob(my_handle, "config", &cfg, sizeof(config_t));
ESP_ERROR_CHECK(err);

5.提交数据

使用NVS_SET_x()函数写入数据后,需要使用nvs_commit()进行提交,不然数据没法真正保存。

c 复制代码
esp_err_t nvs_commit(nvs_handle_t handle);

参数

  • handle :句柄

例子

c 复制代码
static void nvs_save_wifi(const char *ssid, const char *pwd)
{
    nvs_handle_t nvs_handle;
    nvs_open("wifi_cfg", NVS_READWRITE, &nvs_handle);  //打开句柄
    nvs_set_str(nvs_handle, "ssid", ssid);  //写入数据
    nvs_set_str(nvs_handle, "pwd", pwd);
    nvs_commit(nvs_handle); //提交数据
    nvs_close(nvs_handle); //关闭句柄
}

6.获取数据

从键中获取对应的值

1.获取整型数据

与写入数据对应将set``改为get`即可。

c 复制代码
esp_err_t nvs_get_i8 (nvs_handle_t handle, const char* key, int8_t* out_value);

参数

  • handle :句柄
  • key : 键
  • out_value: 值(参数是指针类型的,要使用地址进行接收)

2.获取字符串数据

c 复制代码
esp_err_t nvs_get_str (nvs_handle_t handle, const char* key, char* out_value, size_t* length);

参数:

  • handle:句柄
  • key: 键
  • out_value·:值
  • length:要获取字符串的长度
    例如
c 复制代码
static void nvs_read_wifi(void)
{
    nvs_handle_t nvs_handle;
    if(nvs_open("wifi_cfg", NVS_READONLY, &nvs_handle) == ESP_OK){
        size_t len = sizeof(g_sta_ssid);
        nvs_get_str(nvs_handle, "ssid", g_sta_ssid, &len);
        len = sizeof(g_sta_pass);
        nvs_get_str(nvs_handle, "pwd", g_sta_pass, &len);
        nvs_close(nvs_handle);
    }
}

3.获取二进制数据

c 复制代码
esp_err_t nvs_get_blob(nvs_handle_t handle, const char* key, void* out_value, size_t* length);

参数:

  • handle:句柄
  • key: 键
  • out_value·:值
  • length:要获取字符串的长度

7.删除

1.删除键

从内存在将该键进行删除。(包括对应的值)

c 复制代码
esp_err_t nvs_erase_key(nvs_handle_t handle, const char* key);

2.删除命名空间里所有的键

c 复制代码
esp_err_t nvs_erase_all(nvs_handle_t handle);

8.关闭句柄

c 复制代码
void nvs_close(nvs_handle_t handle);

3.wifi储存例子

c 复制代码
char g_sta_ssid[32] = {0}; //要连接的wifi名称
char g_sta_pass[64] = {0}; //保存家里WIFI密码

//==================== NVS 存储 ====================
//读取闪存分区里的WIFI账号和密码
static void nvs_read_wifi(void)
{
    nvs_handle_t nvs_handle;
    if(nvs_open("wifi_cfg", NVS_READONLY, &nvs_handle) == ESP_OK){
        size_t len = sizeof(g_sta_ssid);
        nvs_get_str(nvs_handle, "ssid", g_sta_ssid, &len);
        len = sizeof(g_sta_pass);
        nvs_get_str(nvs_handle, "pwd", g_sta_pass, &len);
        nvs_close(nvs_handle);
    }
}
//把WIFI名称和密码写进闪存分区里
static void nvs_save_wifi(const char *ssid, const char *pwd)
{
    nvs_handle_t nvs_handle;
    nvs_open("wifi_cfg", NVS_READWRITE, &nvs_handle);
    nvs_set_str(nvs_handle, "ssid", ssid);
    nvs_set_str(nvs_handle, "pwd", pwd);
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
}
//清除闪存里面的WIFI数据
static void nvs_clear_wifi(void)
{
    nvs_handle_t nvs_handle;
    nvs_open("wifi_cfg", NVS_READWRITE, &nvs_handle);
    nvs_erase_all(nvs_handle);
    nvs_commit(nvs_handle);
    nvs_close(nvs_handle);
    ESP_LOGI(TAG, "✅ 已重置配网,重启生效");
    esp_restart();
}

void app_main()
{
	esp_err_t err = nvs_flash_init();
	if(err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
		//如果NVS分区满了/版本不匹配,先擦除再初始化
		ESP_ERROR_SHECK(nvs_flash_erase());
		err == nvs_flash_init();
	}
	ESP_ERROR_CHECK(err); //检测是否初始化成功
	
  nvs_read_wifi(); //读取是否存有WIFI信息
  if(strlen(g_sta_ssid) > 0) {  //直接连接
     start_sta_wifi(g_sta_ssid, g_sta_pass);
  } else {    //配网
     start_ap_web_server();
  }

}
相关推荐
FreakStudio10 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘16 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
zd84510150016 天前
RS485 总线详解
单片机·嵌入式硬件
✎ ﹏梦醒͜ღ҉繁华落℘16 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展16 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司16 天前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设
踏着七彩祥云的小丑16 天前
嵌入式测试学习第 37 天:异常场景测试:断电、拔插、干扰、非法指令
单片机·嵌入式硬件·学习
意法半导体STM3216 天前
【官方原创】如何为STM32CubeMX2配置Visual Studio Code配置方案
vscode·stm32·单片机·嵌入式硬件·策略模式·stm32cubemx·嵌入式开发
雾削木16 天前
B语言经典教程现代化重构
java·前端·stm32·单片机·嵌入式硬件
Hello-FPGA16 天前
Camera Link 与 CoaXPress 技术对比 如何选择你的相机接口
单片机·嵌入式硬件