闪存文件系统
基础知识
对于这个开发板,闪存文件系统大小一般是4Mb。其中有1Mb是留给上传程序的,剩下3Mb是文件存储(里面含有一部分是系统文件)
故一般上传的文件总和小于2.5Mb
除了可以存放上传的程序以外,我们还可以将网页文件或者系统配置文件存放在ESP8266的闪存中
在IDE里可以设置开发板闪存系统的大小
通过程序向闪存文件系统写入信息
向NodeMCU的SPIFFS中建立名为notes.txt的文件
如果是新用的,格式化会更保险
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
| #include <FS.h> String file_name = "/taichi-maker/notes.txt"; void setup() { Serial.begin(9600); Serial.println(""); Serial.println("SPIFFS format start"); SPIFFS.format(); Serial.println("SPIFFS format finish"); if(SPIFFS.begin()){ Serial.println("SPIFFS Started."); } else { Serial.println("SPIFFS Failed to Start."); } File dataFile = SPIFFS.open(file_name, "w"); dataFile.println("Hello IOT World."); dataFile.close(); Serial.println("Finished Writing data to SPIFFS"); } void loop() { }
|
通过程序从闪存文件系统读取信息
dataFile.read()将会读取dataFile文件内容。每调用一次该含税都会返回dataFile文件中一个字符。再次调用,将会返回下一个字符。以此类推,直到dataFile结尾。通过for循环语句,程序将会依次读取dataFile文件内容,并且将文件内容逐字符输出于串口监视器中
注意此时不要再格式化了!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
if (SPIFFS.exists(file_name)){ Serial.print(file_name); Serial.println(" FOUND."); } else { Serial.print(file_name); Serial.print(" NOT FOUND."); }
File dataFile = SPIFFS.open(file_name, "r");
for(int i=0; i<dataFile.size(); i++){ Serial.print((char)dataFile.read()); }
|
通过程序向闪存文件系统文件添加信息
注意如果要对文件进行操作,比如说读取,一定要在文件open后,close前
1 2 3
| File dataFile = SPIFFS.open(file_name, "a"); dataFile.println("This is Appended Info."); dataFile.close();
|
(不知道为什么读取的时候会乱码
通过程序读取目录内容
添加信息是不会删除文件内原有信息,而是在原有信息后面添加新的信息。这与但写入操作是有所区别的。写入操作是将文件内容完全清除,重新写入新信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| String file_name = "/taichi-maker/myFile.txt"; String folder_name = "/taichi-maker";
File dataFile = SPIFFS.open(file_name, "w"); dataFile.println("Hello Taichi-Maker."); dataFile.close(); Serial.println(F("Finished Writing data to SPIFFS")); Dir dir = SPIFFS.openDir(folder_name); while (dir.next()) { Serial.println(dir.fileName()); }
|
从闪存文件系统中删除文件
用remove
1 2 3 4 5 6 7 8 9 10 11 12
|
if (SPIFFS.remove(file_name)){ Serial.print(file_name); Serial.println(" remove sucess"); } else { Serial.print(file_name); Serial.println(" remove fail"); }
|
*显示闪存文件系统信息
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
| #include <FS.h> FSInfo fs_info; void setup() { Serial.begin(9600); SPIFFS.begin(); Serial.println(""); Serial.println("SPIFFS Started."); SPIFFS.info(fs_info); Serial.print("totalBytes: "); Serial.print(fs_info.totalBytes); Serial.println(" Bytes"); Serial.print("usedBytes: "); Serial.print(fs_info.usedBytes); Serial.println(" Bytes"); Serial.print("maxPathLength: "); Serial.println(fs_info.maxPathLength); Serial.print("maxOpenFiles: "); Serial.println(fs_info.maxOpenFiles); Serial.print("blockSize: "); Serial.println(fs_info.blockSize); Serial.print("pageSize: "); Serial.println(fs_info.pageSize); } void loop() { }
|
闪存应用——ESP8266开发板搭建网页服务
关于安装闪存文件系统上传文件的插件
我用的IDE是2.3.5,自2.0后上传插件的方法就变了
(预先准备:在github下载littlefs包,然后放在C:\Users\Administrator.arduinoIDE\plugins)
上传方法:打开IDE,shift+ctrl+p,输入upload,点击下载项
一定要关闭串口监视器
upload一次就是上传一次文件
用了littlefs后,每次的命令就不是SPIFFS,而是LittleFS
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
| #include "LittleFS.h" String file_name = "/test_text.txt";
void setup() { Serial.begin(9600); if(!LittleFS.begin()){ Serial.println("An Error has occurred while mounting LittleFS"); return; } if (LittleFS.exists(file_name)){ Serial.print(file_name); Serial.println(" FOUND."); } else { Serial.print(file_name); Serial.print(" NOT FOUND."); }
File file = LittleFS.open("/test_text.txt", "r"); if(!file){ Serial.println("Failed to open file for reading"); return; } Serial.println("File Content:"); while(file.available()){ Serial.write(file.read()); } file.close(); } void loop() { }
|
在网页中加载闪存文件系统中的图片、CSS和JavaScript
这是重要的控制网页的模板
注意理解代码
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| #include <ESP8266WiFi.h> #include <ESP8266WiFiMulti.h> #include <ESP8266WebServer.h> #include <LittleFS.h>
ESP8266WiFiMulti wifiMulti;
ESP8266WebServer esp8266_server(80);
void setup() { Serial.begin(9600); Serial.println(""); wifiMulti.addAP("zzz"); wifiMulti.addAP("zzz"); Serial.println("Connecting ..."); int i = 0; while (wifiMulti.run() != WL_CONNECTED) { delay(1000); Serial.print(i++); Serial.print(' '); } Serial.println('\n'); Serial.print("Connected to "); Serial.println(WiFi.SSID()); Serial.print("IP address:\t"); Serial.println(WiFi.localIP());
if(LittleFS.begin()){ Serial.println("LittleFS Started."); } else { Serial.println("LittleFS Failed to Start."); } esp8266_server.onNotFound(handleUserRequet);
esp8266_server.begin(); Serial.println("HTTP server started"); }
void loop(void) { esp8266_server.handleClient(); }
void handleUserRequet() { String webAddress = esp8266_server.uri(); bool fileReadOK = handleFileRead(webAddress);
if (!fileReadOK){ esp8266_server.send(404, "text/plain", "404 Not Found"); } }
bool handleFileRead(String path) {
if (path.endsWith("/")) { path = "/index.html"; } String contentType = getContentType(path); if (LittleFS.exists(path)) { File file = LittleFS.open(path, "r"); esp8266_server.streamFile(file, contentType); file.close(); return true; } return false; }
String getContentType(String filename){ if(filename.endsWith(".htm")) return "text/html"; else if(filename.endsWith(".html")) return "text/html"; else if(filename.endsWith(".css")) return "text/css"; else if(filename.endsWith(".js")) return "application/javascript"; else if(filename.endsWith(".png")) return "image/png"; else if(filename.endsWith(".gif")) return "image/gif"; else if(filename.endsWith(".jpg")) return "image/jpeg"; else if(filename.endsWith(".ico")) return "image/x-icon"; else if(filename.endsWith(".xml")) return "text/xml"; else if(filename.endsWith(".pdf")) return "application/x-pdf"; else if(filename.endsWith(".zip")) return "application/x-zip"; else if(filename.endsWith(".gz")) return "application/x-gzip"; return "text/plain"; }
|
通过网页控制ESP8266开发板的引脚
使用ESP8266-NodeMCU建立一个有多个页面的网站。在LED页面中配有可控制LED点亮和熄灭的
按钮。点击首页的LED Page链接进入LED页。点击LED页按钮将控制NodeMCU的内置LED点亮和熄灭。
PS:因为抄的代码是用fs.h,所以替换时要变成LittleFS
PS:不要忘记给LED灯的引脚初始化
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 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
pinMode(LED_BUILTIN, OUTPUT);
esp8266_server.on("/LED-Control", handleLEDControl); esp8266_server.onNotFound(handleUserRequest);
void handleLEDControl(){ bool ledStatus = digitalRead(LED_BUILTIN); ledStatus == HIGH ? digitalWrite(LED_BUILTIN, LOW) : digitalWrite(LED_BUILTIN, HIGH); esp8266_server.sendHeader("Location", "/LED.html"); esp8266_server.send(303); }
void handleUserRequest() { String reqResource = esp8266_server.uri(); Serial.print("reqResource: "); Serial.println(reqResource); bool fileReadOK = handleFileRead(reqResource);
if (!fileReadOK){ esp8266_server.send(404, "text/plain", "404 Not Found"); } }
bool handleFileRead(String resource) {
if (resource.endsWith("/")) { resource = "/index.html"; } String contentType = getContentType(resource); if (LittleFS.exists(resource)) { File file = LittleFS.open(resource, "r"); esp8266_server.streamFile(file, contentType); file.close(); return true; } return false; }
String getContentType(String filename){ if(filename.endsWith(".htm")) return "text/html"; else if(filename.endsWith(".html")) return "text/html"; else if(filename.endsWith(".css")) return "text/css"; else if(filename.endsWith(".js")) return "application/javascript"; else if(filename.endsWith(".png")) return "image/png"; else if(filename.endsWith(".gif")) return "image/gif"; else if(filename.endsWith(".jpg")) return "image/jpeg"; else if(filename.endsWith(".ico")) return "image/x-icon"; else if(filename.endsWith(".xml")) return "text/xml"; else if(filename.endsWith(".pdf")) return "application/x-pdf"; else if(filename.endsWith(".zip")) return "application/x-zip"; else if(filename.endsWith(".gz")) return "application/x-gzip"; return "text/plain"; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>太极创客-零基础入门学用物联网教程</title> </head> <body> <center> <a href="http://www.taichi-maker.com" target="_blank"><img src="/img/taichi-maker.jpg" alt="太极创客"></a> <h1>ESP8266 LED 引脚控制</h1> <p><a href="LED.html">前往LED控制页面</a></p> <p>此页面用于演示如何通过网页按钮来控制ESP8266开发板引脚。</p> <p>本教程可在太极创客网站免费获取。太极创客网址: <a href="http://www.taichi-maker.com" target="_blank">www.taichi-maker.com</a> </center> </body>
</html>
|
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
|
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>太极创客-零基础入门学用物联网教程</title> </head> <body> <center> <a href="http://www.taichi-maker.com" target="_blank"><img src="/img/taichi-maker.jpg" alt="太极创客"></a> <h1>LED引脚控制</h1> <p>通过以下按键,您可以控制ESP8266开发板上的内置LED引脚</p>
<form action="LED-Control"><input type="submit" value="LED控制"> </form> <br> <form action="index.html"><input type="submit" value="返回首页"> </form>
<p>此页面用于演示如何通过网页按钮来控制ESP8266开发板引脚。</p> <p>本教程可在太极创客网站免费获取。太极创客网址: <a href="http://www.taichi-maker.com" target="_black">www.taichi-maker.com</a> </center> </body>
</html>
|
通过网页文本框控制ESP8266开发板的PWM引脚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void handleLEDControl(){
String ledPwm = esp8266_server.arg("ledPwm");
int ledPwmVal = ledPwm.toInt();
analogWrite(LED_BUILTIN, ledPwmVal);
String httpBody = "Led PWM: " + ledPwm + "<p><a href=\"/LED.html\"><-LED Page</a></p>"; esp8266_server.send(200, "text/html", httpBody); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>太极创客-零基础入门学用物联网教程</title> </head> <body> <center> <a href="http://www.taichi-maker.com" target="_blank"><img src="/img/taichi-maker.jpg" alt="太极创客"></a> <form action="/LED-Control"> <input type="text" name="ledPwm"> </br> <input type="submit" value="OK"> </form> <p>通过本页的文本框输入0 - 1023 数值来控制ESP8266开发板的LED亮度。</p> <p>本教程可在太极创客网站免费获取。太极创客网址: <a href="http://www.taichi-maker.com" target="_blank">www.taichi-maker.com</a> </center> </body>
</html>
|
通过网页将文件上传到ESP8266开发板闪存文件系统
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
| File fsUploadFile;
esp8266_server.on("/upload.html", HTTP_POST, respondOK, handleFileUpload);
void handleFileUpload(){ HTTPUpload& upload = esp8266_server.upload(); if(upload.status == UPLOAD_FILE_START){ String filename = upload.filename; if(!filename.startsWith("/")) filename = "/" + filename; Serial.println("File Name: " + filename);
fsUploadFile = LittleFS.open(filename, "w"); } else if(upload.status == UPLOAD_FILE_WRITE){ if(fsUploadFile) fsUploadFile.write(upload.buf, upload.currentSize); } else if(upload.status == UPLOAD_FILE_END){ if(fsUploadFile) { fsUploadFile.close(); Serial.println(" Size: "+ upload.totalSize); esp8266_server.sendHeader("Location","/success.html"); esp8266_server.send(303); } else { Serial.println("File upload failed"); esp8266_server.send(500, "text/plain", "500: couldn't create file"); } } }
void respondOK(){ esp8266_server.send(200); } }
|