ESP32-C3实现非易失变量(Arduino IDE )

1效果

网页输入数据,串口打印数据。掉电后数据还在

2源码

#include <WiFi.h> // 包含WiFi库,用于处理WiFi连接
#include <WebServer.h> // 包含WebServer库,用于创建Web服务器
#include <Preferences.h> // 包含Preferences库,用于在非易失性存储中保存键值对// 定义接入点名称
const char* ssid = "ESP32C3";
WebServer server(80); // 创建Web服务器实例,监听80端口Preferences preferences; // 创建Preferences实例,用于存储数据// 处理根目录请求的函数
void handleRoot() {String html = "<html><body>" // 构建HTML响应"<form action=\"/save\" method=\"POST\">" // 表单提交到/save路由"Enter data: <input type=\"text\" name=\"data\">" // 输入框,用户可以输入数据"<input type=\"submit\" value=\"Save\">" // 提交按钮"</form></body></html>";server.send(200, "text/html", html); // 发送HTTP响应,状态码200表示成功,内容类型为text/html
}// 处理保存数据的函数
void handleSave() {if (server.hasArg("data")) { // 检查是否有名为"data"的参数String data = server.arg("data"); // 获取名为"data"的参数值// 将数据保存到Preferencespreferences.putString("myDataKey", data); // 使用"myDataKey"作为键保存数据server.send(200, "text/plain", "Data saved!"); // 发送成功保存的响应} else {server.send(400, "text/plain", "Bad Request"); // 如果没有"data"参数,发送400错误响应}
}// 初始化函数
void setup() {Serial.begin(115200); // 初始化串口通信,波特率为115200WiFi.softAP(ssid); // 创建一个名为ssid的接入点server.begin(); // 启动Web服务器// 初始化Preferences,创建或打开名为"storage"的命名空间,不允许在文件系统中创建新文件preferences.begin("storage", false);// 设置Web服务器路由server.on("/", handleRoot); // 当访问根目录时,调用handleRoot函数server.on("/save", HTTP_POST, handleSave); // 当通过POST方法访问/save时,调用handleSave函数
}// 主循环函数
void loop() {server.handleClient(); // 处理客户端请求// 读取Preferences中的数据并通过串口输出String data = preferences.getString("myDataKey", "No data saved"); // 读取键为"myDataKey"的数据,如果不存在则返回"No data saved"Serial.println("Data from Preferences: " + data); // 输出数据到串口delay(1000); // 等待1000毫秒(1秒),每秒输出一次
}

3重点解释区

3-1

<Preferences.h> 是 Arduino ESP32 环境中的一个库,用于在 ESP32 的非易失性存储器(NVS)上保存数据。这个库是 Arduino EEPROM 库的替代品,特别适用于存储多个小值,而不是几个大值。如果需要存储大量数据,可以考虑使用文件系统库,如 LitteFS5。

基本功能和使用方法

  1. 数据存储方式Preferences 库在 NVS 中以“命名空间(namespace)”的形式存储数据,每个命名空间包含一系列的“键值对(key-value pairs)”。键名(key)是数据项的名称,值(value)是该项数据的具体值。命名空间和键名都是字符串,且长度不超过15个字符。多个命名空间是允许的,且每个命名空间内的键名必须是唯一的5。

  2. 支持的数据类型Preferences 直接支持多种数据类型,包括布尔型、字符型、整型、长整型、浮点型、双精度型和字符串等5。

  3. 基本操作:使用 Preferences 库的基本步骤包括创建或打开命名空间、存储和检索数据、删除键值对、确定键值对的数据类型等。存储数据时,需要先打开命名空间,然后使用键名存储数据,最后关闭命名空间。检索数据时,同样需要先打开命名空间,然后使用键名获取数据,最后关闭命名空间5。

  4. #include <Preferences.h>void setup() {Serial.begin(115200);Serial.println();delay(2000);Preferences prefs; // 声明Preferences对象prefs.begin("mynamespace"); // 打开命名空间mynamespaceuint32_t count = prefs.getUInt("count", 0); // 获取当前命名空间中的键名为"count"的值count++; // 累加计数Serial.printf("这是系统第 %u 次启动\n", count);prefs.putUInt("count", count); // 将数据保存到当前命名空间的"count"键中prefs.end(); // 关闭当前命名空间
    }void loop() {// ...
    }
    

    布尔型(bool)

    存储布尔值:

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putBool("myBool", true); // 存储布尔值 true
    prefs.end();
    

    获取布尔值:

    Preferences prefs;
    prefs.begin("mynamespace");
    bool myBool = prefs.getBool("myBool", false); // 获取布尔值,如果不存在则返回默认值 false
    prefs.end();
    

    字符型(int8_t)

    存储字符型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putChar("myChar", 'A'); // 存储字符 'A'
    prefs.end();
    

    获取字符型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    char myChar = prefs.getChar("myChar", 'Z'); // 获取字符,如果不存在则返回默认值 'Z'
    prefs.end();
    

    整型(int32_t)

    存储整型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putInt("myInt", 123); // 存储整型值 123
    prefs.end();
    

    获取整型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    int32_t myInt = prefs.getInt("myInt", -1); // 获取整型值,如果不存在则返回默认值 -1
    prefs.end();
    

    长整型(int32_t)

    存储长整型值(在 Preferences 库中,长整型和整型使用相同的数据类型和存储方法):

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putLong("myLong", 1234567890); // 存储长整型值 1234567890
    prefs.end();
    

    获取长整型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    int32_t myLong = prefs.getLong("myLong", -1); // 获取长整型值,如果不存在则返回默认值 -1
    prefs.end();
    

    浮点型(float)

    存储浮点型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putFloat("myFloat", 3.14f); // 存储浮点型值 3.14
    prefs.end();
    

    获取浮点型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    float myFloat = prefs.getFloat("myFloat", 0.0f); // 获取浮点型值,如果不存在则返回默认值 0.0
    prefs.end();
    

    双精度型(double)

    存储双精度型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putDouble("myDouble", 3.14159265358979323846); // 存储双精度型值
    prefs.end();
    

    获取双精度型值:

    Preferences prefs;
    prefs.begin("mynamespace");
    double myDouble = prefs.getDouble("myDouble", 0.0); // 获取双精度型值,如果不存在则返回默认值 0.0
    prefs.end();
    

    字符串(const char*)

    存储字符串:

    Preferences prefs;
    prefs.begin("mynamespace");
    prefs.putString("myString", "Hello World"); // 存储字符串 "Hello World"
    prefs.end();
    

    获取字符串:

    Preferences prefs;
    prefs.begin("mynamespace");
    String myString = prefs.getString("myString", "Default"); // 获取字符串,如果不存在则返回默认值 "Default"
    prefs.end();
    

    请注意,字符串可以存储为 Arduino String 对象或 C-string(以空字符结尾的字符数组)。在存储和检索字符串时,确保使用正确的方法。如果使用 C-string,请确保字符串长度不超过 NVS 分区允许的最大长度。

