csxqwe 发表于 2022-5-17 21:57

新人求助,为什么我的SD卡的图片无法被ESP32找到

本帖最后由 csxqwe 于 2022-5-18 17:29 编辑

这段代码的功能是在TFT屏幕上显示SD卡上的图片,但是ESP32总是找不到上面的图片,萌新求助

下附代码(详情见图片,总是会跳入箭头的if条件中):

/**    基于ESP32   
*SD卡模块      
*SDA/SS    5   
*SCK       18
*MOSI      23
*MISO      19   
*GND
*5V
*
*TFT模块
*VCC             3.3
*#define TFT_MISO 19
*#define TFT_MOSI 23
*#define TFT_SCLK 18
*#define TFT_CS   15// Chip select control pin
*#define TFT_DC    2// Data Command control pin
*#define TFT_RST   4// Reset pin (could connect to RST pin)
*
*PAJ7620
*IIC_SCL22
*IIC_SDA21
*VCC   3.3
*GND   
*/
#include <SPI.h>

#include <FS.h>
#include <SD.h>

#include <TFT_eSPI.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <EEPROM.h>//数据保存库
#include <NTPClient.h>    //NTP库
#include <HTTPClient.h>//HTTP库
#include <WiFiUdp.h>
// JPEG decoder library
#include <JPEGDecoder.h>
/*天气API*/
#include <ArduinoJson.h>//使用JSON-v5版的库
/*PAJ7620*/
#include <Wire.h>
#include "html.h"//网页文件
#include "MyFont.h"
#include "As.h"
#include "I2Cdev.h"
#include "MPU6050.h"

TFT_eSPI tft = TFT_eSPI();


const char* ssid = "CMCC-EGLJ"; //Replace youself wifi ssid
const char* password = "8a1zljzb"; //Replace youself wifi password
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "ntp.aliyun.com"); // NTP获取时间
WebServer server(80);//相册用

WiFiClient client;//创建一个网络对象获取天气用

int tft_num = 0;//相册计数器
int flag_finsh = 0;
boolupload_flag = false;//文件上传
char* now_wea;
int tm_Hour,tm_Minute,monthDay,tm_Month;
String weekDay;
char* week;
String weekDays={"周日", "周一", "周二","周三", "周四", "周五", "周六"};
String weekEnglish = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
String months={"January", "February", "March", "April","May", "June", "July", "August", "September", "October", "November", "December"};
File fsUploadFile;//创建网页文件指针
/*mpu6050*/
/*定义主要的姿态*/
#define Forward   1
#define Backward2
#define Right   3
#define Left      4
#define GES_REACTION_TIME    500       // You can adjust the reaction time according to the actual circumstance.
#define GES_ENTRY_TIME      800       // When you want to recognize the Forward/Backward gestures, your gestures' reaction time must less than GES_ENTRY_TIME(0.8s).
#define GES_QUIT_TIME   1000

