通俗来说,NVS 就是在 flash 上分配的一块内存空间 ,提供给用户保存掉电不丢失的数据。

  • 非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。
  • NVS适合存储一些小数据,如果对象占用空间比较大,使用负载均衡的FAT文件系统。
  • 如果NVS分区被截断,比如更改分区表布局的时候,应该擦除分区内容。可以使用 idf.py erase_flash 命令擦除flash上全部的内容。

参考文章:http://t.csdn.cn/JkIFk

对照着官方的例程和API进行编写程序。

官方例程如下:

/* Non-Volatile Storage (NVS) Read and Write a Blob - ExampleFor other examples please check:https://github.com/espressif/esp-idf/tree/master/examplesThis example code is in the Public Domain (or CC0 licensed, at your option.)Unless required by applicable law or agreed to in writing, thissoftware is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES ORCONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "driver/gpio.h"#define STORAGE_NAMESPACE "storage"#if CONFIG_IDF_TARGET_ESP32C3
#define BOOT_MODE_PIN GPIO_NUM_9
#else
#define BOOT_MODE_PIN GPIO_NUM_0
#endif //CONFIG_IDF_TARGET_ESP32C3/* Save the number of module restarts in NVSby first reading and then incrementingthe number that has been saved previously.Return an error if anything goes wrongduring this process.*/
esp_err_t save_restart_counter(void)
{nvs_handle_t my_handle;esp_err_t err;// Openerr = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);if (err != ESP_OK) return err;// Readint32_t restart_counter = 0; // value will default to 0, if not set yet in NVSerr = nvs_get_i32(my_handle, "restart_conter", &restart_counter);if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;// Writerestart_counter++;err = nvs_set_i32(my_handle, "restart_conter", restart_counter);if (err != ESP_OK) return err;// Commit written value.// After setting any values, nvs_commit() must be called to ensure changes are written// to flash storage. Implementations may write to storage at other times,// but this is not guaranteed.err = nvs_commit(my_handle);if (err != ESP_OK) return err;// Closenvs_close(my_handle);return ESP_OK;
}/* Save new run time value in NVSby first reading a table of previously saved valuesand then adding the new value at the end of the table.Return an error if anything goes wrongduring this process.*/
esp_err_t save_run_time(void)
{nvs_handle_t my_handle;esp_err_t err;// Openerr = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);if (err != ESP_OK) return err;// Read the size of memory space required for blobsize_t required_size = 0;  // value will default to 0, if not set yet in NVSerr = nvs_get_blob(my_handle, "run_time", NULL, &required_size);if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;// Read previously saved blob if availableuint32_t* run_time = malloc(required_size + sizeof(uint32_t));if (required_size > 0) {err = nvs_get_blob(my_handle, "run_time", run_time, &required_size);if (err != ESP_OK) {free(run_time);return err;}}// Write value including previously saved blob if availablerequired_size += sizeof(uint32_t);run_time[required_size / sizeof(uint32_t) - 1] = xTaskGetTickCount() * portTICK_PERIOD_MS;err = nvs_set_blob(my_handle, "run_time", run_time, required_size);free(run_time);if (err != ESP_OK) return err;// Commiterr = nvs_commit(my_handle);if (err != ESP_OK) return err;// Closenvs_close(my_handle);return ESP_OK;
}/* Read from NVS and print restart counterand the table with run times.Return an error if anything goes wrongduring this process.*/
esp_err_t print_what_saved(void)
{nvs_handle_t my_handle;esp_err_t err;// Openerr = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);if (err != ESP_OK) return err;// Read restart counterint32_t restart_counter = 0; // value will default to 0, if not set yet in NVSerr = nvs_get_i32(my_handle, "restart_conter", &restart_counter);if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;printf("Restart counter = %d\n", restart_counter);// Read run time blobsize_t required_size = 0;  // value will default to 0, if not set yet in NVS// obtain required memory space to store blob being read from NVSerr = nvs_get_blob(my_handle, "run_time", NULL, &required_size);if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;printf("Run time:\n");if (required_size == 0) {printf("Nothing saved yet!\n");} else {uint32_t* run_time = malloc(required_size);err = nvs_get_blob(my_handle, "run_time", run_time, &required_size);if (err != ESP_OK) {free(run_time);return err;}for (int i = 0; i < required_size / sizeof(uint32_t); i++) {printf("%d: %d\n", i + 1, run_time[i]);}free(run_time);}// Closenvs_close(my_handle);return ESP_OK;
}void app_main(void)
{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_initESP_ERROR_CHECK(nvs_flash_erase());err = nvs_flash_init();}ESP_ERROR_CHECK( err );err = print_what_saved();if (err != ESP_OK) printf("Error (%s) reading data from NVS!\n", esp_err_to_name(err));err = save_restart_counter();if (err != ESP_OK) printf("Error (%s) saving restart counter to NVS!\n", esp_err_to_name(err));gpio_reset_pin(BOOT_MODE_PIN);gpio_set_direction(BOOT_MODE_PIN, GPIO_MODE_INPUT);/* Read the status of GPIO0. If GPIO0 is LOW for longer than 1000 ms,then save module's run time and restart it*/while (1) {if (gpio_get_level(BOOT_MODE_PIN) == 0) {vTaskDelay(1000 / portTICK_PERIOD_MS);if(gpio_get_level(BOOT_MODE_PIN) == 0) {err = save_run_time();if (err != ESP_OK) printf("Error (%s) saving run time blob to NVS!\n", esp_err_to_name(err));printf("Restarting...\n");fflush(stdout);esp_restart();}}vTaskDelay(200 / portTICK_PERIOD_MS);}
}

