ESP32 偏好设置



非易失性存储器是嵌入式系统的重要需求。通常,我们希望芯片即使在电源循环之间也能记住一些事情,例如设置变量、WiFi凭据等。如果每次设备进行电源重置都必须执行设置或配置,那将非常不方便。ESP32 有两种常用的非易失性存储方法:偏好设置和 SPIFFS。偏好设置通常用于存储键值对,而 SPIFFS(SPI Flash 文件系统)顾名思义,用于存储文件和文档。在本章中,让我们关注偏好设置。

偏好设置存储在主闪存的一个区域中,类型为数据,子类型为nvsnvs代表非易失性存储器。默认情况下,为偏好设置保留 20 KB 的空间,因此请不要尝试在偏好设置中存储大量庞大的数据。对于庞大的数据,请使用 SPIFFS(SPIFFS 默认保留 1.5 MB 的空间)。在偏好设置中可以存储哪些类型的键值对?让我们通过示例代码来了解。

代码演练

我们将使用提供的示例代码。转到文件 -> 示例 -> 偏好设置 -> StartCounter。它也可以在GitHub上找到。

此代码记录 ESP32 重置了多少次。因此,每次它唤醒时,它都会从偏好设置中获取现有计数,将其加一,并将更新后的计数保存回偏好设置。然后它重置 ESP32。您可以通过 ESP32 上的打印语句看到,计数的值在重置之间不会丢失,它确实是持久的。

此代码包含大量的注释,因此在很大程度上是不言自明的。但是,让我们逐步浏览代码。

我们首先包含 Preferences 库。

#include <Preferences.h>

接下来,我们创建一个 Preferences 类的对象。

Preferences preferences;

现在让我们逐行查看 setup 函数。我们首先初始化 Serial。

void setup() {
   Serial.begin(115200);
   Serial.println();

接下来,我们使用命名空间打开偏好设置。现在,将偏好设置存储想象成一个银行储物柜室。有很多储物柜,你一次打开一个。命名空间就像储物柜的名称。在每个储物柜中,都有您可以访问的键值对。如果您提到的储物柜名称不存在,则会创建它,然后您可以向该储物柜添加键值对。为什么会有不同的储物柜?为了避免名称冲突。假设您有一个使用偏好设置存储凭据的 WiFi 库,还有一个也使用偏好设置存储凭据的蓝牙库。假设这两个库由不同的开发者开发。如果两者都使用相同的键名credentials怎么办?这显然会造成很大的混乱。但是,如果两者都在不同的储物柜中存储键值,则根本不会有任何混乱。

// Open Preferences with my-app namespace. Each application module, library, etc
// has to use a namespace name to prevent key name collisions. We will open storage in
// RW-mode (second parameter has to be false).
// Note: Namespace name is limited to 15 chars.
preferences.begin("my−app", false);

preferences.begin()的第二个参数false表示我们希望同时读取和写入此储物柜。如果是 true,我们只能读取储物柜,而不能写入。此外,如注释中所述,命名空间的长度不应超过 15 个字符。

接下来,代码中有一些已注释的语句,您可以根据需要使用它们。一个允许您清除储物柜,另一个帮助您从储物柜中删除特定的键值对(键为“counter”)。

// Remove all preferences under the opened namespace
//preferences.clear();

// Or remove the counter key only
//preferences.remove("counter");

下一步,我们获取与键“counter”关联的值。现在,当您第一次运行此程序时,可能不存在这样的键。因此,我们还提供 0 作为preferences.getUInt()函数的参数作为默认值。这告诉 ESP32,如果键“counter”不存在,则创建一个新的键值对,键为“counter”,值为0。另请注意,我们使用getUInt是因为该值是无符号整型。根据值的类型,需要调用其他函数,如getFloatgetString等。完整的选项列表可以在这里找到。

unsigned int counter = preferences.getUInt("counter", 0);

接下来,我们将此计数加一,并将其打印到串口监视器上。

// Increase counter by 1
counter++;

// Print the counter to Serial Monitor
Serial.printf("Current counter value: %u\n", counter);

然后我们将此更新后的值存储回非易失性存储器。我们基本上是在更新键“counter”的值。下次 ESP32 读取键“counter”的值时,它将获取递增后的值。

// Store the counter to the Preferences
preferences.putUInt("counter", counter);

最后,我们关闭偏好设置储物柜并在 10 秒钟后重新启动 ESP32。

// Close the Preferences
preferences.end();

// Wait 10 seconds
Serial.println("Restarting in 10 seconds...");
delay(10000);
   
// Restart ESP
ESP.restart();
}

因为我们在进入循环之前重新启动了 ESP32,所以循环永远不会执行。因此,它保持为空。

void loop() {}
Serial Monitor Output

此示例很好地演示了 ESP32 偏好设置存储确实是持久的。当您检查串口监视器上的打印语句时,您可以看到计数在连续重置之间递增。这对于局部变量来说是不可能的。这只有通过偏好设置使用非易失性存储才能实现。

参考资料

广告