ESP32 NVS 非易失性存储

简介

非易失性存储 (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

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的示例代码,演示如何在ESP32 IDF中使用非易失性存储(NVS)来存储和读取数据。 首先,需要在头文件中包含NVS库: ``` #include "nvs_flash.h" ``` 在主函数中,需要初始化NVS库: ``` // 初始化NVS esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); ``` 然后,可以使用以下代码块来读取和写入NVS中的数据: ``` // 打开NVS命名空间 nvs_handle_t my_handle; esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle); if (err != ESP_OK) { printf("Error opening NVS handle!\n"); } else { // 读取数据 int32_t my_value; err = nvs_get_i32(my_handle, "my_value", &my_value); switch (err) { case ESP_OK: printf("my_value = %d\n", my_value); break; case ESP_ERR_NVS_NOT_FOUND: printf("The value is not initialized yet!\n"); break; default : printf("Error reading value!\n"); } // 写入数据 my_value++; err = nvs_set_i32(my_handle, "my_value", my_value); printf((err != ESP_OK) ? "Failed!\n" : "Done\n"); // 关闭NVS命名空间 nvs_close(my_handle); } ``` 完整的代码示例如下: ``` #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "nvs_flash.h" void app_main() { // 初始化NVS esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK(err); // 打开NVS命名空间 nvs_handle_t my_handle; err = nvs_open("storage", NVS_READWRITE, &my_handle); if (err != ESP_OK) { printf("Error opening NVS handle!\n"); } else { // 读取数据 int32_t my_value; err = nvs_get_i32(my_handle, "my_value", &my_value); switch (err) { case ESP_OK: printf("my_value = %d\n", my_value); break; case ESP_ERR_NVS_NOT_FOUND: printf("The value is not initialized yet!\n"); break; default : printf("Error reading value!\n"); } // 写入数据 my_value++; err = nvs_set_i32(my_handle, "my_value", my_value); printf((err != ESP_OK) ? "Failed!\n" : "Done\n"); // 关闭NVS命名空间 nvs_close(my_handle); } } ``` 注意,这只是一个简单的示例代码,可以根据需要进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值