uint8_t flag_page = 100;//确定页面标志位
int flag_pic = 0;//确定照片标志位
uint32_t t=0;//超时标志位
bool flag = 1;//确定加载标志位
int16_t ax, ay, az;
int16_t gx, gy, gz;
MPU6050 accelgyro;
SPIClass sdSPI(VSPI);
#define SD_MISO   13
#define SD_MOSI   15
#define SD_SCLK   17
#define SD_CS       14
/*******************时间界面显示****************/
void showtext(int16_t x,int16_t y,uint8_t font,uint8_t s,uint16_t fg,uint16_t bg,const String str)
{
//设置文本显示坐标,和文本的字体,默认以左上角为参考点,
    tft.setCursor(x, y, font);
// 设置文本颜色为白色,文本背景黑色
    tft.setTextColor(fg,bg);
//设置文本大小,文本大小的范围是1-7的整数
    tft.setTextSize(s);
// 设置显示的文字,注意这里有个换行符 \n 产生的效果
    tft.println(str);
}
/*******************单个汉字显示****************/
void showMyFont(int32_t x, int32_t y, const char c, uint32_t color) {
for (int k = 0; k < 32; k++)// 根据字库的字数调节循环的次数
    if (hanzi.Index == c && hanzi.Index == c && hanzi.Index == c)
    { tft.drawBitmap(x, y, hanzi.hz_Id, hanzi.hz_width, 16, color);
    }
}
/*******************整句汉字显示****************/
void showMyFonts(int32_t x, int32_t y, const char str[], uint32_t color) { //显示整句汉字,字库比较简单,上下、左右输出是在函数内实现
int x0 = x;
for (int i = 0; i < strlen(str); i += 3) {
    showMyFont(x0, y, str+i, color);
    x0 += 17;
}
}
void show_time(uint16_t fg,uint16_t bg,const uint16_t* image[], String currentTime, String currentDate, int tm_Year,const char* week)
{
    uint8_t i=0;
    //tft.fillRect(10, 55,64, 64, bg);
    tft.setSwapBytes(true);             //使图片颜色由RGB->BGR
    tft.pushImage(10, 55,64, 64, image);
    delay(100);
    i+=1;
    if(i>8){i=0;}
    tft.drawFastHLine(10, 53, 108, tft.alphaBlend(0, bg,fg));
    showtext(15,5,2,3,fg,bg,currentTime);
    showtext(75,60,1,2,fg,bg, String(tm_Year));
    showtext(75,80,1,2,fg,bg, currentDate);
    showMyFonts(80, 100, week, TFT_YELLOW);
}
void display_time()
{
    timeClient.update();
    String formattedTime = timeClient.getFormattedTime();
    int tm_Hour = timeClient.getHours();
    int tm_Minute = timeClient.getMinutes();
    int tm_Second = timeClient.getSeconds();
    String weekDay = weekDays;
    unsigned long epochTime = timeClient.getEpochTime();
    char week;
    weekDay.toCharArray(week,weekDay.length() + 1);
   
    struct tm *ptm = gmtime ((time_t *)&epochTime);
    int monthDay = ptm->tm_mday;
    int tm_Month = ptm->tm_mon+1;
    String currentMonthName = months;
    int tm_Year = ptm->tm_year+1900;
    String currentDate = String(tm_Month) + "/" + String(monthDay);
    String currentTime, hour, minute;
    if (tm_Hour < 10)
      hour = "0" + String(tm_Hour);
    else
      hour = String(tm_Hour);
    if (tm_Minute < 10)
      minute = "0" + String(tm_Minute);
    else
      minute = String(tm_Minute);
    currentTime = hour + ":" + minute;
      tft.setSwapBytes(true);
    show_time(TFT_WHITE, TFT_BLACK, Astronaut, currentTime, currentDate, tm_Year, week); // 显示时间界面
    delay(500);
    display_time();
}
//####################################################################################################
//MPU6050传感器扫描
//####################################################################################################
void mpu_update(int interval)
{
int16_t last_update_time;
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
if (millis() - last_update_time > interval)
{
    if (ay > 3000 && flag)
    {
      flag_page--;
      flag = 0;
    }
    else if (ay < -3000 && flag)
    {
      flag_page++;
      flag = 0;
    }
    else
    {
      flag = 1;
    }
    last_update_time = millis();
}
}
//####################################################################################################
//web服务初始化
//####################################################################################################
void WEB_setup(){
server.on("/", HTTP_GET, handleRoot);//发送开始获取
//把上传的数据保存到spiffs
server.on("/", HTTP_POST,[](){uplaodFinish();}, handleFileUpload);//下载文件
//访问的url没有在找spiffs中找到回复404
server.onNotFound([](){if(!handleFileRead(server.uri()))server.send(404, "text/plain", "FileNotFound");});
server.begin();//网络服务开启
}
//####################################################################################################
//SD初始化
//####################################################################################################
void SD_setup(){
sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
if (!SD.begin(SD_CS, sdSPI))
{
    Serial.println("存储卡挂载失败");
    return;
}
uint8_t cardType = SD.cardType();

if (cardType == CARD_NONE)
{
    Serial.println("未连接存储卡");
    return;
}
else if (cardType == CARD_MMC)
{
    Serial.println("挂载了MMC卡");
}
else if (cardType == CARD_SD)
{
    Serial.println("挂载了SDSC卡");
}
else if (cardType == CARD_SDHC)
{
    Serial.println("挂载了SDHC卡");
}
else
{
    Serial.println("挂载了未知存储卡");
}

//打印存储卡信息
Serial.printf("存储卡总大小是: %lluMB \n", SD.cardSize() / (1024 * 1024)); // "/ (1024 * 1024)"可以换成">> 20"
Serial.printf("文件系统总大小是: %lluB \n", SD.totalBytes());
Serial.printf("文件系统已用大小是: %lluB \n", SD.usedBytes());
}
//####################################################################################################
//TFT初始化
//####################################################################################################
void TFT_setup(){
    tft.init();                         //初始化显示寄存器
    tft.fillScreen(TFT_WHITE);          //屏幕颜色
    tft.setTextColor(TFT_BLACK);      //设置字体颜色黑色
    tft.setCursor(15, 100, 1);         //设置文字开始坐标(15,30)及1号字体
    tft.setTextSize(1);
    //tft.setRotation(4);//屏幕内容镜像显示或者旋转屏幕0-4ST7735_Rotation中设置
}
//####################################################################################################
//WIFI初始化
//####################################################################################################
void WIFI_setup(){
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
    // Wait for connection
uint8_t i = 0;
uint8_t wifi_image_num = 1;
while (WiFi.status() != WL_CONNECTED && i++ < 50) {//wait 25 seconds
    Serial.print(".");
    delay(500);
}
    tft.fillScreen(TFT_WHITE);
    tft.println("Connecting Wifi...");
    tft.setSwapBytes(true);             //使图片颜色由RGB->BGR
   while(wifi_image_num<=5)
{
    drawSdJpeg(wifi_image_num, 0, 0, 5);   // This draws a jpeg pulled off the SD Card
    wifi_image_num=wifi_image_num+1;
}   
if (i == 51) {
    Serial.print("Could not connect to");
    Serial.println(ssid);
    while (1) {
      delay(500);
    }
}
Serial.print("Connected! IP address: ");
drawSdJpeg(6, 0, 0, 5);      
Serial.println(WiFi.localIP());//输出IP地址
    tft.setCursor(20, 100, 1);                //设置文字开始坐标(20,30)及1号字体
    tft.setTextSize(1);
    tft.println("WiFi Connected!");
}
//####################################################################################################
//mpu6050初始化
//####################################################################################################
void mpu6050_setup(){
#define LED_PIN 13
    Wire.begin();
    Serial.begin(115200);
    Serial.println("Initializing I2C devices...");
    accelgyro.initialize();
    Serial.println("Testing device connections...");
    Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
    pinMode(LED_PIN, OUTPUT);
}
//####################################################################################################
// 天气获取并显示
//####################################################################################################
void weather_api(){//天气API获取
if(client.connect("api.seniverse.com",80)==1)//连接服务器并判断是否连接成功,若成功就发送GET 请求数据下发      
{                                             //换成你自己在心知天气申请的私钥//改成你所在城市的拼音   
   //client.print("GET/v3/weather/now.json?key=*********&location=beijing&language=zh-Hans&unit=c HTTP/1.1\r\n"); //心知天气的URL格式   
   client.print("GET/v3/weather/daily.json?key=SnVROk4GLlocDZ1UQ&location=chengdu&language=zh-Hans&unit=c&start=0&days=5 HTTP/1.1\r\n"); //心知天气的三天天气URL格式
   client.print("Host:api.seniverse.com\r\n");
   client.print("Accept-Language:zh-cn\r\n");
   client.print("Connection:close\r\n\r\n"); //向心知天气的服务器发送请求。

               
   String status_code = client.readStringUntil('\r');      //读取GET数据,服务器返回的状态码,若成功则返回状态码200
   //Serial.println(status_code);
   /*
    * {"results":
    * [
    * {"location":
    * {"id":"WX4FBXXFKE4F","name":"北京","country":"CN","path":"北京,北京,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"}
    * ,"now":{"text":"晴","code":"1","temperature":"10"},"last_update":"2020-04-04T23:10:00+08:00"}
    * ]
    * }
   */
   if(client.find("{")==1)//跳过返回的数据头,直接读取后面的JSON数据
   //if(client.available())
    {
      String json_from_server=client.readStringUntil(']');//读取返回的JSON数据
      json_from_server = "{"+json_from_server+"]}]}";
      Serial.println(json_from_server);
      parseUserData(json_from_server);                      //将读取的JSON数据,传送到JSON解析函数中进行显示。
    }
    else
    {
       Serial.println("Not find.");
    }
}
else                                       
{
   Serial.println("connection failed this time");
   delay(500);                                          //请求失败等5秒
}
client.stop(); //关闭HTTP客户端,采用HTTP短链接,数据请求完毕后要客户端要主动断开
}
//####################################################################################################
// JOSN解析函数
//####################################################################################################
void parseUserData(String content){   // Json数据解析并串口打印.可参考https://www.bilibili.com/video/av65322772
int weather_num;
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
DynamicJsonBuffer jsonBuffer(1660);

JsonObject& root = jsonBuffer.parseObject(content);

JsonObject& results_0 = root["results"];

JsonObject& results_daily0 = results_0["daily"];
JsonObject& results_daily1 = results_0["daily"];
JsonObject& results_daily2 = results_0["daily"];

const char* results_0_now_data = results_daily0["date"];//天气时间
const char* results_0_now_text = results_daily0["text_day"];//天气时间

const char* results_0_now_code = results_daily0["code_day"];//天气现象数值
const char* results_1_now_code = results_daily1["code_day"];//天气现象数值

String high_tem_0= results_daily0["high"];//天气温度最高数值
String high_tem_1= results_daily1["high"];//天气温度最高数值

String low_tem_0= results_daily0["low"];//天气温度最低数值
String low_tem_1= results_daily1["low"];//天气温度最低数值

String hum= results_daily0["humidity"];//天气湿度数值

const char* wind_speed0 = results_daily0["wind_speed"];//天气风速数值
const char* wind_speed1 = results_daily1["wind_speed"];//天气风速数值

const char* rain= results_daily0["rainfall"];//天气降雨量数值

//atoi()函数将字符转换为数字
weather_num = atoi(results_0_now_code);
weather_num = atoi(results_1_now_code);

/*Serial.println(results_0_now_code);                     //通过串口打印出需要的信息
Serial.println(results_1_now_code);
Serial.println(results_2_now_code);
Serial.print("\r\n");*/


drawSdJpeg(0,0,0,3);//加载主页面

tft_showstring(10,70,1,results_0_now_data);//显示今日日期

drawSdJpeg(weather_num,25,25,1);//加载今天天气
drawSdJpeg(weather_num,20,102,4);//加载明天天气

tft_showstring(100,20,1,low_tem_0+"-"+high_tem_0+"C");//显示今日温度
tft_showstring(100,33,1,wind_speed0);//显示今日风速
tft_showstring(100,46,1,hum+"%");//显示今日湿度
tft_showstring(110,59,1,rain);//显示今日降雨量


tft_showstring(100,102,1,low_tem_1+"-"+high_tem_1+"C");//显示明日温度
tft_showstring(100,116,1,wind_speed1);//显示明日风速

}
//####################################################################################################
// 显示数字
//####################################################################################################
void tft_showstring(int x,int y,int c,String z){
tft.setCursor(x, y, c);
tft.setTextColor(TFT_BLACK,TFT_WHITE);
tft.println(z);
}
//####################################################################################################
// 控制显示
//####################################################################################################
void jpg_draw(int bmp_screen_num){
//tft.setRotation(2);//设置旋转
tft.fillScreen(0x0000);//背景颜色
drawSdJpeg(bmp_screen_num,0,0,0);   // This draws a jpeg pulled off the SD Card
//delay(5000);
}
/*******************开机画面****************/
int image_num = 1;
void magic() {

//播放magic,共128帧,每秒30帧
while(image_num<=128)
{
    drawSdJpeg(image_num, 0, 0, 2);   // This draws a jpeg pulled off the SD Card
    image_num=image_num+1;
}
}
//####################################################################################################
//读取SD卡图片
//####################################################################################################
void drawSdJpeg(int bmp_screen_num, int xpos, int ypos,int mode_pic) {
char filename1;
int mode_ = 0;
switch(mode_pic){
    case 0://加载照片
      //filename = "/loge"+String(bmp_screen_num)+".jpg";
      sprintf(filename1,"/loge%d.jpg",bmp_screen_num);
      mode_ =1;
       break;
    case 1://加载64x64天气图片
      //filename = "/img/64x64/"+String(bmp_screen_num)+".jpg";//重定向文件
      sprintf(filename1,"/img/64x64/%d.jpg",bmp_screen_num);
      break;
    case 2://开机画面
   //filename = "/magic/"+String(bmp_screen_num)+".jpg";
   sprintf(filename1,"/magic/%d.jpg",bmp_screen_num);
      break;
    case 3://加载天气主页面图片
      //filename = "/main.jpg";//重定向文件
      sprintf(filename1,"/main.jpg",bmp_screen_num);
      break;
    case 4://加载40x40天气图片
      //filename = "/img/40x40/"+String(bmp_screen_num)+".jpg";//重定向文件
      sprintf(filename1,"/img/40x40/%d.jpg",bmp_screen_num);
      break;
    case 5://WIFI连接
      //filename = "/wifi/"+String(bmp_screen_num)+".jpg";//重定向文件
      sprintf(filename1,"/wifi/%d.jpg",bmp_screen_num);
      break;
    }
const char *filename = filename1;
File jpegFile = SD.open(filename1,FILE_READ);// or, file handle reference for SD library

if ( !jpegFile ) {
    Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!");
    return;
}

Serial.println("===========================");
Serial.print("Drawing file: "); Serial.println(filename);
Serial.println("===========================");

// Use one of the following methods to initialise the decoder:
boolean decoded = JpegDec.decodeSdFile(jpegFile);// Pass the SD file handle to the decoder,
//boolean decoded = JpegDec.decodeSdFile(filename);// or pass the filename (String or character array)

if (decoded) {
    // print information about the image to the serial port
    jpegInfo();
    // render the image onto the screen at given coordinates
    jpegRender(xpos, ypos,mode_);
}
else {
    Serial.println("Jpeg file format not supported!");
}
}
//####################################################################################################
// 在TFT上绘图片
//####################################################################################################
void jpegRender(int xpos, int ypos,int mode_) {

//jpegInfo(); // Print information from the JPEG file (could comment this line out)

uint16_t *pImg;
uint32_t mcu_w = JpegDec.MCUWidth;
uint32_t mcu_h = JpegDec.MCUHeight;
uint32_t max_x = JpegDec.width;
uint32_t max_y = JpegDec.height;
//调整选转角度并且居中显示
if(mode_ == 1)
{
    if(max_x > max_y)
    {
      tft.setRotation(1);
      xpos = (128-max_x)/2; //居中显示
      ypos = (128-max_y)/2; //居中显示
      if(xpos < 0 ||xpos > 128)
       xpos = 0;
      if(ypos < 0 || ypos >128)
       ypos = 0;
    }
    else if(max_x <= max_y)
    {
      tft.setRotation(2);
      xpos = (128-max_x)/2; //居中显示
      ypos = (128-max_y)/2; //居中显示
      if(xpos < 0 ||xpos > 128)
       xpos = 0;
      if(ypos < 0 || ypos >128)
       ypos = 0;
    }
}
else
{
    tft.setRotation(2);
}
bool swapBytes = tft.getSwapBytes();
tft.setSwapBytes(true);


   
// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
// Typically these MCUs are 16x16 pixel blocks
// Determine the width and height of the right and bottom edge image blocks
uint32_t min_w = min(mcu_w, max_x % mcu_w);
uint32_t min_h = min(mcu_h, max_y % mcu_h);

// save the current image block size
uint32_t win_w = mcu_w;
uint32_t win_h = mcu_h;



// record the current time so we can measure how long it takes to draw an image
uint32_t drawTime = millis();

// save the coordinate of the right and bottom edges to assist image cropping
// to the screen size
max_x += xpos;
max_y += ypos;

    // Fetch data from the file, decode and display
    while (JpegDec.read()) {    // While there is more data in the file
      pImg = JpegDec.pImage ;   // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block)

    // Calculate coordinates of top left corner of current MCU
    int mcu_x = JpegDec.MCUx * mcu_w + xpos;
    int mcu_y = JpegDec.MCUy * mcu_h + ypos;

    // check if the image block size needs to be changed for the right edge
    if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
    else win_w = min_w;

    // check if the image block size needs to be changed for the bottom edge
    if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
    else win_h = min_h;

    // copy pixels into a contiguous block
    if (win_w != mcu_w)
    {
      uint16_t *cImg;
      int p = 0;
      cImg = pImg + win_w;
      for (int h = 1; h < win_h; h++)
      {
      p += mcu_w;
      for (int w = 0; w < win_w; w++)
      {
          *cImg = *(pImg + w + p);
          cImg++;
      }
      }
    }

    // calculate how many pixels must be drawn
    uint32_t mcu_pixels = win_w * win_h;

    // draw image MCU block only if it will fit on the screen
    if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height())
      tft.pushImage(mcu_x, mcu_y, win_w, win_h, pImg);
    else if ( (mcu_y + win_h) >= tft.height())
      JpegDec.abort(); // Image has run off bottom of screen so abort decoding
}

