首页
NodeMcu
NodeMcu_ESP8266开发板--TCP Server
NodeMcu_ESP8266简介
NodeMcu_温湿度传感器(DHT11)的使用
esp8266+DHT11温湿传感器 制作web室内温度计
ESP8266NodeMcu网页控制四个LED灯
NodeMcu用网页上传图片来驱动1.44寸TFT屏幕
esp8266使用1.44寸tft屏Arduino模块示例程序
1.44寸TFT屏ST7735使用方法
NodeMcu_ESP8266编程
NodeMcu环境监控+远程控制
NodeMcu实现网页远程控制+温湿度显示
NodeMcu网页控制+温湿度显示+TFT
NodeMcu、ESP8266、ESP32区别
本文档由 内网文摘 发布,转载请注明出处
-
+
首页
NodeMcu用网页上传图片来驱动1.44寸TFT屏幕
利用ESP8266的3m spiffs+wifi,通过web上传图片到tft彩屏显示。 #### 效果图 ![](/media/202110/2021-10-28_135943.png) #### 工作流程 8266连接路由器-->8266建立web服务器-->电脑访问web页面-->上传图片-->保存图片到flash-->读取图片数据-->发送个给tft显示 #### 准备工作 安装arduino ide esp8266插件(使用arduino ide开发8266)。 加载附件中的库文件到ide目录中。(ST7735S库略微修改过给8266使用)。 下图中选中的两个文件夹放到Arduino IDE安装目录的libraries文件夹下,然后重启ArduinoIDE软件即可。 ![](/media/202110/2021-10-28_140815.png) - ESP8266 *1 - 1.44"TFT彩屏 *1 (驱动IC:ST7735) - 杜邦线若干 #### 接线图 ![](/media/202110/2021-10-28_134627.png) | 标号 | PIN | ESP8266开发板对应的接线引脚 | 引脚说明 | | --- | --- | --- | --- | | 1 | VCC | 3V | 电源正 | | 2 | GND | G | 电源地 | | 3 | GND | - | 电源地 | | 4 | NC | - | 无定义,保留,不需要接线 | | 5 | NC | - | 无定义,保留,不需要接线 | | 6 | LED | D4 | LCD背光控制信号(如不需要控制,请接3.3V) | | 7 | CLK | D5 | LCD SPI总线时钟引脚 | | 8 | SDI | D7 | LCD SPI总线数据引脚 | | 9 | RS | D3 | LCD寄存器/数据选择控制引脚 | | 10 | RST | D2 | LCD复位控制引脚 | | 11 | CS | D1 | LCD片选控制引脚 | #### 烧录源码 烧录完成后,打开串口监视器等待8266连接路由器,值得注意的是如果这片8266第一次使用spiffs可能需要1-2分钟的格式化时间。 待8266正常工作完成后,打开串口监视器中查看ip地址。 浏览器中打开ip地址,选择需要上传显示的图片,本程序只做了显示bmp格式的图片,所以上传的文件附件必须为bmp格式并且分辨率为128*128,24位 #### 源码 ```cpp #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #include <FS.h> #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_ST7735.h> // Hardware-specific library #include <SPI.h> #define TFT_CS D1 // Chip select line for TFT display #define TFT_RST D2 // Reset line for TFT (or see below...) #define TFT_DC D3 // Data/command line for TFT (对应我的tft显示屏的RS引脚) //wifi配置 const char* ssid = "wifiname"; const char* password = "localnetwork.cn"; const char* host = "esp8266fs"; // const char mainPageString[] PROGMEM = "<!DOCTYPE html>\r\n\ <html>\r\n\ <head>\r\n\ <meta http-equiv='Content-type' content='text/html; charset=utf-8'>\r\n\ <title>ESP Monitor</title>\r\n\ </head>\r\n\ <body>\r\n\ <img src='/logo.bmp' width='128' height='128' />\r\n\ <form method='POST' action='/' enctype='multipart/form-data'>\r\n\ <input type='file' name='update' id='update'><input type='submit' value='提交'></form>\r\n\ 文件格式必须为bmp,24位深,本示例使用的屏幕为1.44寸TFT,分辨率128*128,ic:ST7735\r\n\ </body>\r\n\ </html>"; //监听80端口 ESP8266WebServer server(80); Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); File fsUploadFile; #define BUFFPIXEL 20 // These read 16- and 32-bit types from the SD card file. // BMP data is stored little-endian, Arduino is little-endian too. // May need to reverse subscript order if porting elsewhere. uint16_t read16(File f) { uint16_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); // MSB return result; } uint32_t read32(File f) { uint32_t result; ((uint8_t *)&result)[0] = f.read(); // LSB ((uint8_t *)&result)[1] = f.read(); ((uint8_t *)&result)[2] = f.read(); ((uint8_t *)&result)[3] = f.read(); // MSB return result; } void bmpDraw(char *filename, uint8_t x, uint8_t y) { File bmpFile; int bmpWidth, bmpHeight; // W+H in pixels uint8_t bmpDepth; // Bit depth (currently must be 24) uint32_t bmpImageoffset; // Start of image data in file uint32_t rowSize; // Not always = bmpWidth; may have padding uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel) uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer boolean goodBmp = false; // Set to true on valid header parse boolean flip = true; // BMP is stored bottom-to-top int w, h, row, col; uint8_t r, g, b; uint32_t pos = 0, startTime = millis(); if((x >= tft.width()) || (y >= tft.height())) return; Serial.println(); Serial.print("Loading image '"); Serial.print(filename); Serial.println('\''); bmpFile = SPIFFS.open(filename,"r"); // Open requested file on SD card if (!bmpFile) { Serial.print("File not found"); return; } // Parse BMP header if(read16(bmpFile) == 0x4D42) { // BMP signature Serial.print("File size: "); Serial.println(read32(bmpFile)); (void)read32(bmpFile); // Read & ignore creator bytes bmpImageoffset = read32(bmpFile); // Start of image data Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC); // Read DIB header Serial.print("Header size: "); Serial.println(read32(bmpFile)); bmpWidth = read32(bmpFile); bmpHeight = read32(bmpFile); if(read16(bmpFile) == 1) { // # planes -- must be '1' bmpDepth = read16(bmpFile); // bits per pixel Serial.print("Bit Depth: "); Serial.println(bmpDepth); if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed goodBmp = true; // Supported BMP format -- proceed! Serial.print("Image size: "); Serial.print(bmpWidth); Serial.print('x'); Serial.println(bmpHeight); // BMP rows are padded (if needed) to 4-byte boundary rowSize = (bmpWidth * 3 + 3) & ~3; // If bmpHeight is negative, image is in top-down order. // This is not canon but has been observed in the wild. if(bmpHeight < 0) { bmpHeight = -bmpHeight; flip = false; } // Crop area to be loaded w = bmpWidth; h = bmpHeight; if((x+w-1) >= tft.width()) w = tft.width() - x; if((y+h-1) >= tft.height()) h = tft.height() - y; // Set TFT address window to clipped image bounds tft.setAddrWindow(x, y, x+w-1, y+h-1); for (row=0; row<h; row++) { // For each scanline... // Seek to start of scan line. It might seem labor- // intensive to be doing this on every line, but this // method covers a lot of gritty details like cropping // and scanline padding. Also, the seek only takes // place if the file position actually needs to change // (avoids a lot of cluster math in SD library). if(flip) // Bitmap is stored bottom-to-top order (normal BMP) pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize; else // Bitmap is stored top-to-bottom pos = bmpImageoffset + row * rowSize; if(bmpFile.position() != pos) { // Need seek? bmpFile.seek(pos,SeekSet); buffidx = sizeof(sdbuffer); // Force buffer reload } for (col=0; col<w; col++) { // For each pixel... // Time to read more pixel data? if (buffidx >= sizeof(sdbuffer)) { // Indeed bmpFile.read(sdbuffer, sizeof(sdbuffer)); buffidx = 0; // Set index to beginning } // Convert pixel from BMP to TFT format, push to display b = sdbuffer[buffidx++]; g = sdbuffer[buffidx++]; r = sdbuffer[buffidx++]; tft.pushColor(tft.Color565(r,g,b)); } // end pixel } // end scanline Serial.print("Loaded in "); Serial.print(millis() - startTime); Serial.println(" ms"); } // end goodBmp } } bmpFile.close(); if(!goodBmp) Serial.println("BMP format not recognized."); } //format bytes String formatBytes(size_t bytes){ if (bytes < 1024){ return String(bytes)+"B"; } else if(bytes < (1024 * 1024)){ return String(bytes/1024.0)+"KB"; } else if(bytes < (1024 * 1024 * 1024)){ return String(bytes/1024.0/1024.0)+"MB"; } else { return String(bytes/1024.0/1024.0/1024.0)+"GB"; } } //文件格式转换 String getContentType(String filename){ if(server.hasArg("download")) return "application/octet-stream"; else 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"; } //读取spiffs中的文件 bool handleFileRead(String path){ Serial.println("handleFileRead: " + path); if(path.endsWith("/")) path += "index.htm"; String contentType = getContentType(path); String pathWithGz = path + ".gz"; if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){ if(SPIFFS.exists(pathWithGz)) path += ".gz"; File file = SPIFFS.open(path, "r"); size_t sent = server.streamFile(file, contentType); file.close(); return true; } return false; } //上传文件到spiffs中 void handleFileUpload(){ if(server.uri() != "/") return; HTTPUpload& upload = server.upload(); if(upload.status == UPLOAD_FILE_START){ String filename = upload.filename; if(!filename.startsWith("/")) filename = "/"+filename; Serial.print("handleFileUpload Name: "); Serial.println(filename); SPIFFS.remove("/logo.bmp"); fsUploadFile = SPIFFS.open("/logo.bmp", "w"); filename = String(); } else if(upload.status == UPLOAD_FILE_WRITE){ //Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize); if(fsUploadFile) fsUploadFile.write(upload.buf, upload.currentSize); } else if(upload.status == UPLOAD_FILE_END){ if(fsUploadFile) fsUploadFile.close(); Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize); bmpDraw("/logo.bmp", 0, 0); } } void handleRoot() { server.send(200, "text/html", mainPageString); server.client().stop(); } void uplaodFinish() { server.send(200, "text/html", mainPageString); } void setup(void){ Serial.begin(115200); Serial.print("\n"); Serial.setDebugOutput(true); SPIFFS.begin(); { Dir dir = SPIFFS.openDir("/"); while (dir.next()) { String fileName = dir.fileName(); size_t fileSize = dir.fileSize(); Serial.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str()); } Serial.printf("\n"); } tft.initR(INITR_144GREENTAB); bmpDraw("/logo.bmp", 0, 0); delay(2000); //WIFI INIT Serial.printf("Connecting to %s\n", ssid); WiFi.disconnect(); WiFi.mode(WIFI_STA); if (String(WiFi.SSID()) != String(ssid)) { WiFi.begin(ssid, password); } while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected! IP address: "); Serial.println(WiFi.localIP()); MDNS.begin(host); Serial.print("Open http://"); Serial.print(host); Serial.println(".local/ to see the file browser"); //SERVER INIT server.on("/", HTTP_GET, handleRoot); //把上传的数据保存到spiffs server.on("/", HTTP_POST,[](){uplaodFinish();}, handleFileUpload); //访问的url没有在找spiffs中找到回复404 //访问的url没有在找spiffs中找到回复404 server.onNotFound([](){ if(!handleFileRead(server.uri())) server.send(404, "text/plain", "FileNotFound"); }); server.begin(); Serial.println("HTTP server started"); } void loop(void){ server.handleClient(); } ``` [【附件】esp8266网页上传图像到tft显示屏附件.zip](/media/attachment/2021/10/esp8266网页上传图像到tft显示屏附件.zip) 原文链接:https://www.arduino.cn/thread-42247-1-1.html
local
2021年10月28日 14:43
分享文档
收藏文档
上一篇
下一篇
微信扫一扫
复制链接
手机扫一扫进行分享
复制链接
关于 LocalNetwork
LocalNetwork
是由mrdoc开源
LocalNetwork.cn
修改的在线文档系统,作为个人和小型团队的云笔记、文档和知识库管理工具。
如果此文档给你或你的团队带来了帮助,欢迎支持作者持续投入精力更新和维护!内网文摘 & LocalNetwork
>>>主页
logo
logo
下载Markdown文件
分享
链接
类型
密码
更新密码