本文大部分参考使用Arduino开发ESP32(18):使用Preferences保存数据

引出

在其他单片机上我们可以使用单片机自带Flash来保存一些数据,在ESP32上也可以这样,在ESP32的Flash上存在一个叫做nvs的分区,使用Arduino方式来开发的话,可以直接使用Preferences库来操作它。

大小

Arduino core for the ESP32中默认分区( Partition Scheme: “Default 4MB with spiffs (1.2MB APP /1.5MB SPIFFS)” )情况下nvs分区的大小为 20480 字节,实际可存放的数据大小要小于这个值( 单个数据来说最大为496K或者97%的nvs分区大小 )。

组织关系

Preferences中数据以键值对(key - value)的方式存储。
在键值对之上还有一层命名空间(namespace),不同命名空间中可以有相同的键名存在。在Preferences中命名空间和键名均为字符串,并且长度不大于15个字节。

命名空间和键名的关系,可以理解为结构体名和内部元素的关系。

使用演示

基础读写

#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"的值// 如果没有该元素则返回默认值0count++; // 累加计数Serial.printf("这是系统第 %u 次启动\n", count);prefs.putUInt("count", count); // 将数据保存到当前命名空间的"count"键中prefs.end(); // 关闭当前命名空间delay(5000);ESP.restart(); // 重启系统
}void loop() {}

注意:命令空间使用 prefs.begin(“mynamespace”)打开,使用prefs.end()关闭,它们是成对出现的。打开一个命名空间,对里面的键值对操作完成后,关闭这个命名空间,再打开另一个命名空间进行操作。

获取键值的函数,第二个参数是获取失败时的默认返回值。可以使用它来给变量指定默认值,比如:

    cfg->cityname = prefs.getString("cityname", "BeiJing");cfg->language = prefs.getString("language", "zh-Hans");

键值查询

#include <Preferences.h>void setup() {Serial.begin(115200);Serial.println();delay(2000);Preferences prefs;prefs.begin("mynamespace");if(prefs.isKey("naisu")) { // 如果当前命名空间中有键名为"naisu"的元素Serial.printf("naisu: %s\n\n", prefs.getString("naisu"));while (1) {}     } else {String naisu = prefs.getString("naisu", "555"); // 获取当前命名空间中的键名为"naisu"的值// 如果没有该元素则返回默认值"555"Serial.printf("naisu: %s\n\n", naisu);prefs.putString("naisu", "233");prefs.end();delay(5000);ESP.restart();}
}void loop() {}

键值删除

#include <Preferences.h>void setup() {Serial.begin(115200);Serial.println();delay(2000);Preferences prefs;prefs.begin("mynamespace");prefs.putString("naisu", "233");Serial.printf("naisu: %s\n\n", prefs.getString("naisu", "not found"));prefs.remove("naisu"); // 删除当前命名空间中键名为"naisu"的元素Serial.printf("naisu: %s\n\n", prefs.getString("naisu", "not found"));prefs.putString("naisu", "233");Serial.printf("naisu: %s\n\n", prefs.getString("naisu", "not found"));prefs.clear(); // 删除当前命名空间中的所有元素Serial.printf("naisu: %s\n\n", prefs.getString("naisu", "not found"));prefs.end();
}void loop() {}

剩余空间获取

Preferences的freeEntries方法可以获取剩余可用空间,不同类型的键值对会占用不同尺寸的空间。

#include <Preferences.h>void setup() {Serial.begin(115200);Serial.println();delay(2000);Preferences prefs;prefs.begin("mynamespace");Serial.println(prefs.freeEntries());prefs.putString("string", "22333");Serial.println(prefs.freeEntries());prefs.putInt("int", 1234567890);Serial.println(prefs.freeEntries());prefs.putChar("char", 127);Serial.println(prefs.freeEntries());uint8_t buf[5] = {1, 2, 3, 4, 5};prefs.putBytes("byte", buf, 5);Serial.println(prefs.freeEntries());prefs.end();
}void loop() {}