何时调用 prefs.end();(运行后将清理此对象,数据还在就是不可用重新上电后可以看到数据但在运行到它是再次读取数据时读不到)

  1. 在完成所有数据操作后调用:在完成对 NVS 的所有读取和写入操作后,应该调用 prefs.end();。这通常是在一系列 put...()(用于写入数据)或 get...()(用于读取数据)方法调用之后。

  2. 在适当的作用域结束处调用:通常在函数或作用域结束前调用 prefs.end();,以确保资源得到及时释放。

prefs.end(); 的作用

  • 确保数据写入:调用 prefs.end(); 确保所有挂起的写入操作都已完成,并且数据已经安全地存储在 NVS 中。

  • 释放资源:这个方法会关闭 Preferences 实例与 NVS 的连接,并释放与之相关的内存和其他资源。

  • 防止数据损坏:如果不调用 prefs.end();,可能会导致数据未完全写入或损坏,特别是在断电或程序崩溃的情况下。

示例

Preferences prefs;void setup() {// 开始 Preferences 实例,指定命名空间prefs.begin("mynamespace", false); // false 表示不覆盖现有数据// 存储一些数据prefs.putInt("myInt", 123);prefs.putFloat("myFloat", 456.78);// 结束 Preferences 实例prefs.end();
}void loop() {// 其他代码...
}

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

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

