ESP32_学习笔记(一)NVS的操作(存储和读取大数组)(为什么存入数据成功,读取却为零的原因)
目录
- 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的操作(存储和读取大数组)(为什么存入数据成功,读取却为零的原因)相关推荐
- C# 学习笔记(17)操作SQL Server 上
C# 学习笔记(17)操作SQL Server上 安装SQL Server 微软官网 https://www.microsoft.com/zh-cn/sql-server/sql-server-dow ...
- C# 学习笔记(19)操作SQL Server下
C# 学习笔记(19)操作SQL Server下 ADO.net操作数据库 这应该是比较老的技术了,以后有空的话学学 Linq /// <summary> /// 数据库使用类 /// & ...
- C# 学习笔记(18)操作SQL Server 中
C# 学习笔记(18)操作SQL Server 中 数据库基础操作 SQL语法可以参考 菜鸟教程 或者微软官方的SQL示例 注意SQL不区分大小写 查 1.基础查询 --最基础的查询语句, selec ...
- Python学习笔记:使用Python操作数据库
Python学习笔记:使用Python操作数据库 一.数据库编程接口 为了对数据库进行统一的操作,大多数语言都提供了简单的.标准化的数据库接口(API).在Python Database API 2. ...
- python复制指定字符串_python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)...
python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...
- Polyworks脚本开发学习笔记(三)-TREEVIEW进阶操作
Polyworks脚本开发学习笔记(三)-TREEVIEW进阶操作 移动/交换对象的顺序 移动对象的顺序 TREEVIEW FEATURE MOVE ( 1,2 ) 将索引号为1和2的特征交换位置 T ...
- Hive学习笔记三之函数操作
文章目录 5 函数 5.1 系统内置函数 5.2 常用内置函数 5.2.1 空字段赋值 5.2.2 CASE WHEN THEN ELSE END(类似于java中的switch case) 5.2. ...
- Linux_红帽8学习笔记分享_3(文件操作管理)
Linux_红帽8学习笔记分享_3(文件操作管理) 文章目录 Linux_红帽8学习笔记分享_3(文件操作管理) 1.Vi编辑器 1.1两种模式 1.2十种技巧 2.用户的家目录 2.1 su命令的使 ...
- opencv进阶学习笔记5:图像模糊操作,图像锐化,边缘保留滤波EPF(图像滤镜)
基础版传送门: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 模糊操作 方法:均值模糊,中值模 ...
最新文章
- [C] zintrin.h: 智能引入intrinsic函数 V1.01版。改进对Mac OS X的支持,增加INTRIN_WORDSIZE宏...
- 数据库系统概念总结:第十四章 事务
- JavaEE PO VO BO DTO POJO DAO 整理总结
- demo4 debug - create class instance - component works as type
- js模块化之模块依赖处理
- UI测试脸型软件,App脸型美化剖析|UI-影视-其他|观点|freshoil - 原创文章 - 站酷 (ZCOOL)...
- Asp.Net ListView 控件的使用
- 斯坦福教授ICLR演讲:图网络最新进展GraphRNN和GCPN(附PPT下载)
- labview csv文件处理_Labview搭建Web服务器
- css 圆形背景icon_CSS3 各种色彩搭配方案的圆形LOADING动效
- 开启TX2、Xavier最大性能 Opening the Max performance of TX2、Xavier
- 卸载Autodesk系列之后电脑屏幕灰白怎么解决
- Mockplus走进四川师范大学
- RCN-Rich feature hierarchies for accurate object detection and semantic segmentation
- java母子年龄计算,小明12岁了,妈妈的年龄比小明大20岁,请问几年后妈妈的年龄是小明的两倍。
- SPI 及 NOR Flash 介绍
- 手机音视频流媒体开发一些有用资料CVideoPlayerUtility
- 基层教学组织评估系统5_系统管理员数据维护模块功能完善,优化教学组织名称的输入提示补全,项目打包部署篇
- 《离散数学及其应用》读书笔记【三】计数
- [sig12]几个AAA游戏中的阴影技术