支持的数据类型

Preferences支持的数据类型主要就是下面API中涵盖的这部分(当然只要能保存数据那其实什么类型都无所谓了):

// put开头的方法 返回0表示操作失败 返回非0值表示操作成功
size_t putChar(const char* key, int8_t value);
size_t putUChar(const char* key, uint8_t value);
size_t putShort(const char* key, int16_t value);
size_t putUShort(const char* key, uint16_t value);
size_t putInt(const char* key, int32_t value);
size_t putUInt(const char* key, uint32_t value);
size_t putLong(const char* key, int32_t value);
size_t putULong(const char* key, uint32_t value);
size_t putLong64(const char* key, int64_t value);
size_t putULong64(const char* key, uint64_t value);
size_t putFloat(const char* key, float_t value);
size_t putDouble(const char* key, double_t value);
size_t putBool(const char* key, bool value);
size_t putString(const char* key, const char* value);
size_t putString(const char* key, String value);
size_t putBytes(const char* key, const void* value, size_t len);int8_t getChar(const char* key, int8_t defaultValue = 0);
uint8_t getUChar(const char* key, uint8_t defaultValue = 0);
int16_t getShort(const char* key, int16_t defaultValue = 0);
uint16_t getUShort(const char* key, uint16_t defaultValue = 0);
int32_t getInt(const char* key, int32_t defaultValue = 0);
uint32_t getUInt(const char* key, uint32_t defaultValue = 0);
int32_t getLong(const char* key, int32_t defaultValue = 0);
uint32_t getULong(const char* key, uint32_t defaultValue = 0);
int64_t getLong64(const char* key, int64_t defaultValue = 0);
uint64_t getULong64(const char* key, uint64_t defaultValue = 0);
float_t getFloat(const char* key, float_t defaultValue = NAN);
double_t getDouble(const char* key, double_t defaultValue = NAN);
bool getBool(const char* key, bool defaultValue = false);
size_t getString(const char* key, char* value, size_t maxLen);
String getString(const char* key, String defaultValue = String());
size_t getBytesLength(const char* key);
size_t getBytes(const char* key, void * buf, size_t maxLen);

有些地方不清楚的话,可以在库中直接去看源码,比如:

String Preferences::getString(const char* key, const String defaultValue){char * value = NULL;size_t len = 0;if(!_started || !key){return String(defaultValue);}esp_err_t err = nvs_get_str(_handle, key, value, &len);if(err){log_e("nvs_get_str len fail: %s %s", key, nvs_error(err));return String(defaultValue);}char buf[len];value = buf;err = nvs_get_str(_handle, key, value, &len);if(err){log_e("nvs_get_str fail: %s %s", key, nvs_error(err));return String(defaultValue);}return String(buf);
}

存在的问题

通过Arduino IDE上传固件请自动复位启动的话,第一次工作可能会异常(如果Preferences对象是全局声明的话异常可能会更加明显)。再次重启之后工作就正常了,或者在Arduino IDE上传固件完成时马上通过复位按钮手动复位设备也可以正常工作。目前不清楚由于什么原因引起该问题。