tft.setSwapBytes(swapBytes);
}
//####################################################################################################
// 打印TFT上图片信息
//####################################################################################################
void jpegInfo() {
// Print information extracted from the JPEG file
Serial.println("JPEG image info");
Serial.println("===============");
Serial.print("Width      :");
Serial.println(JpegDec.width);
Serial.print("Height   :");
Serial.println(JpegDec.height);
Serial.print("Components :");
Serial.println(JpegDec.comps);
Serial.print("MCU / row:");
Serial.println(JpegDec.MCUSPerRow);
Serial.print("MCU / col:");
Serial.println(JpegDec.MCUSPerCol);
Serial.print("Scan type:");
Serial.println(JpegDec.scanType);
Serial.print("MCU width:");
Serial.println(JpegDec.MCUWidth);
Serial.print("MCU height :");
Serial.println(JpegDec.MCUHeight);
Serial.println("===============");
Serial.println("");
}
//####################################################################################################
// 将上传的文件发送回SD卡
//####################################################################################################
bool handleFileRead(String path){
int upload_ = tft_num - 1;
if(upload_<0)
    upload_ = 0;
path = "/loge"+String(upload_)+".jpg";//上传JPG文件
Serial.println("handleFileRead: " + path);
if(path.endsWith("/")) path += "index.htm";
String contentType = getContentType(path);
String pathWithGz = path + ".gz";
if(SD.exists(pathWithGz) || SD.exists(path)){
    if(SD.exists(pathWithGz))
      path += ".gz";
    File file = SD.open(path, "r");
    size_t sent = server.streamFile(file, contentType);
    file.close();
    upload_flag = false;//完成一次写入
    return true;
}
upload_flag = false;//完成一次写入
return false;
}
//####################################################################################################
// 文件上传SD卡
//####################################################################################################
void handleFileUpload(){//网络服务处理函数
upload_flag = true;//正在进行上传
if(server.uri() != "/") return;
HTTPUpload& upload = server.upload();
String filename;
char *file_sd;
if(upload.status == UPLOAD_FILE_START){//开启下载上传的文件
    filename = upload.filename;
    if(!filename.startsWith("/"))
    {
      filename = "/loge"+String(tft_num)+".jpg";//如果文件开头没有/则添加/ 并且对该图片添加计数尾缀
      tft_num++;//文件数+1
      EEPROM.write(20,tft_num);//将数据保存
      EEPROM.commit();
    }
    Serial.print("handleFileUpload Name: "); Serial.println(filename);//打印文件名
   
    SD.remove(filename);
    fsUploadFile = SD.open(filename, "w");//将上传的文件保存
    filename = String();
} else if(upload.status == UPLOAD_FILE_WRITE){
    if(fsUploadFile)
      fsUploadFile.write(upload.buf, upload.currentSize);//将上传文件写入SD卡
} else if(upload.status == UPLOAD_FILE_END){
    if(fsUploadFile)
      fsUploadFile.close();
}
}
//####################################################################################################
// 加载网页
//####################################################################################################
void handleRoot(){
upload_flag = true;//进入上传就绪状态(打开了网页)
server.send(200, "text/html", mainPageString);
server.client().stop();
}
//####################################################################################################
// 上传完成函数
//####################################################################################################
void uplaodFinish(){
server.send(200, "text/html", uploadString);//重新发送网页
upload_flag = true;//上传完成,但是网页回复仍未完成
}
//####################################################################################################
// 限幅函数
//####################################################################################################
uint8_t limit(){
if(flag_pic >= tft_num)
{
    flag_pic = flag_pic - tft_num;
}
else if(flag_pic < 0)
{
    flag_pic = flag_pic + tft_num;
}
}
//####################################################################################################
// 文件格式获取
//####################################################################################################
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";
}
//####################################################################################################
// 初始化函数
//####################################################################################################
void setup() {
mpu6050_setup();
SD_setup();
TFT_setup();
magic();
WIFI_setup();
client.setTimeout(5000);//设置天气服务器连接超时时间
//EEPROM
EEPROM.begin(512);
tft_num =EEPROM.read(20);
Serial.print("the tft number is");Serial.println(tft_num);
WEB_setup();

}
//####################################################################################################
// 主循环
//####################################################################################################
void loop(){
if(upload_flag == false)
{
    if(flag_finsh == 0)//页面未加载
    {
      switch(flag_page % 2)
      {
      case 0://天气界面
      {
          flag_finsh = 1;//完成加载
          weather_api();
      }
      break;
      case 1://照片界面
      {
          flag_finsh = 1;//完成加载
          limit();//形成循环
          jpg_draw(flag_pic);
      }
      break;
      }
    }
    else if(flag_finsh == 1)//页面已加载,进入扫描 和网络服务处理
    {
      mpu_update(100);
      server.handleClient();
      flag_finsh =0;
      }
    }
if(upload_flag == true)//防止未上传超时
{
    t++;
    delay(5);
    server.handleClient();//上传图片服务处理
}
else
{
    t=0;
}

if(t > 6000)
{
    upload_flag = false;
    t = 0;
}
Serial.print(t);
}

topdog 发表于 2022-5-17 22:10

https://www.arduino.cn/thread-108079-1-1.html

topdog 发表于 2022-5-17 22:13

https://www.arduino.cn/thread-105763-1-1.html

csxqwe 发表于 2022-5-18 17:28

topdog 发表于 2022-5-17 22:10
https://www.arduino.cn/thread-108079-1-1.html

谢谢,不过我想看的是批量显示图片,不是只显示一张,我没有看出我写的代码有哪些问题:Q
页: [1]
查看完整版本: 新人求助,为什么我的SD卡的图片无法被ESP32找到