相关文章

告别微信封号!学会这5招,让你的账号坚不可摧

在这个信息爆炸的时代&#xff0c;无论是工作沟通、社交互动还是获取信息&#xff0c;微信都扮演着极其重要的角色。但是&#xff0c;随着微信平台规则的日益严格&#xff0c;账号被封的风险也随之增加。今天&#xff0c;我们就来聊聊如何有效防止 微信被封&#xff0c;让你的账…

【MySQL】入门篇—基本数据类型:NULL值的概念

在关系数据库中&#xff0c;NULL值是一个特殊的标记&#xff0c;表示缺失或未知的值。 NULL并不等同于零&#xff08;0&#xff09;或空字符串&#xff08;&#xff09;&#xff0c;它表示一个字段没有任何值。 这一概念在数据库设计和数据管理中至关重要&#xff0c;因为它影…

力扣——环形链表问题

判断链表是否有环以及入环的第一个节点 前言判断链表是否有环找到入环的第一个节点 前言 大家好&#xff0c;前段时间&#xff0c;熊二学习了关于环形链表相关的问题&#xff0c;以下是我的见解&#xff0c;希望能够帮助你们呀&#xff01; 判断链表是否有环 给定一个链表&am…

如何在一个月内快速学习掌握大模型

原本给自己的是一个月时间&#xff0c;通过梳理之后我自信的认为不需要一个月&#xff0c;两周即可&#xff0c;相较于其他技术&#xff0c;大模型应用的门槛要低得多。 先明确你想要深入到哪一层 1、基础设施层&#xff1a;了解即可&#xff0c;关注NVIDIA和超大规模厂商的最…

[自动化测试:Selenium]:环境部署和Webdriver的使用

文章目录 修改安装源打开Python Packages。点击梅花按钮。在弹出的对话框中&#xff0c;填入Name&#xff08;随便填&#xff09;&#xff0c;Repository URL&#xff0c;选择下列的源&#xff0c;一般先选择清华源按OK确认。配置完成 安装seleniumFile→Settings→Project&…

多签机制简明理解及实例说明

目录 Multisignature机制简明理解及实例说明 Multisignature机制中的公钥、私钥、Nonce及签名验签详解 加密货币托管账户的多重签名机制 Multisignature机制简明理解及实例说明 一、基本概念 Multisignature(多重签名)机制是一种先进的加密技术,它允许一笔交易必须由多…

word删除空白页 | 亲测有效

想要删掉word里面的末尾空白页&#xff0c;但是按了delete之后也没有用 找了很久找到了以下亲测有效的方法 1. 通过鼠标右键在要删除的空白页面处显示段落标记 2. 在字号输入01&#xff0c;按ENTER&#xff08;回车键&#xff09; 3.成功删除了&#xff01;&#xff01; PS…

【ArcGIS Pro实操第八期】绘制WRF三层嵌套区域

【ArcGIS Pro实操第八期】绘制WRF三层嵌套区域 数据准备ArcGIS Pro绘制WRF三层嵌套区域Map-绘制三层嵌套区域更改ArcMap地图的默认显示方向指定数据框范围 Map绘制研究区Layout-布局出图 参考 本博客基于ArcGIS Pro绘制WRF三层嵌套区域&#xff0c;具体实现图形参考下图&#x…

两性离子水凝胶助力微针传感器:稳定灵敏的监测神器

大家好&#xff01;今天我要向大家介绍一项关于生物相容性核壳微针传感器的研究——《Biocompatible Core–Shell Microneedle Sensor Filled with Zwitterionic Polymer Hydrogel for Rapid Continuous Transdermal Monitoring》发表于《ACS Nano》&#xff0c;该传感器填充两…

力扣每日打卡挑战 3184. 构成整天的下标对数目 I

给你一个整数数组 hours&#xff0c;表示以 小时 为单位的时间&#xff0c;返回一个整数&#xff0c;表示满足 i < j 且 hours[i] hours[j] 构成 整天 的下标对 i, j 的数目。 整天 定义为时间持续时间是 24 小时的 整数倍 。 例如&#xff0c;1 天是 24 小时&#xff0c…

