SOC-ESP32S3部分:21-非易失性存储库

飞书文档https://x509p6c8to.feishu.cn/wiki/QB0Zw7GLeio4l4kyaWQcuQT3nZS

非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。

它允许我们在芯片的闪存中存储和读取数据,即使在断电后,这些数据也不会丢失。

NVS 是 ESP32 flash(flash就是板子上的一个存储芯片)中的一个存储分区,我们可以在其中存储键值对(key-value pairs)。每个键值对都有一个唯一的键名(key name)和一个对应的值(value)。这种组合类似于哈希表的(key-value)对应结构。

初始化NVS

在开始使用NVS之前,需要先初始化整个NVS分区。通常在应用程序启动阶段完成这一操作

esp_err_t nvs_flash_init(void);
返回值
esp_err_t
表示函数执行的结果,通常为以下几种情况:
ESP_OK: 成功初始化 NVS(Non-Volatile Storage)闪存。
ESP_ERR_NVS_NO_FREE_PAGES: NVS 分区没有可用的页。
ESP_ERR_NVS_NEW_VERSION_FOUND: NVS 分区版本更新,需要格式化。
ESP_ERR_NVS_NOT_INITIALIZED: NVS 未初始化。
ESP_ERR_NVS_INVALID_STATE: NVS 已经初始化。
其他可能的错误代码,具体取决于底层实现。示例参考:
#include <nvs_flash.h>
void app_main()
{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_open nvs_set_*nvs_commit三个函数来存储数据。

nvs_open 函数用于打开一个 NVS 命名空间,并返回一个句柄,通过该句柄可以进行后续的读写操作。
esp_err_t nvs_open(const char *name, nvs_open_mode_t open_mode, nvs_handle_t *out_handle);
参数
const char *name: NVS 命名空间的名称。命名空间用于组织存储的数据,类似于文件夹的概念。
nvs_open_mode_t open_mode: 打开命名空间的模式,可以是以下几种:
NVS_READONLY: 只读模式。
NVS_READWRITE: 读写模式。
nvs_handle_t *out_handle: 输出参数,用于返回打开的命名空间的句柄。通过这个句柄可以进行后续的读写操作。nvs_set_i32 函数用于将一个 32 位整数值存储到 NVS 中,使用指定的键名标识该数据。存储的数据可以通过该键名在后续的读取操作中检索。
esp_err_t nvs_set_i32(nvs_handle_t handle, const char *key, int32_t value);
参数
nvs_handle_t handle: 通过 nvs_open 函数获得的命名空间句柄。
const char *key: 要存储的数据的键名。键名用于标识存储的数据。
int32_t value: 要存储的 32 位整数值。nvs_commit 函数用于将对 NVS 命名空间所做的更改(如设置、删除键值对等)提交到闪存中。
在调用 nvs_set_i32 或其他设置函数后,必须调用 nvs_commit 以确保更改被持久化到 NVS 分区中。
如果不调用 nvs_commit,更改将不会保存到闪存中,下次读取时将不会看到这些更改
esp_err_t nvs_commit(nvs_handle_t handle);
参数
nvs_handle_t handle: 通过 nvs_open 函数获得的命名空间句柄。// 存储数据
nvs_handle_t my_handle;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle);        //打开命名空间
if (err == ESP_OK) {err = nvs_set_i32(my_handle, "restart_counter", 1);if (err == ESP_OK) {err = nvs_commit(my_handle);}nvs_close(my_handle);
}

在这个例子中,我们首先打开了一个名为 “storage” 的 NVS 名称空间,然后在其中存储了一个键名为 “restart_counter”、值为1的键值对。

而nvs_commit()函数的主要作用是将所有挂起的更改写入NVS。当你在NVS中设置一个键值对后,这个更改首先被存储在内存中。只有当你调用nvs_commit()函数时,这些更改才会被写入闪存。

所以,如果你在调用nvs_commit()函数之前重启了设备,那么你在NVS中设置的所有键值对都将丢失。因此,每次在NVS中设置键值对后,都应该调用nvs_commit()函数,以确保这些更改在设备重启后仍然存在。

当然,还有其它不同类型的数据存储接口

