ESP32-NVS保存
- [1. 简介](#1. 简介)
- [2. 常用函数](#2. 常用函数)
- 3.wifi储存例子
1. 简介
1.NVS是什么?
NVS= Non-Volatile Storage(非易失性储存)- 掉电不丢失,专门存键值对(key-value),比如配置,参数,计数,WIFI密码等
- 比之间写Flash安全,简单。
- 支持类型:
int、string,blob(二进制数据:结构体,数组)
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();
}
}