大概就分为几个步骤,初始化,打开,写入,读取,关闭

我们接下来也按照这个步骤进行编写就可以。

首先,我们在头文件里定义一个结构体,用来设置要保存的wifi信息。

#define MAX_SETTING_SSID_LEN 32//最大限制
#define MAX_SETTING_PSW_LEN  64//同上typedef struct
{char setting_ssid[MAX_SETTING_SSID_LEN];//WiFi名uint8_t setting_ssid_len;char setting_psw[MAX_SETTING_PSW_LEN];//密码uint8_t setting_psw_len;}SYSSTERM_DATA_T;

然后就可以写相关程序了,基本上都是参照例程进行删改,不难的。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"#include "ds_nvs_da.h"
#include "ds_system_data_da.h"static const char *TAG = "ds_nvs";NVS_WIFI_INFO_E wifi_config_flag = NVS_WIFI_INFO_NULL;//保存信息
void ds_nvs_save_wifi_info(void){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 ;}wifi_config_flag = NVS_WIFI_INFO_SAVE;ESP_ERROR_CHECK(nvs_set_u8(nvs_handle, "wifi_flag", wifi_config_flag));ESP_ERROR_CHECK(nvs_set_str(nvs_handle, "ssid", get_systerm_data().setting_ssid));ESP_ERROR_CHECK(nvs_set_str(nvs_handle, "psw",  get_systerm_data().setting_psw));ESP_ERROR_CHECK(nvs_commit(nvs_handle));nvs_close(nvs_handle);
}//读取
NVS_WIFI_INFO_E ds_nvs_read_wifi_info(void){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));wifi_config_flag = wifi_config;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));ESP_ERROR_CHECK(nvs_get_str(nvs_handle,"psw",psw,&psw_len));set_systerm_data_wifi_info(ssid,ssid_len,psw,psw_len);print_systerm_data_wifi_info();}else{ESP_LOGI(TAG,"wifi config info null");}nvs_close(nvs_handle);return wifi_config_flag;
}
void ds_nvs_init(void){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_initESP_ERROR_CHECK(nvs_flash_erase());err = nvs_flash_init();}ESP_ERROR_CHECK( err );}

特别注意的是这里还有一个ds_systerm_data_da.h头文件,这里 是为了处理数据方便写的,可以不写,但还是最好写一下。