Arduino方式开发ESP32笔记:使用Preferences保存数据相关推荐

  1. WT32-SC01是ESP32驱动3.5彩屏开发板方案适合用arduino方式开发吗?因为需要彩屏和电容触摸的驱动的

    ESP32驱动3.5寸彩屏开发板方案因为带有彩屏和电容触摸的驱动,能否用arduino方式开发,这是很多熟悉arduino开发的技术人员关心的问题. 目前启明云端推出的http://esp32.8ms ...

  2. Polyworks脚本开发学习笔记(十九)-将数据对象与参考对象对齐的方法

    Polyworks脚本开发学习笔记(十九)-将数据对象与参考对象对齐的方法 把开发手册理了一遍,发现还有几个点没有记录下来,其中一个就是使用点对的粗对齐和使用参考目标的精确对齐.为了把这个学习笔记凑够 ...

  3. 【Arduino】开发入门教程【六】数据类型转换函数

    Arduino数据类型转换函数有 char() : 将任意类型的值转换成char类型; byte():  将任意类型的值转换成byte类型; int():  将任意类型的值转换成int类型; long ...

  4. Arduino学习笔记⑦ EEPROM断电保存数据

    1.前言     EEPROM,叫做电可擦可编程可读寄存器(是不是觉得好官方,不知道是什么鬼?反正我也一脸懵逼),只需要知道这是一种断电后数据不会丢失的存储设备,可以用来应对需要做记录做保存的场合.简 ...

  5. Vscode(arduino框架) 开发ESP32 _01_电容Touch和外部中断

    ESP32的电容Touch和外部中断 一.主程序代码 #include <Arduino.h>// 定义外部中断的 mode // 0:无中断,读取touch值 // 1:touch中断, ...

  6. 【iOS开发-74】解决方式:Xcode6下利用preference保存数据,终于的plist文件在哪里?...

    (1)现象:普通情况下.储存数据以一个沙盒为单位,preference数据存在在沙盒路径下Library/Preferences里面,可是Xcode6里找来找去根本什么都没有. (2)原因:Xcode ...

  7. 【Arduino】开发入门教程【一】什么是Arduino

    Arduino Arduino 是一款便捷灵活.方便上手的开源电子原型平台,包含硬件(各种型号的arduino板)和软件(arduino IDE).它适用于艺术家.设计师.爱好者和对于"互动 ...

  8. 【Arduino】开发入门【八】舵机操作+源代码

    [Arduino]开发入门[八]舵机操作+源代码 1.servo类成员函数 函数 说明 attach() 设定舵机的接口,只有9或10接口可利用. write() 用于设定舵机旋转角度的语句,可设定的 ...

  9. 【Arduino】开发入门教程

    [Arduino]开发入门教程[一]什么是Arduino [Ardunio]开发入门教程[二]数据类型 [Arduino]开发入门教程[三]Arduino开发工具 [Arduino]开发入门教程[四] ...

最新文章

  1. 全变量进气系统伺服马_三种伺服电动缸系统的特点
  2. win10关机更新关闭计算机,win10更新并关机怎么破_win10怎么只关机不更新
  3. 2017年关于数据科学的六大预言
  4. 2012黑龙江省赛J题-最小均值圈
  5. HDU 1698 Just a Hook 线段树
  6. 整理了 25 个前端相关的学习网站和一些靠谱的小工具,都来看看吧
  7. unity中简单的血条自作
  8. python字典的基本操作编程_Python入门教程5. 字典基本操作【定义、运算、常用函数】 原创...
  9. PHP___过期header expires
  10. Feign如何针对单个服务屏蔽Hystrix熔断功能
  11. 计算机应用职业生涯规划,计算机职业生涯规划书范文
  12. VS2008安装和打补丁
  13. 怎么设置计算机桌面一键关机,图文详解如何设置电脑定时开关机
  14. [AHK]给PPT插入图片
  15. Meta Learning在NLP领域的应用
  16. nginx安装包安装nginx
  17. luogu2161 SHOI2009 会场预约
  18. 7月书讯(上)| 读书开启下半年
  19. GitLab版本管理
  20. 最好的护眼灯是什么牌子?央视315护眼灯合格名单

热门文章

  1. python序列_科学网—Python:序列(字符串、列表、元组)和序列函数 - 刘洋洋的博文...
  2. mac怎么用c语言写文件路径,Mac 中使用os模块更改文件路径
  3. Xcode模拟器相关操作
  4. 倒频谱原理与python实现
  5. 如何最大化利用CPU性能创作沉浸式VR体验
  6. 你给需求文档,AI就能帮你开发安卓App
  7. 【报告下载】想要评测 Kylin和Vertica的性能?这份基准测试白皮书已经替你做到了...
  8. Python常见编译错更新
  9. Valgrind使用【转】
  10. 准备您的虚拟桌面--WinXp模板