zoukankan      html  css  js  c++  java
  • ESP32-EEPROM存储

    EEPROM前言

      在EPS32中已经将EEPROM弃用。对于ESP32上的新应用程序,建议使用NVS为首选项。提供EEPROM是为了向后兼容现有的Arduino应用程序。EEPROM是使用NVS中的单个blob实现的,因此它是容器(Flash)中的容器(NVS)(弟中弟)。因此,它不会是一种高性能存储方法。首选项将直接使用nvs,并将每个条目存储为其中的单个对象。所以现在的EEPROM也仅是在函数功能上向后兼容,实际储存方式已经完全变了,这需要我们在实际应用中注意。NVS小知识链接

    主要API介绍

        bool begin(size_t size);   // 开启一块分区访问存储
        uint8_t read(int address);  // 读取指定地址数据
        void write(int address, uint8_t val); // 在指定地址保存数据
        uint16_t length();   // 获取申请的分区大小
        bool commit();  // 将数据从缓存区存入flash中
        void end();  // 结束访问

      在实际应用中主要思路是,先申明begin(想要保存的数据大小),再利用write(地址偏移,单个字符数据0-255),当所有数据通过write写完后,一定要记得中commit()提交,使数据从暂存区保存到flash中,实现掉电保护。read的使用直接利用地址偏移可以直接读出数据。

    例子1(随机数的保存)

     1 #include <Arduino.h>
     2 #include "EEPROM.h"
     3 
     4 int addr = 0;
     5 #define EEPROM_SIZE 64
     6 void setup()
     7 {
     8   Serial.begin(9600);
     9   Serial.println("start...");
    10   if (!EEPROM.begin(EEPROM_SIZE)) // 申请存储空间
    11   {
    12     Serial.println("failed to initialise EEPROM"); delay(1000000);
    13   }
    14   Serial.println(" bytes read from Flash . Values are:");
    15   for (int i = 0; i < EEPROM_SIZE; i++)
    16   {
    17     Serial.print(byte(EEPROM.read(i))); Serial.print(" "); //直接读出数据
    18   }
    19   Serial.println();
    20   Serial.println("writing random n. in memory");
    21 }
    22 
    23 void loop()
    24 {
    25   int val = byte(random(10020));
    26   EEPROM.write(addr, val);
    27   Serial.print(val); Serial.print(" ");
    28   addr = addr + 1;
    29   if (addr == EEPROM_SIZE)
    30   {
    31     Serial.println();
    32     addr = 0;
    33     EEPROM.commit();
    34     Serial.print(EEPROM_SIZE);
    35     Serial.println(" bytes written on Flash . Values are:");
    36     for (int i = 0; i < EEPROM_SIZE; i++)
    37     {
    38       Serial.print(byte(EEPROM.read(i))); Serial.print(" ");
    39     }
    40     Serial.println(); Serial.println("----------------------------------");
    41   }
    42   delay(100);
    43 }

    特殊API直接调用

      前面的写入与读取只能是单字符的读取与写入,官方为了方便调用,还提供了对于各数据类型的支持:

    uint8_t readByte(int address);
        int8_t readChar(int address);
        uint8_t readUChar(int address);
        int16_t readShort(int address);
        uint16_t readUShort(int address);
        int32_t readInt(int address);
        uint32_t readUInt(int address);
        int32_t readLong(int address);
        uint32_t readULong(int address);
        int64_t readLong64(int address);
        uint64_t readULong64(int address);
        float_t readFloat(int address);
        double_t readDouble(int address);
        bool readBool(int address);
        size_t readString(int address, char* value, size_t maxLen);
        String readString(int address);
        size_t readBytes(int address, void * value, size_t maxLen);
        template <class T> T readAll (int address, T &);
    
        size_t writeByte(int address, uint8_t value);
        size_t writeChar(int address, int8_t value);
        size_t writeUChar(int address, uint8_t value);
        size_t writeShort(int address, int16_t value);
        size_t writeUShort(int address, uint16_t value);
        size_t writeInt(int address, int32_t value);
        size_t writeUInt(int address, uint32_t value);
        size_t writeLong(int address, int32_t value);
        size_t writeULong(int address, uint32_t value);
        size_t writeLong64(int address, int64_t value);
        size_t writeULong64(int address, uint64_t value);
        size_t writeFloat(int address, float_t value);
        size_t writeDouble(int address, double_t value);
        size_t writeBool(int address, bool value);
        size_t writeString(int address, const char* value);
        size_t writeString(int address, String value);
        size_t writeBytes(int address, const void* value, size_t len);
        template <class T> T writeAll (int address, const T &);
    View Code

    例子2(各数据类型):

      1 #include <Arduino.h>
      2 
      3 #include "EEPROM.h"
      4 
      5 void setup() {
      6   // put your setup code here, to run once:
      7   Serial.begin(9600);
      8   Serial.println("
    Testing EEPROM Library
    ");
      9   if (!EEPROM.begin(1000)) {
     10     Serial.println("Failed to initialise EEPROM");
     11     Serial.println("Restarting...");
     12     delay(1000);
     13     ESP.restart();
     14   }
     15 
     16   int address = 0;
     17 
     18   EEPROM.writeByte(address, -128);                  // -2^7
     19   address += sizeof(byte);
     20 
     21   EEPROM.writeChar(address, 'A');                   // Same as writyByte and readByte
     22   address += sizeof(char);
     23 
     24   EEPROM.writeUChar(address, 255);                  // 2^8 - 1
     25   address += sizeof(unsigned char);
     26 
     27   EEPROM.writeShort(address, -32768);               // -2^15
     28   address += sizeof(short);
     29 
     30   EEPROM.writeUShort(address, 65535);               // 2^16 - 1
     31   address += sizeof(unsigned short);
     32 
     33   EEPROM.writeInt(address, -2147483648);            // -2^31
     34   address += sizeof(int);
     35 
     36   EEPROM.writeUInt(address, 4294967295);            // 2^32 - 1
     37   address += sizeof(unsigned int);
     38 
     39   EEPROM.writeLong(address, -2147483648);           // Same as writeInt and readInt
     40   address += sizeof(long);
     41 
     42   EEPROM.writeULong(address, 4294967295);           // Same as writeUInt and readUInt
     43   address += sizeof(unsigned long);
     44 
     45   int64_t value = -1223372036854775808LL;             // -2^63
     46   EEPROM.writeLong64(address, value);
     47   address += sizeof(int64_t);
     48 
     49   uint64_t  Value = 18446744073709551615ULL;           // 2^64 - 1
     50   EEPROM.writeULong64(address, Value);
     51   address += sizeof(uint64_t);
     52 
     53   EEPROM.writeFloat(address, 1234.1234);
     54   address += sizeof(float);
     55 
     56   EEPROM.writeDouble(address, 123456789.123456789);
     57   address += sizeof(double);
     58 
     59   EEPROM.writeBool(address, true);
     60   address += sizeof(bool);
     61 
     62   String sentence = "I love ESP32.";
     63   EEPROM.writeString(address, sentence);
     64   address += sentence.length() + 1;
     65 
     66   char gratitude[21] = "Thank You Espressif!";
     67   EEPROM.writeString(address, gratitude);
     68   address += 21;
     69 
     70   // See also the general purpose writeBytes() and readBytes() for BLOB in EEPROM library
     71   EEPROM.commit();
     72   address = 0;
     73   
     74   Serial.println(EEPROM.readByte(address));
     75   address += sizeof(byte);
     76 
     77   Serial.println((char)EEPROM.readChar(address));
     78   address += sizeof(char);
     79 
     80   Serial.println(EEPROM.readUChar(address));
     81   address += sizeof(unsigned char);
     82 
     83   Serial.println(EEPROM.readShort(address));
     84   address += sizeof(short);
     85 
     86   Serial.println(EEPROM.readUShort(address));
     87   address += sizeof(unsigned short);
     88 
     89   Serial.println(EEPROM.readInt(address));
     90   address += sizeof(int);
     91 
     92   Serial.println(EEPROM.readUInt(address));
     93   address += sizeof(unsigned int);
     94 
     95   Serial.println(EEPROM.readLong(address));
     96   address += sizeof(long);
     97 
     98   Serial.println(EEPROM.readULong(address));
     99   address += sizeof(unsigned long);
    100 
    101   value = 0;
    102   value = EEPROM.readLong64(value);
    103   Serial.printf("0x%08X", (uint32_t)(value >> 32)); // Print High 4 bytes in HEX
    104   Serial.printf("%08X
    ", (uint32_t)value);         // Print Low 4 bytes in HEX
    105   address += sizeof(int64_t);
    106 
    107   Value = 0;                                        // Clear Value
    108   Value = EEPROM.readULong64(Value);
    109   Serial.printf("0x%08X", (uint32_t)(Value >> 32)); // Print High 4 bytes in HEX
    110   Serial.printf("%08X
    ", (uint32_t)Value);         // Print Low 4 bytes in HEX
    111   address += sizeof(uint64_t);
    112 
    113   Serial.println(EEPROM.readFloat(address), 4);
    114   address += sizeof(float);
    115 
    116   Serial.println(EEPROM.readDouble(address), 8);
    117   address += sizeof(double);
    118 
    119   Serial.println(EEPROM.readBool(address));
    120   address += sizeof(bool);
    121 
    122   Serial.println(EEPROM.readString(address));
    123   address += sentence.length() + 1;
    124 
    125   Serial.println(EEPROM.readString(address));
    126   address += 21;
    127 }
    128 
    129 void loop() {
    130   // put your main code here, to run repeatedly:
    131 
    132 }
    View Code

    初步展现底层:

      前面提到过,在目前的ESP32中并没有EEPROM,而是利用NVS模拟出来的,仅是了程序的向后兼容性,而前面的程序中的EEPROM储存空间也仅仅是NVS的单个blob实现的,也就是说我们可以创造多个EEPROM来存储数据。

      在EEPROMClass类中,有三个:

            EEPROMClass(uint32_t sector);
            EEPROMClass(const char* name, uint32_t user_defined_size);
            EEPROMClass(void);

      程序在默认状态下使用的是最后一个:extern EEPROMClass EEPROM;而从定义中,我们可知这个类是可以指定名称与大小的。

      且提供了函数get与put用于保存数据与读取:

        template<typename T>
        T &get(int address, T &t) {
          if (address < 0 || address + sizeof(T) > _size)
            return t;
    
          memcpy((uint8_t*) &t, _data + address, sizeof(T));
          return t;
        }
    
        template<typename T>
        const T &put(int address, const T &t) {
          if (address < 0 || address + sizeof(T) > _size)
            return t;
    
          memcpy(_data + address, (const uint8_t*) &t, sizeof(T));
          _dirty = true;
          return t;
        }

    例子(对EEPROMClass的调用):

    #include <Arduino.h>
    #include "EEPROM.h"
    
    // Instantiate eeprom objects with parameter/argument names and sizes
    EEPROMClass  NAMES("eeprom0", 0x500);
    EEPROMClass  HEIGHT("eeprom1", 0x200);
    EEPROMClass  AGE("eeprom2", 0x100);
    
    void setup() {
      Serial.begin(9600);
      Serial.println("Testing EEPROMClass
    ");
      if (!NAMES.begin(NAMES.length())) {
        Serial.println("Failed to initialise NAMES");
        Serial.println("Restarting...");
        delay(1000);
        ESP.restart();
      }
      if (!HEIGHT.begin(HEIGHT.length())) {
        Serial.println("Failed to initialise HEIGHT");
        Serial.println("Restarting...");
        delay(1000);
        ESP.restart();
      }
      if (!AGE.begin(AGE.length())) {
        Serial.println("Failed to initialise AGE");
        Serial.println("Restarting...");
        delay(1000);
        ESP.restart();
      }
    
      const char* name = "Teo Swee Ann";
      char rname[32];
      double height = 5.8;
      uint32_t age = 47;
    
      // Write: Variables ---> EEPROM stores
      NAMES.put(0, name);
      HEIGHT.put(0, height);
      AGE.put(0, age);
      Serial.print("name: ");   Serial.println(name);
      Serial.print("height: "); Serial.println(height);
      Serial.print("age: ");    Serial.println(age);
      Serial.println("------------------------------------
    ");
    
      // Clear variables
      name = '';
      height = 0;
      age = 0;
      Serial.print("name: ");   Serial.println(name);
      Serial.print("height: "); Serial.println(height);
      Serial.print("age: ");    Serial.println(age);
      Serial.println("------------------------------------
    ");
    
      // Read: Variables <--- EEPROM stores
      NAMES.get(0, rname);
      HEIGHT.get(0, height);
      AGE.get(0, age);
      Serial.print("name: ");   Serial.println(rname);
      Serial.print("height: "); Serial.println(height);
      Serial.print("age: ");    Serial.println(age);
      
      Serial.println("Done!");
    }
    
    void loop() {
      delay(0xFFFFFFFF);
    }
  • 相关阅读:
    Web网页数据抽取软件的设计与实现
    以Groovy的方式更稳定地解析HTML(转载)
    HTML 资讯汲取(上篇) 使用 JDOM 、 TagSoup 及 XPath
    html解析
    HTML 資訊汲取(下篇) TagSoup 輸出 namespace 問題的解決方案
    国外免费主机空间
    ASP.NET获取客户端IP地址、系统版本、浏览器版本
    阁下莫非就是当年华山论剑武功独步天下罕有其匹号称一朵梨花压海棠的少林寺智障大师收养的小沙弥低能的爱犬旺财踩扁的蟑螂小强曾滚过的一个粪球?
    html中table里的col标签
    Visual Studio 2010 中的 TODO
  • 原文地址:https://www.cnblogs.com/zy-cnblogs/p/13299474.html
Copyright © 2011-2022 走看看