简介
非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。
本章节采用NVS存储WIFI的账户和密码信息。
本章涉及核心知识点:NVS掉电不丢失存储系统。
ESP-IDF版本:V5.1.2
源码
小智学长的源码:Docs
程序实现
NVS实现的核心步骤:
1.nvs_flash_init() NVS初始化
2.nvs_open(const char* namespace_name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle) 打开NVS存储区,创建文件夹,文件夹的名字为namespace_name指针所指向的名字,并赋予其打开模式,以及传递给句柄
3.设置数据或者获取数据,例nvs_get_u32或nvs_set_u32,该函数需要根据具体的参数类型进行匹配设定
4.递交 nvs_commit(nvs_handle_t c_handle) 句柄为创建时的句柄,该步骤确保之前设定的数据提交到nvs中
5.关闭nvs_close(nvs_handle_t handle) 句柄为创建时的句柄
6.销毁(若需要)
首先,创建全局枚举变量,用于反馈NVS状态是错误、空或存储。
创建nvs存储函数、nvs读取函数、以及nvs初始化函数。
static const char *TAG = "ds_nvs";
typedef enum{
NVS_WIFI_INFO_ERROR =0,
NVS_WIFI_INFO_NULL,
NVS_WIFI_INFO_SAVE,
}NVS_WIFI_INFO_E;
NVS_WIFI_INFO_E wifi_config_flag = NVS_WIFI_INFO_NULL; //创建全局枚举变量wifi_config
void ds_nvs_save_wifi_info(){
esp_err_t err;
nvs_handle_t nvs_handle;
err = nvs_open("wificonfig", NVS_READWRITE, &nvs_handle); //打开wificondig存储区,可读可写,成功返回到nvs_handle句柄
if (err != ESP_OK) {
ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return ;
}
wifi_config_flag = NVS_WIFI_INFO_SAVE;
ESP_ERROR_CHECK(nvs_set_u8(nvs_handle, "wifi_flag", wifi_config_flag)); //设置wifi标志
ESP_ERROR_CHECK(nvs_set_str(nvs_handle, "ssid", get_system_data().setting_ssid)); //设置wifi账号
ESP_ERROR_CHECK(nvs_set_str(nvs_handle, "psw", get_system_data().setting_psw)); //设置wifi密码
ESP_ERROR_CHECK(nvs_commit(nvs_handle)); //确保将更改的数据写入nvs中
nvs_close(nvs_handle); //关闭句柄
}
NVS_WIFI_INFO_E ds_nvs_read_wifi_info(){
esp_err_t err;
nvs_handle_t nvs_handle;
err = nvs_open("wificonfig", NVS_READWRITE, &nvs_handle);
if (err != ESP_OK) {
ESP_LOGI(TAG,"Error (%s) opening NVS handle!\n", esp_err_to_name(err));
return NVS_WIFI_INFO_ERROR;
}
uint8_t wifi_config = 0;
ESP_ERROR_CHECK(nvs_get_u8(nvs_handle, "wifi_flag", &wifi_config)); //nvs_handle句柄,wifi_config键值,读取数据存储到wifi_config变量中
wifi_config_flag = wifi_config; //将局部变量wifi_config的值传递给全局变量wifi_config_flag
if(wifi_config_flag == NVS_WIFI_INFO_SAVE){
ESP_LOGI(TAG,"has wifi config info");
char ssid[32];
char psw[64];
size_t ssid_len = sizeof(ssid);
size_t psw_len = sizeof(psw);
ESP_ERROR_CHECK(nvs_get_str(nvs_handle, "ssid", ssid, &ssid_len)); //指定nvs_handle句柄,key值,存储地址,长度
ESP_ERROR_CHECK(nvs_get_str(nvs_handle, "psw", psw, &psw_len));
set_system_data_wifi_info(ssid,ssid_len,psw,psw_len);
print_system_data_wifi_info();
}else{
ESP_LOGI(TAG,"wifi config info null");
}
nvs_close(nvs_handle);
return wifi_config_flag;
}
void ds_nvs_init(){
// Initialize NVS
esp_err_t err = nvs_flash_init();
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// NVS partition was truncated and needs to be erased
// Retry nvs_flash_init
ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );
}
#include <string.h>
#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_log.h"
#include "print_wifi_data.h"
static const char *TAG = "ds_system_data";
SYSTRM_DATA_T g_system_data;
void ds_system_data_init(){
memset(&g_system_data,0,sizeof(SYSTRM_DATA_T));
}
//创建该函数是为了让其能在其他文件调用该结构体
SYSTRM_DATA_T get_system_data(){
return g_system_data;
}
//保存数据到g_system_data结构体中
void set_system_data_wifi_info(char * p_ssid,uint8_t p_ssidlen,char *p_psw ,uint8_t p_pswlen){
if(p_pswlen >= MAX_SETTING_SSID_LEN || p_ssidlen >= MAX_SETTING_PSW_LEN){
ESP_LOGE(TAG, "MAX_SETTING_SSID_PWD_LEN ERROR");
}
g_system_data.setting_ssid_len = p_ssidlen;
g_system_data.setting_psw_len = p_pswlen;
memcpy(g_system_data.setting_ssid,p_ssid,p_ssidlen);
memcpy(g_system_data.setting_psw,p_psw,p_pswlen);
g_system_data.setting_ssid[p_ssidlen] = '\0';
g_system_data.setting_psw[p_pswlen] = '\0';
}
void print_system_data_wifi_info(){
printf("\r\nwifi_ssid:");
for(int i = 0;i<g_system_data.setting_ssid_len;i++){
printf("%c",g_system_data.setting_ssid[i]);
}
printf("\r\nwifi_password:");
for(int i = 0;i<g_system_data.setting_psw_len;i++){
printf("%c",g_system_data.setting_psw[i]);
}
printf("\r\n");
}
SETTING_DATA_E check_system_data_wifi_info(){
if(g_system_data.setting_ssid_len != 0){
return SETTING_DATA_HAS_WIFI_INFO;
}
return SETTING_DATA_INIT;
}
学习资源
此处推荐孤独的二进制NVS的学习,很不错!
ESP32 存储篇 NVS 非易失性存储库 - 乐鑫 ESP32 物联网开发框架 ESP-IDF 开发入门 - 孤独的二进制出品_哔哩哔哩_bilibili