目录

  • ESP32_学习笔记(一)NVS的操作
    • 前言
    • 函数介绍
      • 创建句柄:
      • 定义存储空间:
      • 打开函数:
      • 存储函数:
      • 读取函数:
      • 提交函数:
      • 关闭函数:
    • 易错点提醒:为什么明明存入了,读取的值为0
      • 这就是我们很多时候读取到的值为零的原因:
      • 解决方法:
    • 具体代码实操
      • 这是一个完整的代码,将其复制到主文件之中就可以运行
    • 参考文献:

ESP32_学习笔记(一)NVS的操作

前言

ESP32在RTOS3.0的环境下,拥有很多已经开发好的功能和组件供我们使用。NVS就是其中的一个。这么奇怪的名字其实就是我们原来的读写函数的抽象化,将原来的直接在地址上读写改为现在的通过系统来管理底层的存储,我们只需要像文件一样的写入和读出就行了,

函数介绍

创建句柄:

首先创建句柄用来操作。

nvs_handle_t nvs_handle;

定义存储空间:

存储空间是一个名字,用字符串表示:

#define STORAGE_NAMESPACE "storage"

打开函数:

esp_err_t nvs_open(const char* name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle);
我们要实现NVS的存储,我们首先就需要打开一个存储空间。以上这个函数就是用来打开的函数。

存储函数:

下面的都是用来存储数据的函数:

esp_err_t nvs_set_i8  (nvs_handle_t handle, const char* key, int8_t value);
esp_err_t nvs_set_u8  (nvs_handle_t handle, const char* key, uint8_t value);
esp_err_t nvs_set_i16 (nvs_handle_t handle, const char* key, int16_t value);
esp_err_t nvs_set_u16 (nvs_handle_t handle, const char* key, uint16_t value);
esp_err_t nvs_set_i32 (nvs_handle_t handle, const char* key, int32_t value);
esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, uint32_t value);
esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int64_t value);
esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, uint64_t value);
esp_err_t nvs_set_str (nvs_handle_t handle, const char* key, const char* value);
//用来存储大二进制数据的函数(比如说结构体)
esp_err_t nvs_set_blob(nvs_handle_t handle, const char* key, const void* value, size_t length);

读取函数:

esp_err_t nvs_get_i8  (nvs_handle_t handle, const char* key, int8_t* out_value);
esp_err_t nvs_get_u8  (nvs_handle_t handle, const char* key, uint8_t* out_value);
esp_err_t nvs_get_i16 (nvs_handle_t handle, const char* key, int16_t* out_value);
esp_err_t nvs_get_u16 (nvs_handle_t handle, const char* key, uint16_t* out_value);
esp_err_t nvs_get_i32 (nvs_handle_t handle, const char* key, int32_t* out_value);
esp_err_t nvs_get_u32 (nvs_handle_t handle, const char* key, uint32_t* out_value);
esp_err_t nvs_get_i64 (nvs_handle_t handle, const char* key, int64_t* out_value);
esp_err_t nvs_get_u64 (nvs_handle_t handle, const char* key, uint64_t* out_value);
//这两个的长度需要特殊操作
esp_err_t nvs_get_str (nvs_handle_t handle, const char* key, char* out_value, size_t* length);
esp_err_t nvs_get_blob(nvs_handle_t handle, const char* key, void* out_value, size_t* length);

提交函数:

这个函数用于我们每次写入NVS之后提交更改的。每次存入之后必须提交

esp_err_t nvs_commit(nvs_handle_t handle);

关闭函数:

void nvs_close(nvs_handle_t handle);

易错点提醒:为什么明明存入了,读取的值为0

我们要注意,传入的长度参数。
注意这几个函数:

esp_err_t nvs_get_str (nvs_handle_t handle, const char* key, char* out_value, size_t* length);
esp_err_t nvs_get_blob(nvs_handle_t handle, const char* key, void* out_value, size_t* length);
esp_err_t nvs_set_str (nvs_handle_t handle, const char* key, const char* value);
esp_err_t nvs_set_blob(nvs_handle_t handle, const char* key, const void* value, size_t length);

