
我個(gè)人很喜歡ESP8266這個(gè)板,主要是由于它提供了一系列價(jià)格低廉、高可用的IoT開發(fā)及接入方案。你是否知道在ESP8266的系統(tǒng)閃存可以用來存儲(chǔ)代碼甚至是文件嗎?
這個(gè)文件系統(tǒng)可以讓我們存儲(chǔ)一些變更頻率不頻繁的文件例如網(wǎng)頁、配置或者是某些固化的數(shù)據(jù)等。芯片內(nèi)置這樣的小型文件系統(tǒng)后ESP8266就相當(dāng)于是一塊Arduino+WIFI+SD擴(kuò)展板的功能了,但價(jià)格上卻只需要比Arduino低上很多。正因?yàn)榱怂覀兙湍茉诶锩嬷踩胍恍┢渌墓碳糜谥С窒馤ua或者M(jìn)icropython這樣的腳本類語言引擎以簡化嵌入式設(shè)備的編程。
它就是SPIFFs - SPI Flash Filing System!
環(huán)境配置
那怎么來使用SPIFFs呢?首先你需要在Arduino中加入對(duì)ESP8266這個(gè)板子的支持,在我以前的文章Arduino Core For ESP8266中對(duì)此已經(jīng)有所介紹。其次,你需要下載一個(gè)Arduino IDE的插件Arduino-ESP8266FS-Plugin,解壓縮至<home>/Arduino/tools/然后重啟Arduino后就會(huì)看到ESP8266 Sketch Data Upload 的菜單。
ESP8266由于有很多種不同的板子,所以在使用SPIFFS之前應(yīng)該先確認(rèn)你所用的板子的SPIFFS的大小。


Flash的結(jié)構(gòu):
以下是ESP8266的Flash基本結(jié)構(gòu):
|--------------|-------|---------------|--|--|--|--|--|
^ ^ ^ ^ ^
Sketch OTA更新 文件系統(tǒng) EEPROM WiFi config (SDK)
文件系統(tǒng)的大小依賴于Flash芯片的大小,下表為現(xiàn)時(shí)收集到的常見芯片的FLash大小:
| 主板 | Flash(bytes) | 文件系統(tǒng)(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功能之前需要在文件內(nèi)引用頭文件:
#include "FS.h"
使用SPIFFS
ESP8266FS插件其實(shí)只是在當(dāng)前項(xiàng)目目錄下創(chuàng)建了一個(gè)data目錄,我們只要將需要上傳到芯片文件系統(tǒng)的內(nèi)容放置在這個(gè) data目錄中就可以了,然后點(diǎn)擊ESP8266 Skech Data Upload Arduino IDE就會(huì)將這個(gè)目錄的文件寫入到SPIFFS中了。要注意的是文件的大小不能超過板子SPIFFS的大小,否則會(huì)上傳失敗。
我們就嘗試將一個(gè)index.html網(wǎng)頁文件放到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) {
// 在打開過程中出現(xiàn)問題f就會(huì)為空
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的文本內(nèi)容
String data = f.readString();
Serial.println(data);
//關(guān)閉文件
f.close();
}
}
else {
Serial.println("No such file found.");
}
}
}
void loop() {
// put your main code here, to run repeatedly:
}
FS的參考
SPIFFS對(duì)象
begin
SPIFFS.begin()
該方法用于掛載SPIFFS文件系統(tǒng),必須在使用SPIFFS之前就調(diào)用,一般都會(huì)在setup()過程調(diào)用。該方法如果調(diào)用成功將會(huì)返回true,否則返回false 。
format
SPIFFS.format()
格式化文件系統(tǒng)。返回true表示格式化成功。
open
SPIFFS.open(path, mode)
打開指定位置上的一個(gè)文件并返回File對(duì)象。
-
path- 文件的路徑(如:/test.text) -
mode- 文件的讀寫模式,可以為 "r", "w", "a", "r+", "w+", "a+"中的任意一個(gè),這個(gè)與C言語中訪問文件系統(tǒng)的方式是一樣的。
該方法返用成功后會(huì)返回一個(gè)File對(duì)象,否則就會(huì)返回空。
File f = SPIFFS.open("/f.txt", "w");
if (!f) {
Serial.println("file open failed");
}
exists
SPIFFS.exists(path)
檢測(cè)指定文件或目錄是否存在。
openDir
SPIFFS.openDir(path)
打開指定目錄并返回一個(gè)目錄對(duì)象實(shí)例。
remove
SPIFFS.remove(path)
刪除指定絕對(duì)路徑上的文件或目錄。
rename
SPIFFS.rename(pathFrom, pathTo)
重命名。
info
FSInfo fs_info;
SPIFFS.info(fs_info);
獲取一個(gè)文件系統(tǒng)信息結(jié)構(gòu)。
文件系統(tǒng)信息結(jié)構(gòu)
struct FSInfo {
size_t totalBytes; // 可用量
size_t usedBytes; // 已用
size_t blockSize; // 塊大小
size_t pageSize; // 頁大小
size_t maxOpenFiles; // 最大打開文件數(shù)
size_t maxPathLength; // 最大文件路徑長度
};
目錄 (Dir)
目錄對(duì)象常用于枚舉,它會(huì)提供三個(gè)方法:next(),fileName(), 和 openFile(mode)
以下例子用于枚舉指定目錄下的子目錄、文件名和文件大?。?/p>
Dir dir = SPIFFS.openDir("/data");
while (dir.next()) {
Serial.print(dir.fileName());
File f = dir.openFile("r");
Serial.println(f.size());
}
dir.next()返回真時(shí)就表示目錄枚舉完成。它的調(diào)用必須早于fileName和openFile函數(shù)。
文件對(duì)象
SPIFFS.open 和 dir.openFile 函數(shù)都可以返回一個(gè)File文件對(duì)象實(shí)例。這個(gè)對(duì)象用于處理所有的文件流,例如:readBytes, findUntil, parseInt, println。
seek
file.seek(offset, mode)
移動(dòng)文件指針。
position
file.position()
返回當(dāng)前文件指針的位置 。
size
file.size()
返回文件的大小。
name
String name = file.name();
返回文件名。
close
file.close()
關(guān)閉并釋放文件對(duì)象。
在實(shí)際的運(yùn)用場(chǎng)景中,合理地使用SPIFFS會(huì)給我們省下很多的時(shí)間甚至是生產(chǎn)成本,希望這篇短文能給你在使用ESP8266的過程中給予一些幫助。