深入解析 Golang 并发编程中的同步机制:WaitGroup 与 Mutex 详解

文章目录 一、简介二、WaitGroup 的使用1. 什么是 WaitGroup&#xff1f;2. 基本操作3. WaitGroup 示例4. 注意事项 三、Mutex 的使用1. 什么是 Mutex&#xff1f;2. 基本操作3. Mutex 示例 四、竞争条件示例与解决1. 竞争条件问题示例2. 使用 Mutex 解决竞争条件 五、使用 RWM…

FFMPEG录屏(19)--- 枚举Windows下的屏幕列表,并获取名称、缩略图

在Windows下枚举显示器列表并获取名称、缩略图 在Windows系统中&#xff0c;枚举显示器列表并获取它们的名称和缩略图是一个常见的需求。本文将详细介绍如何实现这一功能&#xff0c;涉及到的主要技术包括Windows API和C编程。 获取显示器信息 首先&#xff0c;我们需要一个…

爬虫结合项目实战

由于本人是大数据专业&#xff0c;所以准备的是使用pycharm工具进行爬虫爬取数据&#xff0c;然后实现一个可视化大屏 参考项目&#xff1a; 1.医院大数据可视化最后展示 2. 大数据分析可视化系统展示 代码包&#xff1a;

自由学习记录(13)

服务端常见的“资源” 在服务端&#xff0c;常见的“资源”指的是服务端提供给客户端访问、使用、处理或操作的各种数据和功能。根据不同类型的服务和应用场景&#xff0c;服务端的资源种类可以非常广泛。以下是一些常见的服务端资源类型&#xff1a; 1. 文件和静态资源 网页…

LSP的建立

MPLS需要为报文事先分配好标签&#xff0c;建立一条LSP&#xff0c;才能进行报文转发。LSP分为静态LSP和动态LSP两种。 静态LSP的建立 静态LSP是用户通过手工为各个转发等价类分配标签而建立的。由于静态LSP各节点上不能相互感知到整个LSP的情况&#xff0c;因此静态LSP是一个…

阿里云云盘在卸载时关联到PHP进程,如何在不影响PHP进程情况下卸载磁盘

1.问题&#xff1a; 在使用umount /dev/vdc1 卸载磁盘时&#xff0c;提示如下&#xff0c;导致无法在Linux系统下卸载磁盘 umount /dev/vdc1 umount: /var/www/html/*/eshop/IFile3: target is busy.(In some cases useful info about processes that usethe device is found…

NumPy学习Day18

1.数据迭代 1.1 nditer 使用np.nditer(x,order)遍历数组x中的元素 x为需要遍历的数组orderc’时按照行优先遍历orderf’时按照列优先遍历 1.2 flags参数 flags可以返回数组中元素的多维索引&#xff08;类似矩阵的坐标&#xff09; multi_index: 返回每个元素的多维索引。…

工具类的构造方法为什么要用private修饰

工具类&#xff08;Utility Class&#xff09;通常被设计为包含静态方法和静态变量的类&#xff0c;可以使用类名.方法名直接调用&#xff0c;不用进行实例化&#xff0c;这是工具类的设计原则&#xff0c;所以构造方法用private修饰&#xff08;因为公开的方法可以被实例化&am…

基于neo4j的糖尿病知识图谱数据

基于Neo4j的糖尿病知识图谱项目&#xff1a;毕业设计必备&#x1f4a1; 这个项目&#xff0c;专为需要深入挖掘医学或AI数据的朋友们量身定制&#xff0c;尤其适合用于毕业设计&#xff01;如果你对图谱构建、AI问答系统、或者正在学习Neo4j&#xff0c;那么你不得不看看这个技…

管家婆财贸ERP BB014.销售按库存选存货

最低适用版本: 财贸系列 22.8 插件简要功能说明: 销售按库存选存货插件,多元化价格跟踪体系用户根据存货+仓库自设仓库协议价仓库协议价支持手工或通过售价生成便捷录入销售单开单,无需选择客户,支持按存货查询库存余额及仓库协议价,选中存货即可将存货默认出库单位一级…