nvs_set_i8
功能: 存储 8 位整数。
esp_err_t nvs_set_i8(nvs_handle_t handle, const char *key, int8_t value);nvs_set_u8
功能: 存储 8 位无符号整数。
esp_err_t nvs_set_u8(nvs_handle_t handle, const char *key, uint8_t value);nvs_set_i16
功能: 存储 16 位整数。
esp_err_t nvs_set_i16(nvs_handle_t handle, const char *key, int16_t value);nvs_set_u16
功能: 存储 16 位无符号整数。
esp_err_t nvs_set_u16(nvs_handle_t handle, const char *key, uint16_t value);nvs_set_u32
功能: 存储 32 位无符号整数。
esp_err_t nvs_set_u32(nvs_handle_t handle, const char *key, uint32_t value);nvs_set_i64
功能: 存储 64 位整数。
esp_err_t nvs_set_i64(nvs_handle_t handle, const char *key, int64_t value);nvs_set_u64
功能: 存储 64 位无符号整数。
esp_err_t nvs_set_u64(nvs_handle_t handle, const char *key, uint64_t value);nvs_set_str
功能: 存储字符串。
esp_err_t nvs_set_str(nvs_handle_t handle, const char *key, const char *value);
参数:
handle: NVS 命名空间句柄。
key: 键名。
value: 要存储的字符串。nvs_set_blob
功能: 存储二进制数据块。
esp_err_t nvs_set_blob(nvs_handle_t handle, const char *key, const void *value, size_t length);
参数:
handle: NVS 命名空间句柄。
key: 键名。
value: 要存储的二进制数据块。
length: 数据块的长度(以字节为单位)。使用示例:// 存储不同类型的数据err = nvs_set_i8(my_handle, "int8_key", 10);ESP_ERROR_CHECK(err);err = nvs_set_u8(my_handle, "uint8_key", 20);ESP_ERROR_CHECK(err);err = nvs_set_i16(my_handle, "int16_key", 300);ESP_ERROR_CHECK(err);err = nvs_set_u16(my_handle, "uint16_key", 400);ESP_ERROR_CHECK(err);err = nvs_set_u32(my_handle, "uint32_key", 5000);ESP_ERROR_CHECK(err);err = nvs_set_i64(my_handle, "int64_key", 60000);ESP_ERROR_CHECK(err);err = nvs_set_u64(my_handle, "uint64_key", 70000);ESP_ERROR_CHECK(err);const char *str_value = "Hello, NVS!";err = nvs_set_str(my_handle, "str_key", str_value);ESP_ERROR_CHECK(err);uint8_t blob_value[] = {0x01, 0x02, 0x03, 0x04};size_t blob_length = sizeof(blob_value);err = nvs_set_blob(my_handle, "blob_key", blob_value, blob_length);ESP_ERROR_CHECK(err);

使用 NVS 读取数据

我们可以使用 nvs_get_* 函数来读取数据。例如,我们可以使用 nvs_get_i32 函数来读取一个整数:

nvs_get_i32 函数用于从 NVS 中读取一个 32 位整数值,使用指定的键名标识该数据。读取的数据存储在输出参数中,可以通过该参数访问。
esp_err_t nvs_get_i32(nvs_handle_t handle, const char *key, int32_t *out_value);
参数
nvs_handle_t handle: 通过 nvs_open 函数获得的命名空间句柄。const char *key: 要读取的数据的键名。键名用于标识存储的数据。int32_t *out_value: 输出参数,用于存储从 NVS 中读取的 32 位整数值。使用参考
// 检索数据
nvs_handle_t my_handle;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &my_handle);
if (err == ESP_OK) {int32_t value;err = nvs_get_i32(my_handle, "restart_counter", &value);if (err == ESP_OK) {printf("Value = %d\n", value);}nvs_close(my_handle);
}

删掉NVS上的数据

esp_err_t nvs_flash_erase(void);
返回值
esp_err_t
表示函数执行的结果,通常为以下几种情况:
ESP_OK: 成功擦除 NVS 分区。
ESP_ERR_NVS_NOT_INITIALIZED: NVS 未初始化。
ESP_ERR_NVS_INVALID_STATE: NVS 处于无效状态。
其他可能的错误代码,具体取决于底层实现

最终参考程序:

#include <stdio.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_log.h"static const char *TAG = "NVS"; // 定义日志标签void app_main(void)
{// 初始化 NVSesp_err_t err = nvs_flash_init();if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {// NVS 分区被截断,需要擦除// 重新初始化 nvs_flashESP_ERROR_CHECK(nvs_flash_erase());err = nvs_flash_init();}ESP_ERROR_CHECK(err);// 打开命名空间ESP_LOGI(TAG, "打开非易失性存储 (NVS) 句柄...");nvs_handle_t my_handle;err = nvs_open("storage", NVS_READWRITE, &my_handle);if (err != ESP_OK) {ESP_LOGI(TAG, "打开 NVS 句柄时出错 (%s)!\n", esp_err_to_name(err));} else {// 读取重启计数器ESP_LOGI(TAG, "从 NVS 读取重启计数器 ... ");int32_t restart_counter = 0; // 如果 NVS 中未设置值,则默认为 0err = nvs_get_i32(my_handle, "restart_counter", &restart_counter);ESP_LOGI(TAG, "重启计数器 = %" PRIu32 "\n", restart_counter);// 更新重启计数器ESP_LOGI(TAG, "更新 NVS 中的重启计数器 ... ");restart_counter++;err = nvs_set_i32(my_handle, "restart_counter", restart_counter);// 提交写入的值。设置任何值后,必须调用 nvs_commit() 以确保更改写入闪存存储。ESP_LOGI(TAG, "提交 NVS 中的更改 ... ");err = nvs_commit(my_handle);// 关闭命名空间nvs_close(my_handle);}ESP_LOGI(TAG, "\n");// 重启模块for (int i = 10; i >= 0; i--) {ESP_LOGI(TAG, "将在 %d 秒后重启...\n", i);vTaskDelay(1000 / portTICK_PERIOD_MS);}ESP_LOGI(TAG, "现在重启。\n");fflush(stdout);esp_restart();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82014.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

让大模型看得见自己的推理 — KnowTrace结构化知识追踪

让大模型“看得见”自己的推理 —— KnowTrace 结构化知识追踪式 RAG 全解析 一句话概括:把检索-推理“改造”成 动态知识图构建任务,再让 LLM 只关注这张不断精炼的小图 —— 这就是显式知识追踪的核心价值。 1. 背景:为什么 RAG 仍难以搞定多跳推理? 长上下文负担 传统 I…

新版智慧景区信息化系统解决方案

该智慧景区信息化系统解决方案以云 + 大数据 + 物联网技术为核心,秉持 “汇聚联合,突显数据隐性价值” 理念,通过数据融合、业务融合、技术融合,构建 “营销、服务、管理” 三位一体模式。方案涵盖智慧票务、智能入园、精准营销、景区管理(如用电安全监测、森林防火、客流…

人工智能在智能健康监测中的创新应用与未来趋势

随着人们健康意识的不断提高和医疗资源的日益紧张&#xff0c;智能健康监测作为一种新兴的健康管理方式&#xff0c;正在迅速发展。人工智能&#xff08;AI&#xff09;技术通过其强大的数据分析和预测能力&#xff0c;为智能健康监测提供了重要的技术支持。本文将探讨人工智能…

python打卡day40

知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 导入包 # 先继续之前的代码 import torch …

系统性学习C语言-第十二讲-深入理解指针(2)

系统性学习C语言-第十二讲-深入理解指针&#xff08;2&#xff09; 1. const 修饰指针1.1 const 修饰变量1.2 const 修饰指针变量 2. 野指针2.1 野指针成因2.2 如何规避野指针2.2.1 指针初始化2.2.2 小心指针越界2.2.3 指针变量不再使用时&#xff0c;及时置 NULL &…

《高等数学》(同济大学·第7版) 第一节《映射与函数》超详细解析

集合&#xff08;Set&#xff09;—— 最基础的数学容器 定义&#xff1a; 集合是由确定的、互不相同的对象&#xff08;称为元素&#xff09;组成的整体。 表示方法&#xff1a; 列举法&#xff1a;A {1, 2, 3} 描述法&#xff1a;B {x | x > 0}&#xff08;表示所有大于…

Spring Boot整活指南:从Helo World到“真香”定律

&#x1f4cc; 一、Spring Boot的"真香"本质&#xff08;不是996的福报&#xff09; 你以为Spring Boot只是个简化配置的工具&#xff1f;Too young&#xff01;它其实是程序员的​​摸鱼加速器​​。 ​​经典场景还原​​&#xff1a; 产品经理&#xff1a;“这个…

打字练习:平台推荐

1.打字练习 . 1&#xff09;平台推荐 下面推荐两个打字练习平台 Keybr&#xff1a;https://www.keybr.com/ TypingClub&#xff1a;https://www.edclub.com/sportal/ . 2&#xff09;平台对比 特性KeybrTypingClub核心优势AI智能弱项训练结构化课程体系适合人群开发者/…

ASP.NET Core 中JWT的基本使用

文章目录 前言一、JWT与RBAC二、JWT 的作用三、RBAC 的核心思想四、使用1、配置文件 (appsettings.json)2、JWT配置模型 (Entity/JwtSettings.cs)3、服务扩展类&#xff0c;JWT配置 (Extensions/ServiceExtensions.cs)4、用户仓库接口服务5、认证服务 (Interface/IAuthService.…

(19)java在区块链中的应用

&#x1f517; Java在区块链中的应用&#xff1a;智能合约开发全攻略 TL;DR: Java在区块链领域主要通过Hyperledger Fabric、Web3j和专用JVM实现智能合约开发&#xff0c;相比Solidity具有更强的企业级支持和开发效率&#xff0c;但在执行效率和Gas消耗方面存在差异&#xff0c…

深入理解设计模式之访问者模式

深入理解设计模式之访问者模式&#xff08;Visitor Pattern&#xff09; 一、什么是访问者模式&#xff1f; 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式。它的主要作用是将数据结构与数据操作分离&#xff0c;使得在不改变数据结构的前提下&…

div或button一些好看实用的 CSS 样式示例

1&#xff1a;现代渐变按钮 .count {width: 800px;background: linear-gradient(135deg, #72EDF2 0%, #5151E5 100%);padding: 12px 24px;border-radius: 10px;box-shadow: 0 4px 15px rgba(81, 81, 229, 0.3);color: white;font-weight: bold;border: none;cursor: pointer;t…

【基于STM32的新能源汽车智能循迹系统开发全解析】

基于STM32的新能源汽车智能循迹系统开发全解析&#xff08;附完整工程代码&#xff09; 作者声明 作者&#xff1a; 某新能源车企资深嵌入式工程师&#xff08;专家认证&#xff09; 技术方向&#xff1a; 智能驾驶底层控制 | 车规级嵌入式开发 原创声明&#xff1a; 本文已申…

HTML Day02

Day02 0. 引言1. 文本格式化1.1 HTML文本格式化标签1.2 HTML"计算机输出"标签1.3 HTML 引文&#xff0c;引用及标签定义 2. HTML链接2.1链接跳转原理&#xff08;有点乱可跳过&#xff09;2.2 HTML超链接2.3 target属性2.4 id属性2.4.1 id属性在页面内和不同页面的定…

MIT 6.S081 2020 Lab6 Copy-on-Write Fork for xv6 个人全流程

文章目录 零、写在前面一、Implement copy-on write1.1 说明1.2 实现1.2.1 延迟复制与释放1.2.2 写时复制 零、写在前面 可以阅读下 《xv6 book》 的第五章中断和设备驱动。 问题 在 xv6 中&#xff0c;fork() 系统调用会将父进程的整个用户空间内存复制到子进程中。**如果父…

xhr、fetch和axios

XMLHttpRequest (XHR) XMLHttpRequest 是最早用于在浏览器中进行异步网络请求的 API。它允许网页在不刷新整个页面的情况下与服务器交换数据。 // 创建 XHR 对象 const xhr new XMLHttpRequest();// 初始化请求 xhr.open(GET, https://api.example.com/data, true);// 设置请…

电脑驱动程序更新工具, 3DP Chip 中文绿色版,一键更新驱动!

介绍 3DP Chip 是一款免费的驱动程序更新工具&#xff0c;可以帮助用户快速、方便地识别和更新计算机硬件驱动程序。 驱动程序更新工具下载 https://pan.quark.cn/s/98895d47f57c 软件截图 软件特点 简单易用&#xff1a;用户界面简洁明了&#xff0c;操作方便&#xff0c;…

机器学习与深度学习06-决策树02

目录 前文回顾5.决策树中的熵和信息增益6.什么是基尼不纯度7.决策树与回归问题8.随机森林是什么 前文回顾 上一篇文章地址&#xff1a;链接 5.决策树中的熵和信息增益 熵和信息增益是在决策树中用于特征选择的重要概念&#xff0c;它们帮助选择最佳特征进行划分。 熵&#…

【Kotlin】数字字符串数组集合

【Kotlin】简介&变量&类&接口 【Kotlin】数字&字符串&数组&集合 文章目录 Kotlin_数字&字符串&数组&集合数字字面常量显式转换数值类型转换背后发生了什么 运算字符串字符串模板字符串判等修饰符数组集合通过序列提高效率惰性求值序列的操…

oscp练习PG Monster靶机复现

端口扫描 nmap -A -p- -T4 -Pn 192.168.134.180 PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.41 ((Win64) OpenSSL/1.1.1c PHP/7.3.10) |_http-server-header: Apache/2.4.41 (Win64) OpenSSL/1.1.1c PHP/7.3.10 | http-methods:…