#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_log.h"#include "ds_system_data_da.h"static const char *TAG = "ds_system_data";SYSSTERM_DATA_T g_system_data; //定义要数据结构//初始化数据
void ds_systerm_data_init(void){memset(&g_system_data,0,sizeof(SYSSTERM_DATA_T));//将所有的内容替换为0
}//获取数据,返回量为SYSTERM_DATA_T结构体
SYSSTERM_DATA_T get_systerm_data(void){return g_system_data;
}//设置数据
void set_systerm_data_wifi_info(char *p_ssid,uint8_t p_ssidlen,char * p_psw,uint8_t p_pswlen){if(p_pswlen >= MAX_SETTING_PSW_LEN || p_ssidlen >=MAX_SETTING_SSID_LEN)//判断长度是否在范围内{ESP_LOGE(TAG,"MAX_SETTING_SSID_PSW_LEN ERROR!");}g_system_data.setting_psw_len = p_pswlen;g_system_data.setting_ssid_len = p_ssidlen;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_systerm_data_wifi_info(void){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");}//检查是否已经有wifi的信息传进来
SETTING_DATA_E check_systerm_data_wifi_info(void){if(g_system_data.setting_ssid_len != 0){return SETTING_DATA_HAS_WIFI_INFO;}return SETTING_DATA_INIT;
}

然后在主程序里面测试,这里是基于上次文件系统改的。

在上次的基础上,增加了这些,主要就是设置wifi的信息进行测试。

然后上开发板进行测试。

可以看到,已经成功打印出我们所设置的wifi信息。

成功!

ESP32用NVS存储wifi信息相关推荐

  1. ESP32 通过NVS存储WiFi账号和密码至Flash

    前言 项目需求:在ESP32板子重启之后,自动从Flash中寻找已经存储好的WiFi账号和秘密,连接到网络. 要想能够很好的理解如何将WiFi的账号和密码如何写入到Flash的什么地方,首先需要了解下 ...

  2. 【中移芯昇】2. eeprom存储wifi信息

    1 前言 本章介绍下使用芯昇的eeprom保存wifi账户和密码. 测试功能块:I2C 2 硬件 如图,eeprom使用的是PC0和PC1. 3 打开示例 File – New – Project – ...

  3. ESP32开发--使用NVS存储数据

    ESP32基础系列 ESP32初体验之环境搭建 ESP32外设学习之GPIO ESP32外设学习之UART ESP32开发之给模块连上网络 ESP32的一键配网与Airkiss配网 ESP32使用NV ...

  4. 【MicroPython ESP32】手动配网和wifi信息保存示例

    [MicroPython ESP32]手动配网和wifi信息保存示例 本示例基于Thonny平台开发. 入网演示 配网机制 ESP32 Micropython运行后,首先从目录下读取json配置文件信 ...

  5. ESP32学习入门:WiFi连接网络

    目录 一.ESP32简单介绍 二.ESP32 Wi-Fi模块介绍 三.ESP32 Wi-Fi 编程模型 四.ESP32 Wi-Fi 事件处理流程 五.ESP32 Wi-Fi开发环境 六.ESP32 W ...

  6. Arduino ESP32 flash数据存储结构

    Arduino ESP32 flash数据存储结构 分区表官方文档:<分区表> 想了解ESP32 flash数据存储结构需要从分区表开始了解.一点类似一台电脑上挂载的硬盘一样. 分区表保存 ...

  7. Arduino ESP32 对NVS数据操作测试

    Arduino ESP32 对NVS数据操作测试 对NVS数据操作,所需加载的头文件Preferences.h. 对命名空间初始化函数begin()操作测试一 bool begin(const cha ...

  8. esp32与android蓝牙,ESP32通过蓝牙配置WIFI

    ESP32通过蓝牙配置WIFI [复制链接] 以下内容通过软件自动翻译,源文为:https://robotzero.one/esp32-wi-fi-connection-bluetooth/ 使用蓝牙 ...

  9. SimpleFOC之ESP32(九)—— WIFI、UDP和TCP

    目录 说明 一.网络通信 1.1.准备工作 1.2.UDP通信 1.3.TCP通信 二.硬件准备 三.代码参考 四.代码演示 4.1.WIFI_AP模式UDP通信 4.2.WIFI_STA模式TCP ...

最新文章

  1. 2022版中国液压、气压动力机械及元件制造行业建设现状与投资动向研究报告
  2. [leetcode] 874. 行走机器人模拟(周赛)
  3. java 获取当前方法的名称_Java中获取当前函数名
  4. html与css结合动效案例,写CSS动效的常用套路(附demo的效果实现与源码)
  5. Part01、sqlalchemy 使用
  6. iBatis下使用like查询,以及需要注意的问题
  7. 用户登录问题python_Python Flask单点登录问题
  8. 这一年,我“生病”了
  9. Total Control的深入用法,如何使用脚本实现启动或重启指定App
  10. Linux——MySQL-MMM
  11. 吉林大学软件学院黄庆道《最优化算法》对偶单纯形使用大M法条件
  12. 【Unity】跨场景音乐资源不间断播放(可控音量)
  13. 手机注册服务器异常是什么问题,ohho注册不了网络异常
  14. python对淘宝运营有帮助吗_优秀的淘宝运营需要具备哪些能力
  15. 自然语言处理中的Character Embedding技术
  16. 侍魂胧月传说显示服务器满了,侍魂胧月传说满级之后做什么 满级每日必做任务详解[多图]...
  17. JupyterNotebook使用
  18. matlab中矩阵取值的方法
  19. mfp 服务器控制中心,固网1008MFP驱动
  20. php对于给定的正整数k,删数

热门文章

  1. 信创,即信息技术应用创新,是贯穿2020年整个IT行业的主题主线
  2. 计算机德语,计算机办公软件中常见德语词汇
  3. 音视频进阶教程|如何实现游戏中的实时语音
  4. 深度解析:外贸高手报价时的原则和技巧
  5. 联发科 MTK8735 方案
  6. Unity ugui——toggle多选小坑
  7. html背景颜色中药制剂,中药制剂
  8. 社区团购小程序需要服务器吗,为什么说社区团购小程序和团购电商模式结合很有必要!...
  9. Cocos2dx 程序用 VS2012编译安卓和WPhone
  10. 【STM32】射频RFIDRC522