这几个函数都是对不定长的数据进行存储和读取,可以看到我们需要传入一个长度和一个key。那么在这个过程中我们并不知道要读取的数据长度究竟是多少,所以我们需要传入一个长度的指针进去。
我们可以看他的源码是怎么要求这一个数据的:

 /* @param[inout]  length     A non-zero pointer to the variable holding the length of out_value.*                           In case out_value a zero, will be set to the length*                           required to hold the value. In case out_value is not*                           zero, will be set to the actual length of the value*                           written. For nvs_get_str this includes zero terminator.*                         length指向变量out_value的长度的非零指针。如果out_value为零,则将其设置为保存该值所需的长度。如果out_value不为零,则将其设置为写入值的实际长度。 对于nvs_get_str,它包括零终止符。*/

这就是我们很多时候读取到的值为零的原因:

如果我们传入的值就是零的话,那么我们读取到的数据长度就是0:
官方文档解释:这里我们可以看到,如果读的到数据的话,这个长度指针的值会被设置为你传入的值,但是如果读不到数据既数据为零的情况了?

    // 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;}}

解决方法:

这里,我拿出官方的例程操作,我们可以看到,他开始为了读取所取得键得大小,传入空,获取到一个长度数据,然后再将这个长度数据来传入,从而获取所需要的值。
所以在这里我推荐,如果不知道这个实际的大小,大家都先采例程的方法,先读取长度,然后读取数据

具体代码实操

下面是一个用来存储和读取结构体的例子

//定义
//注意,我们可以定义多个存储空间来存储对应的值
#define STORAGE_NAMESPACE "storage"//结构体
struct Temp_st
{uint32_t temp_a;uint8_t * temp_str;char      temp_b;
}
//读取函数
/*
*读取函数
*para1:要读取的结构体指针。
*para2:长度*/
esp_err_t nvs_read_wifi(struct Temp_st *Temp_st, uint32_t *len)
{nvs_handle_t nvs_handle;esp_err_t err;//首先一部操作打开存储空间// Open//para(空间名字(字符串),操作类型(只读还是读写),操作句柄)err = nvs_open(STORAGE_NAMESPACE, NVS_READONLY, &nvs_handle);if (err != ESP_OK){printf("NVS_READ:存储空间打开失败\n");return err;}//注意这一步十分重要,因为在NVS存储已知长度类型的数据时,我们可以明确的传入已知的长度。
//但是这个地方对于我们传入的数组或者说结构体,我们不知道明确长度,于是我们采用下面的操作来获取要读取的数据的长度。// 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(nvs_handle, "Temp_st", NULL, &required_size);if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) return err;//再来读取对应的值err = nvs_get_blob(nvs_handle, "Temp_st", Temp_st, &required_size);if (err ==ESP_ERR_NVS_NOT_FOUND ){printfln("NVS_READ:key doesn’t exist");return err;}else if (err ==ESP_ERR_NVS_INVALID_HANDLE  ){printfln("NVS_READ:handle has been closed or is NULL");return err;}else if (err ==ESP_ERR_NVS_INVALID_NAME  ){printfln("NVS_READ:name doesn’t satisfy constraints ");return err;}else if (err ==ESP_ERR_NVS_INVALID_LENGTH  ){printfln("NVS_READ:length is not sufficient to store data");return err;}else{printfln("NVS_READ:读取成功");}//关闭句柄nvs_close(nvs_handle);return ESP_OK;
}

存储函数


/*
*存储函数
*para1:要读取的结构体指针。
*para2:长度*/
esp_err_t nvs_write_wifi(struct Temp_st *Temp_st, uint32_t len)
{nvs_handle_t nvs_handle;esp_err_t err;printfln("NVS_WRITE:存储wifi信息\n");// Openerr = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &nvs_handle);if (err != ESP_OK){printf("NVS_WRITE:存储空间打开失败\n");return err;}err = nvs_set_blob(nvs_handle, "Temp_st", Temp_st, len);if (err != ESP_OK){printf("NVS_WRITE:存储空间存储失败\n");return err;}err = nvs_commit(nvs_handle);if (err != ESP_OK){printf("NVS_WRITE:存储空间提交失败\n");return err;}err = nvs_close(nvs_handle);if (err != ESP_OK){printf("NVS_WRITE:存储空间关闭失败\n");return err;}return ESP_OK;
}

这是一个完整的代码,将其复制到主文件之中就可以运行

源代码

参考文献:

ESP32_学习笔记(一)NVS的操作(存储和读取大数组)(为什么存入数据成功,读取却为零的原因)相关推荐

  1. C# 学习笔记(17)操作SQL Server 上

    C# 学习笔记(17)操作SQL Server上 安装SQL Server 微软官网 https://www.microsoft.com/zh-cn/sql-server/sql-server-dow ...

  2. C# 学习笔记(19)操作SQL Server下

    C# 学习笔记(19)操作SQL Server下 ADO.net操作数据库 这应该是比较老的技术了,以后有空的话学学 Linq /// <summary> /// 数据库使用类 /// & ...

  3. C# 学习笔记(18)操作SQL Server 中

    C# 学习笔记(18)操作SQL Server 中 数据库基础操作 SQL语法可以参考 菜鸟教程 或者微软官方的SQL示例 注意SQL不区分大小写 查 1.基础查询 --最基础的查询语句, selec ...

  4. Python学习笔记:使用Python操作数据库

    Python学习笔记:使用Python操作数据库 一.数据库编程接口 为了对数据库进行统一的操作,大多数语言都提供了简单的.标准化的数据库接口(API).在Python Database API 2. ...

  5. python复制指定字符串_python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)...

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  6. Polyworks脚本开发学习笔记(三)-TREEVIEW进阶操作

    Polyworks脚本开发学习笔记(三)-TREEVIEW进阶操作 移动/交换对象的顺序 移动对象的顺序 TREEVIEW FEATURE MOVE ( 1,2 ) 将索引号为1和2的特征交换位置 T ...

  7. Hive学习笔记三之函数操作

    文章目录 5 函数 5.1 系统内置函数 5.2 常用内置函数 5.2.1 空字段赋值 5.2.2 CASE WHEN THEN ELSE END(类似于java中的switch case) 5.2. ...

  8. Linux_红帽8学习笔记分享_3(文件操作管理)

    Linux_红帽8学习笔记分享_3(文件操作管理) 文章目录 Linux_红帽8学习笔记分享_3(文件操作管理) 1.Vi编辑器 1.1两种模式 1.2十种技巧 2.用户的家目录 2.1 su命令的使 ...

  9. opencv进阶学习笔记5:图像模糊操作,图像锐化,边缘保留滤波EPF(图像滤镜)

    基础版传送门: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 模糊操作 方法:均值模糊,中值模 ...

最新文章

  1. [C] zintrin.h: 智能引入intrinsic函数 V1.01版。改进对Mac OS X的支持,增加INTRIN_WORDSIZE宏...
  2. 数据库系统概念总结:第十四章 事务
  3. JavaEE PO VO BO DTO POJO DAO 整理总结
  4. demo4 debug - create class instance - component works as type
  5. js模块化之模块依赖处理
  6. UI测试脸型软件,App脸型美化剖析|UI-影视-其他|观点|freshoil - 原创文章 - 站酷 (ZCOOL)...
  7. Asp.Net ListView 控件的使用
  8. 斯坦福教授ICLR演讲:图网络最新进展GraphRNN和GCPN(附PPT下载)
  9. labview csv文件处理_Labview搭建Web服务器
  10. css 圆形背景icon_CSS3 各种色彩搭配方案的圆形LOADING动效
  11. 开启TX2、Xavier最大性能 Opening the Max performance of TX2、Xavier
  12. 卸载Autodesk系列之后电脑屏幕灰白怎么解决
  13. Mockplus走进四川师范大学
  14. RCN-Rich feature hierarchies for accurate object detection and semantic segmentation
  15. java母子年龄计算,小明12岁了,妈妈的年龄比小明大20岁,请问几年后妈妈的年龄是小明的两倍。
  16. SPI 及 NOR Flash 介绍
  17. 手机音视频流媒体开发一些有用资料CVideoPlayerUtility
  18. 基层教学组织评估系统5_系统管理员数据维护模块功能完善,优化教学组织名称的输入提示补全,项目打包部署篇
  19. 《离散数学及其应用》读书笔记【三】计数
  20. [sig12]几个AAA游戏中的阴影技术

热门文章

  1. java switch是什么意思_java switch语句详解
  2. Qt--QVariant
  3. LeetCode 319 灯泡开关[数学] HERODING的LeetCode之路
  4. OpenGL南邮计算机图形学实验报告二——两个纹理的渐变变换和移动
  5. 【图形】输出一行星号
  6. UTF-8的编码规则
  7. Mature程序员演讲-二十年后的自己
  8. 基于OpenCV的摄像头人脸检测
  9. jQuery实现简单分页
  10. Pta——敲笨钟,制定位置输出字符串