SPIFFS

我个人很喜欢ESP8266这个板,主要是由于它提供了一系列价格低廉、高可用的IoT开发及接入方案。你是否知道在ESP8266的系统闪存可以用来存储代码甚至是文件吗?

这个文件系统可以让我们存储一些变更频率不频繁的文件例如网页、配置或者是某些固化的数据等。芯片内置这样的小型文件系统后ESP8266就相当于是一块Arduino+WIFI+SD扩展板的功能了,但价格上却只需要比Arduino低上很多。正因为了它我们就能在里面植入一些其它的固件用于支持像Lua或者Micropython这样的脚本类语言引擎以简化嵌入式设备的编程。

它就是SPIFFs - SPI Flash Filing System!

环境配置

那怎么来使用SPIFFs呢?首先你需要在Arduino中加入对ESP8266这个板子的支持,在我以前的文章Arduino Core For ESP8266中对此已经有所介绍。其次,你需要下载一个Arduino IDE的插件Arduino-ESP8266FS-Plugin,解压缩至<home>/Arduino/tools/然后重启Arduino后就会看到ESP8266 Sketch Data Upload 的菜单。

ESP8266由于有很多种不同的板子,所以在使用SPIFFS之前应该先确认你所用的板子的SPIFFS的大小。

 
目录
 
Arduino IDE 插件

Flash的结构:

以下是ESP8266的Flash基本结构:

|--------------|-------|---------------|--|--|--|--|--|
^              ^       ^               ^     ^
      Sketch    OTA更新   文件系统   EEPROM  WiFi config (SDK)

文件系统的大小依赖于Flash芯片的大小,下表为现时收集到的常见芯片的FLash大小:

主板Flash(bytes)文件系统(bytes)
Generic module 512k 64k
Generic module 1M 64k, 128k, 256k, 512k
Generic module 2M 1M
Generic module 4M 3M
Adafruit HUZZAH 4M 1M, 3M
NodeMCU 0.9 4M 1M, 3M
NodeMCU 1.0 4M 1M, 3M
Olimex MOD-WIFI-ESP8266(-DEV) 2M 1M
SparkFun Thing 512k 64k
SweetPea ESP-210 4M 1M, 3M
WeMos D1 & D1 mini 4M 1M, 3M

注:在使用SPIFFS功能之前需要在文件内引用头文件:
#include "FS.h"

使用SPIFFS

ESP8266FS插件其实只是在当前项目目录下创建了一个data目录,我们只要将需要上传到芯片文件系统的内容放置在这个 data目录中就可以了,然后点击ESP8266 Skech Data Upload Arduino IDE就会将这个目录的文件写入到SPIFFS中了。要注意的是文件的大小不能超过板子SPIFFS的大小,否则会上传失败。

我们就尝试将一个index.html网页文件放到data目录,然后将其上传到ESP8266中,接下来用以下的代码将SPIFFS中的index.html读出来:


#include"FS.h"

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

  bool ok = SPIFFS.begin();
  if (ok) {
    Serial.println("ok");
    //检查文件是否存在
    bool exist = SPIFFS.exists("/index.html");

    if (exist) {
      Serial.println("The file exists!"); 

      File f = SPIFFS.open("/index.html", "r");
      if (!f) {
        // 在打开过程中出现问题f就会为空
        Serial.println("Some thing went wrong trying to open the file...");
      }
      else {
        int s = f.size();
        Serial.printf("Size=%d\r\n", s);

        //读取index.html的文本内容
        String data = f.readString();
        Serial.println(data);

        //关闭文件
        f.close();
      }
    }
    else {
      Serial.println("No such file found.");
    }
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

FS的参考

SPIFFS对象

begin

SPIFFS.begin()

该方法用于挂载SPIFFS文件系统,必须在使用SPIFFS之前就调用,一般都会在setup()过程调用。该方法如果调用成功将会返回true,否则返回false

format

SPIFFS.format()

格式化文件系统。返回true表示格式化成功。

open

SPIFFS.open(path, mode)

打开指定位置上的一个文件并返回File对象。

  • path - 文件的路径(如:/test.text)
  • mode - 文件的读写模式,可以为 "r", "w", "a", "r+", "w+", "a+"中的任意一个,这个与C言语中访问文件系统的方式是一样的。

该方法返用成功后会返回一个File对象,否则就会返回空。

File f = SPIFFS.open("/f.txt", "w");
if (!f) {
    Serial.println("file open failed");
}

exists

SPIFFS.exists(path)

检测指定文件或目录是否存在。

openDir

SPIFFS.openDir(path)

打开指定目录并返回一个目录对象实例。

remove

SPIFFS.remove(path)

删除指定绝对路径上的文件或目录。

rename

SPIFFS.rename(pathFrom, pathTo)

重命名。

info

FSInfo fs_info;
SPIFFS.info(fs_info);

获取一个文件系统信息结构。

文件系统信息结构

struct FSInfo {
    size_t totalBytes;   // 可用量
    size_t usedBytes;  // 已用
    size_t blockSize;   // 块大小
    size_t pageSize;  // 页大小
    size_t maxOpenFiles; // 最大打开文件数
    size_t maxPathLength; // 最大文件路径长度
};

目录 (Dir)

目录对象常用于枚举,它会提供三个方法:next(),fileName(), 和 openFile(mode)

以下例子用于枚举指定目录下的子目录、文件名和文件大小:

Dir dir = SPIFFS.openDir("/data");
while (dir.next()) {
    Serial.print(dir.fileName());
    File f = dir.openFile("r");
    Serial.println(f.size());
}

dir.next()返回真时就表示目录枚举完成。它的调用必须早于fileNameopenFile函数。

文件对象

SPIFFS.opendir.openFile 函数都可以返回一个File文件对象实例。这个对象用于处理所有的文件流,例如:readBytes, findUntil, parseInt, println

seek

file.seek(offset, mode)

移动文件指针。

position

file.position()

返回当前文件指针的位置 。

size

file.size()

返回文件的大小。

name

String name = file.name();

返回文件名。

close

file.close()

关闭并释放文件对象。

在实际的运用场景中,合理地使用SPIFFS会给我们省下很多的时间甚至是生产成本,希望这篇短文能给你在使用ESP8266的过程中给予一些帮助。



作者:梁睿坤
链接:https://www.jianshu.com/p/014bcae94c8b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted on 2020-01-20 15:17  孤独斗士  阅读(1968)  评论(0编辑  收藏  举报