Arduino方式开发ESP32笔记:使用Preferences保存数据
Posted qlexcel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Arduino方式开发ESP32笔记:使用Preferences保存数据相关的知识,希望对你有一定的参考价值。
本文大部分参考使用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"); // 打开命名空间mynamespace
uint32_t count = prefs.getUInt("count", 0); // 获取当前命名空间中的键名为"count"的值
// 如果没有该元素则返回默认值0
count++; // 累加计数
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保存数据的主要内容,如果未能解决你的问题,请参考以下文章
ESP32上手笔记 | 02 - ESP32-Arduino开发环境搭建
基于arduino的ESP32 学习笔记 TFT_eSPI和LVGL库使用笔记