• Arduino框架下对ESP32 NVS非易失性存储解读以及应用示例


    Arduino框架下对ESP32 NVS非易失性存储解读以及应用示例


    NVS非易失性存储库介绍

    非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。本文档将详细介绍 NVS 常用的一些概念。

    • 引用:https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/storage/nvs_flash.html

    NVS 最适合存储一些较小的数据,而非字符串或二进制大对象 (BLOB) 等较大的数据。如需存储较大的 BLOB 或者字符串,请考虑使用基于磨损均衡库的 FAT 文件系统。

    Arduino框架下,NVS区域在分区表上的体现:

    分区表配置文件位置:C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.4\tools\partitions

    在这里插入图片描述

    • Arduino IDE分区表配置信息选项:
      在这里插入图片描述

    NVS区域具体在每一份分区表当中的体现

    app13Mfat3M.csv为例:

    在这里插入图片描述

    在Arduino环境下,不同的分区表默认配置的NVS容量都是5000 Byte(字节)

    NVS 存储对象

    像用户的一般数据存储例如wifi信息,eeprom库也是使用了其中的一部分。

    用户如何使用NVS 来存储数据

    相关头文件位置:C:\Users\Administrator\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.4\libraries\Preferences\src

    在这里插入图片描述

    • 获取数据函数

    在这里插入图片描述

            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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 读取数据函数
            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);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 数据操作函数
     bool clear();
     bool remove(const char * key);
    
    • 1
    • 2

    操作流程

    在这里插入图片描述

    键值对使用注意事项

    • NVS 的操作对象为键值对,其中键是 ASCII 字符串,当前支持的最大键长为 15 个字符。(键的名字不要取过长的字符串名)
    • 在同一个命名空间(NameSpace)当中,键名不能有重复。

    示例程序

    本示例展示的是对结构体数据对象进行存储,比起使用eeprom库来实现,在操作上来讲要简单的多。

    /*
    This example shows how to use Preferences (nvs) to store a
    structure.  Note that the maximum size of a putBytes is 496K
    or 97% of the nvs partition size.  nvs has signifcant overhead,
    so should not be used for data that will change often.
    */ 
    #include //引入头文件
    Preferences prefs;
    
    typedef struct {
      uint8_t hour;
      uint8_t minute;
      uint8_t setting1;
      uint8_t setting2;
    } schedule_t;
    
    void setup() {
      Serial.begin(115200);
      delay(2000);
      while(!Serial);
      prefs.begin("schedule"); // use "schedule" namespace
      Serial.println(prefs.freeEntries());//获取该"schedule" 命名空间大小:414
      uint8_t content[] = {9, 30, 235, 255, 20, 15, 0, 1}; // two entries
      prefs.putBytes("schedule", content, sizeof(content));//将数组存储进"schedule"命名的空间
      size_t schLen = prefs.getBytesLength("schedule");
      char buffer[schLen]; // prepare a buffer for the data
      prefs.getBytes("schedule", buffer, schLen);//获取"schedule"命名的空间数据的大小
      if (schLen % sizeof(schedule_t)) { // 对存储的数据进行校验
        log_e("Data is not correct size!");
        return;
      }
      schedule_t *schedule = (schedule_t *) buffer; // 用结构体指针指向buffer数组名,将数组成员赋值给结构体成员变量
      Serial.printf("%02d:%02d %d/%d\n", 
        schedule[1].hour, schedule[1].minute,
        schedule[1].setting1, schedule[1].setting2);//20:15 0/1
      
      Serial.printf("%02d:%02d %d/%d\n", 
        schedule[0].hour, schedule[0].minute,
        schedule[0].setting1, schedule[0].setting2);//09:30 235/255
         
      schedule[2] = {8, 30, 20, 21}; // add a third entry (unsafely)
      
    // force the struct array into a byte array
      prefs.putBytes("schedule", schedule, 3*sizeof(schedule_t)); 
      schLen = prefs.getBytesLength("schedule");
      char buffer2[schLen];
      prefs.getBytes("schedule", buffer2, schLen);
      for (int x=0; x<schLen; x++) Serial.printf("%02X ", buffer[x]);//09 1E EB FF 14 0F 00 01 08 1E 14 15
      Serial.println(); 
    }
    
    void loop() {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 串口打印信息
      在这里插入图片描述
  • 相关阅读:
    Qt 4.8.6 的下载与安装
    慢慢欣赏linux 进程unattended-upgr CPU占用率过高定位
    论文笔记: 全波形反演的无监督学习: 将 CNN 与偏微分方程做成一个环
    使用c#将aj-report桌面化:3.C#操作java
    为OneFlow添加新的前端语言
    【深度思考】如何优雅的实现脱敏?
    Redis学习记录------Redis6持久化操作(十)
    666666666666666
    Serverless 数仓技术与挑战 - 张雁飞|3306π
    Java NIO,Selector机制源码分析
  • 原文地址:https://blog.csdn.net/weixin_42880082/article/details/126130326