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();
  }

}
相关推荐
Hall_IC4 小时前
意法半导体STM32F103RCT6分销商
stm32·单片机·嵌入式硬件
世微 如初5 小时前
基于AP5160的大功率LED恒流驱动设计:原理分析与外围计算
驱动开发·单片机·芯片
老李的森林6 小时前
嵌入式开发--STM32用DMA+IDLE中断方式串口接收不定长数据--之2
stm32·单片机·嵌入式硬件·串口·dma·idle中断
三易串口屏6 小时前
实验2 实时显示单片机的参数(整数、小数、中文 自定义协议方式)
单片机·物联网·mongodb·自动化·串口屏·医疗器械·工控设备
高速上的乌龟8 小时前
Lattice LFCPNX-100 HSB+Fpga开发详解: MAC+PCS以太网SFP光口传输
单片机·嵌入式硬件·fpga开发
易水寒陈8 小时前
单片机的hardfault打印信息定位错误
单片机
振浩微433射频芯片8 小时前
告别“遥控失灵”:如何评估国产433芯片在智能家居领域的可靠性?
网络·单片机·嵌入式硬件·物联网·智能家居
互联科技报8 小时前
极海APM32F427高性能MCU赋能中高端PLC,筑牢工业自动化控制核心
单片机·嵌入式硬件·自动化
0南城逆流09 小时前
【网站分享】常用网站分享三:STM32常用模块链接
stm32·单片机·嵌入式硬件