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 |
1M | 64k, 128k, 256k, 512k | |
2M | ||
4M | 3M | |
Adafruit HUZZAH | 1M, 3M | |
NodeMCU 0.9 | ||
NodeMCU 1.0 | ||
Olimex MOD-WIFI-ESP8266(-DEV) | ||
SparkFun Thing | ||
SweetPea ESP-210 | ||
WeMos D1 & D1 mini |
注:在使用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
-
- 檔案的讀寫模式,可以為 "r", "w", "a", "r+", "w+", "a+"中的任意一個,這個與C言語中通路檔案系統的方式是一樣的。mode
該方法返用成功後會傳回一個
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()
傳回真時就表示目錄枚舉完成。它的調用必須早于
fileName
和
openFile
函數。
檔案對象
SPIFFS.open
dir.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的過程中給予一些幫助。
ESP8266 Core 參考