Arduino ESP32将数据保存到NVS中

Arduino ESP32将数据保存到NVS中


该功能类似AVR单片机里面的EEPROM存储区域。

  • 关于ESP32分区表参考《分区表》

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

  • 一般默认的分区模式
# ESP-IDF Partition Table
# Name,   Type, SubType, Offset,  Size, Flags
nvs,      data, nvs,     0x9000,  0x4000,
otadata,  data, ota,     0xd000,  0x2000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000,  1M,
ota_0,    app,  ota_0,   0x110000, 1M,
ota_1,    app,  ota_1,   0x210000, 1M,

那么跟给nvs的容量就是0x4000,也就是4KB

  • 在ArduinoIDE里面有很多不同分区表的配置可选择。
    Arduino ESP32将数据保存到NVS中_第1张图片
  • 关于分区表生成,可以参考:《NVS 分区生成程序》
  • 如何查看具体位置可以看《Arduino ESP32 flash各型号分区表配置详略整理》

分区表相关的配置信息查询示例程序

/* Code gathered by Marc MERLIN  from code found
on gitter (license unknown) and in esp32-arduino's 
libraries/FFat/examples/FFat_Test/FFat_Test.ino */

#include 
#include "FFat.h"

void partloop(esp_partition_type_t part_type) {
  esp_partition_iterator_t iterator = NULL;
  const esp_partition_t *next_partition = NULL;
  iterator = esp_partition_find(part_type, ESP_PARTITION_SUBTYPE_ANY, NULL);
  while (iterator) {
     next_partition = esp_partition_get(iterator);
     if (next_partition != NULL) {
        Serial.printf("partition addr: 0x%06x; size: 0x%06x; label: %s\n", next_partition->address, next_partition->size, next_partition->label);  
     iterator = esp_partition_next(iterator);
    }
  }
}
 
void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\r\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("- failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println(" - not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("\tSIZE: ");
            Serial.println(file.size());
        }
  file.close();
        file = root.openNextFile();
    }
}

void setup(){
    Serial.begin(115200);
   
    Serial.setDebugOutput(true);

    Serial.println("Partition list:");
    partloop(ESP_PARTITION_TYPE_APP);
    partloop(ESP_PARTITION_TYPE_DATA);

    Serial.println("\n\nTrying to mount ffat partition if present");
 
    // Only allow one file to be open at a time instead of 10, saving 9x4 - 36KB of RAM
    if(!FFat.begin( 0, "", 1 )){
        Serial.println("FFat Mount Failed");
        return;
    }
 
    Serial.println("File system mounted");
    Serial.printf("Total space: %10lu\n", FFat.totalBytes());
    Serial.printf("Free space:  %10lu\n\n", FFat.freeBytes());
    listDir(FFat, "/", 5);
}
 
void loop(){}

Arduino ESP32将数据保存到NVS中_第2张图片

我们在有效数据读取和存储方面,我们更多的关注是如何去利用它。

ArduinoIDE ESP32固件包自带的有关示例

Preferences

在这里插入图片描述

Preferences.h头文件涵盖的所支持的数据类型API函数:

存放不同类型数据的API函数
  • Char putChar(const char* key, int8_t value)
  • Unsigned Char putUChar(const char* key, int8_t value)
  • Short putShort(const char* key, int16_t value)
  • Unsigned Short putUShort(const char* key, uint16_t value)
  • Int putInt(const char* key, int32_t value)
  • Unsigned Int putUInt(const char* key, uint32_t value)
  • Long putLong(const char* key, int32_t value)
  • Unsigned Long putULong(const char* key, uint32_t value)
  • Long64 putLong64(const char* key, int64_t value)
  • Unsigned Long64 putULong64(const char* key, uint64_t value)
  • Float putFloat(const char* key, const float_t value)
  • Double putDouble(const char* key, const double_t value)
  • Bool putBool(const char* key, const bool value)
  • String putString(const char* key, const String value)
  • Bytes putBytes(const char* key, const void* value, size_t len)
读取不同类型数据的API函数
  • Char getChar(const char* key, const int8_t defaultValue)
  • Unsigned Char getUChar(const char* key, const uint8_t defaultValue)
  • Short getShort(const char* key, const int16_t defaultValue
  • Unsigned Short getUShort(const char* key, const uint16_t defaultValue)
  • Int getInt(const char* key, const int32_t defaultValue)
  • Unsigned Int getUInt(const char* key, const uint32_t defaultValue)
  • Long getLong(const char* key, const int32_t defaultValue)
  • Unsigned Long getULong(const char* key, const uint32_t defaultValue)
  • Long64 getLong64(const char* key, const int64_t defaultValue)
  • Unsigned Long64 gettULong64(const char* key, const uint64_t defaultValue)
  • Float getFloat(const char* key, const float_t defaultValue)
  • Double getDouble(const char* key, const double_t defaultValue)
  • Bool getBool(const char* key, const bool defaultValue)
  • String getString(const char* key, const String defaultValue)
  • String getString(const char* key, char* value, const size_t maxLen)
  • Bytes getBytes(const char* key, void * buf, size_t maxLen)

不管是存储还是读取函数,都至少包含2个参数:键名和键值,我们从上面不难发现,不管是获取键值还是存放键值,它们的第二个参数的返回值和操作的对象都是相同的。

数据操作相关的API函数
  • clear():清除打开的首选项中的所有键。
  • freeEntries():获取剩余可用空间.
  • remove():删除单独一个键值对象。与clear()不同,
  • end():关闭命名空间(namespace)
  • bool begin(const char * name, bool readOnly=false, const char* partition_label=NULL);:第一个参数是必填的,命名空间,第二个参数是默认初始化是只读模式,第三个参数为空,不填。

存储键值到NVS区域示例

#include 

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

    Preferences prefs;
    prefs.begin("mynamespace");

    Serial.println(prefs.freeEntries());//查询剩余空间

    prefs.putString("wifiname", "MERCURY_D268G");
    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() {}

你可能感兴趣的:(Arduino,ESP32,入门实例教程,Arduino,ESP32)