新人求助,为什么我的SD卡的图片无法被ESP32找到-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 544|回复: 3

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

[复制链接]
回帖奖励 1 金币 回复本帖可获得 1 金币奖励! 每人限 1 次(中奖概率 30%)
发表于 2022-5-17 21:57 | 显示全部楼层 |阅读模式
本帖最后由 csxqwe 于 2022-5-18 17:29 编辑

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

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

  1. /**    基于ESP32   
  2. *  SD卡模块      
  3. *  SDA/SS    5     
  4. *  SCK       18  
  5. *  MOSI      23  
  6. *  MISO      19   
  7. *  GND
  8. *  5V
  9. *  
  10. *  TFT模块
  11. *  VCC             3.3
  12. *  #define TFT_MISO 19
  13. *  #define TFT_MOSI 23
  14. *  #define TFT_SCLK 18
  15. *  #define TFT_CS   15  // Chip select control pin
  16. *  #define TFT_DC    2  // Data Command control pin
  17. *  #define TFT_RST   4  // Reset pin (could connect to RST pin)
  18. *  
  19. *  PAJ7620
  20. *  IIC_SCL  22
  21. *  IIC_SDA  21
  22. *  VCC     3.3
  23. *  GND     
  24. */
  25. #include <SPI.h>

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

  28. #include <TFT_eSPI.h>
  29. #include <WiFi.h>
  30. #include <WiFiClient.h>
  31. #include <WebServer.h>
  32. #include <ESPmDNS.h>
  33. #include <EEPROM.h>//数据保存库
  34. #include <NTPClient.h>    //NTP库
  35. #include <HTTPClient.h>  //HTTP库
  36. #include <WiFiUdp.h>
  37. // JPEG decoder library
  38. #include <JPEGDecoder.h>
  39. /*天气API*/
  40. #include <ArduinoJson.h>//使用JSON-v5版的库
  41. /*PAJ7620*/
  42. #include <Wire.h>
  43. #include "html.h"//网页文件
  44. #include "MyFont.h"
  45. #include "As.h"
  46. #include "I2Cdev.h"
  47. #include "MPU6050.h"

  48. TFT_eSPI tft = TFT_eSPI();


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

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

  55. int tft_num = 0;//相册计数器
  56. int flag_finsh = 0;
  57. bool  upload_flag = false;//文件上传
  58. char* now_wea;
  59. int tm_Hour,tm_Minute,monthDay,tm_Month;
  60. String weekDay;
  61. char* week;
  62. String weekDays[7]={"周日", "周一", "周二","周三", "周四", "周五", "周六"};
  63. String weekEnglish[7] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
  64. String months[12]={"January", "February", "March", "April","May", "June", "July", "August", "September", "October", "November", "December"};
  65. File fsUploadFile;//创建网页文件指针
  66. /*mpu6050*/
  67. /*定义主要的姿态*/
  68. #define Forward   1
  69. #define Backward  2
  70. #define Right     3
  71. #define Left      4
  72. #define GES_REACTION_TIME    500       // You can adjust the reaction time according to the actual circumstance.
  73. #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).
  74. #define GES_QUIT_TIME     1000

  75. uint8_t flag_page = 100;//确定页面标志位
  76. int flag_pic = 0;//确定照片标志位
  77. uint32_t t=0;//超时标志位
  78. bool flag = 1;//确定加载标志位
  79. int16_t ax, ay, az;
  80. int16_t gx, gy, gz;
  81. MPU6050 accelgyro;
  82. SPIClass sdSPI(VSPI);
  83. #define SD_MISO     13
  84. #define SD_MOSI     15
  85. #define SD_SCLK     17
  86. #define SD_CS       14
  87. /*******************时间界面显示****************/
  88. void showtext(int16_t x,int16_t y,uint8_t font,uint8_t s,uint16_t fg,uint16_t bg,const String str)
  89. {
  90.   //设置文本显示坐标,和文本的字体,默认以左上角为参考点,
  91.     tft.setCursor(x, y, font);
  92.   // 设置文本颜色为白色,文本背景黑色
  93.     tft.setTextColor(fg,bg);
  94.   //设置文本大小,文本大小的范围是1-7的整数
  95.     tft.setTextSize(s);
  96.   // 设置显示的文字,注意这里有个换行符 \n 产生的效果
  97.     tft.println(str);
  98. }
  99. /*******************单个汉字显示****************/
  100. void showMyFont(int32_t x, int32_t y, const char c[3], uint32_t color) {
  101.   for (int k = 0; k < 32; k++)// 根据字库的字数调节循环的次数
  102.     if (hanzi[k].Index[0] == c[0] && hanzi[k].Index[1] == c[1] && hanzi[k].Index[2] == c[2])
  103.     { tft.drawBitmap(x, y, hanzi[k].hz_Id, hanzi[k].hz_width, 16, color);
  104.     }
  105. }
  106. /*******************整句汉字显示****************/
  107. void showMyFonts(int32_t x, int32_t y, const char str[], uint32_t color) { //显示整句汉字,字库比较简单,上下、左右输出是在函数内实现
  108.   int x0 = x;
  109.   for (int i = 0; i < strlen(str); i += 3) {
  110.     showMyFont(x0, y, str+i, color);
  111.     x0 += 17;
  112.   }
  113. }
  114. void show_time(uint16_t fg,uint16_t bg,const uint16_t* image[], String currentTime, String currentDate, int tm_Year,const char* week)
  115. {
  116.     uint8_t i=0;
  117.     //tft.fillRect(10, 55,  64, 64, bg);
  118.     tft.setSwapBytes(true);             //使图片颜色由RGB->BGR
  119.     tft.pushImage(10, 55,  64, 64, image);
  120.     delay(100);
  121.     i+=1;
  122.     if(i>8){i=0;}
  123.     tft.drawFastHLine(10, 53, 108, tft.alphaBlend(0, bg,  fg));
  124.     showtext(15,5,2,3,fg,bg,currentTime);
  125.     showtext(75,60,1,2,fg,bg, String(tm_Year));
  126.     showtext(75,80,1,2,fg,bg, currentDate);
  127.     showMyFonts(80, 100, week, TFT_YELLOW);
  128. }
  129. void display_time()
  130. {
  131.     timeClient.update();
  132.     String formattedTime = timeClient.getFormattedTime();
  133.     int tm_Hour = timeClient.getHours();
  134.     int tm_Minute = timeClient.getMinutes();
  135.     int tm_Second = timeClient.getSeconds();
  136.     String weekDay = weekDays[timeClient.getDay()];
  137.     unsigned long epochTime = timeClient.getEpochTime();  
  138.     char week[weekDay.length() + 1];
  139.     weekDay.toCharArray(week,weekDay.length() + 1);
  140.    
  141.     struct tm *ptm = gmtime ((time_t *)&epochTime);
  142.     int monthDay = ptm->tm_mday;
  143.     int tm_Month = ptm->tm_mon+1;
  144.     String currentMonthName = months[tm_Month-1];
  145.     int tm_Year = ptm->tm_year+1900;
  146.     String currentDate = String(tm_Month) + "/" + String(monthDay);
  147.     String currentTime, hour, minute;
  148.     if (tm_Hour < 10)
  149.       hour = "0" + String(tm_Hour);
  150.     else
  151.       hour = String(tm_Hour);
  152.     if (tm_Minute < 10)
  153.       minute = "0" + String(tm_Minute);
  154.     else
  155.       minute = String(tm_Minute);
  156.     currentTime = hour + ":" + minute;
  157.       tft.setSwapBytes(true);
  158.     show_time(TFT_WHITE, TFT_BLACK, Astronaut, currentTime, currentDate, tm_Year, week); // 显示时间界面
  159.     delay(500);
  160.     display_time();
  161.   }
  162. //####################################################################################################
  163. //  MPU6050传感器扫描
  164. //####################################################################################################
  165. void mpu_update(int interval)
  166. {
  167.   int16_t last_update_time;
  168.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  169.   if (millis() - last_update_time > interval)
  170.   {
  171.     if (ay > 3000 && flag)
  172.     {
  173.       flag_page--;
  174.       flag = 0;
  175.     }
  176.     else if (ay < -3000 && flag)
  177.     {
  178.       flag_page++;
  179.       flag = 0;
  180.     }
  181.     else
  182.     {
  183.       flag = 1;
  184.     }
  185.     last_update_time = millis();
  186.   }
  187. }
  188. //####################################################################################################
  189. //  web服务初始化
  190. //####################################################################################################
  191. void WEB_setup(){
  192.   server.on("/", HTTP_GET, handleRoot);//发送开始获取
  193.   //把上传的数据保存到spiffs
  194.   server.on("/", HTTP_POST,[](){uplaodFinish();}, handleFileUpload);//下载文件
  195.   //访问的url没有在找spiffs中找到回复404
  196.   server.onNotFound([](){if(!handleFileRead(server.uri()))server.send(404, "text/plain", "FileNotFound");});
  197.   server.begin();//网络服务开启
  198. }
  199. //####################################################################################################
  200. //  SD初始化
  201. //####################################################################################################
  202. void SD_setup(){
  203.   sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  204.   if (!SD.begin(SD_CS, sdSPI))
  205.   {
  206.     Serial.println("存储卡挂载失败");
  207.     return;
  208.   }
  209.   uint8_t cardType = SD.cardType();

  210.   if (cardType == CARD_NONE)
  211.   {
  212.     Serial.println("未连接存储卡");
  213.     return;
  214.   }
  215.   else if (cardType == CARD_MMC)
  216.   {
  217.     Serial.println("挂载了MMC卡");
  218.   }
  219.   else if (cardType == CARD_SD)
  220.   {
  221.     Serial.println("挂载了SDSC卡");
  222.   }
  223.   else if (cardType == CARD_SDHC)
  224.   {
  225.     Serial.println("挂载了SDHC卡");
  226.   }
  227.   else
  228.   {
  229.     Serial.println("挂载了未知存储卡");
  230.   }

  231.   //打印存储卡信息
  232.   Serial.printf("存储卡总大小是: %lluMB \n", SD.cardSize() / (1024 * 1024)); // "/ (1024 * 1024)"可以换成">> 20"
  233.   Serial.printf("文件系统总大小是: %lluB \n", SD.totalBytes());
  234.   Serial.printf("文件系统已用大小是: %lluB \n", SD.usedBytes());
  235. }
  236. //####################################################################################################
  237. //  TFT初始化
  238. //####################################################################################################
  239. void TFT_setup(){
  240.     tft.init();                         //初始化显示寄存器
  241.     tft.fillScreen(TFT_WHITE);          //屏幕颜色
  242.     tft.setTextColor(TFT_BLACK);        //设置字体颜色黑色
  243.     tft.setCursor(15, 100, 1);           //设置文字开始坐标(15,30)及1号字体
  244.     tft.setTextSize(1);
  245.     //tft.setRotation(4);//屏幕内容镜像显示或者旋转屏幕0-4  ST7735_Rotation中设置
  246. }
  247. //####################################################################################################
  248. //  WIFI初始化
  249. //####################################################################################################
  250. void WIFI_setup(){
  251.   WiFi.mode(WIFI_STA);
  252.   WiFi.begin(ssid, password);
  253.     // Wait for connection
  254.   uint8_t i = 0;
  255.   uint8_t wifi_image_num = 1;
  256.   while (WiFi.status() != WL_CONNECTED && i++ < 50) {//wait 25 seconds
  257.     Serial.print(".");
  258.     delay(500);
  259.   }
  260.     tft.fillScreen(TFT_WHITE);
  261.     tft.println("Connecting Wifi...");
  262.     tft.setSwapBytes(true);             //使图片颜色由RGB->BGR
  263.    while(wifi_image_num<=5)
  264.   {
  265.     drawSdJpeg(wifi_image_num, 0, 0, 5);     // This draws a jpeg pulled off the SD Card
  266.     wifi_image_num=wifi_image_num+1;
  267.   }   
  268.   if (i == 51) {
  269.     Serial.print("Could not connect to");
  270.     Serial.println(ssid);
  271.     while (1) {
  272.       delay(500);
  273.     }
  274.   }
  275.   Serial.print("Connected! IP address: ");
  276.   drawSdJpeg(6, 0, 0, 5);      
  277.   Serial.println(WiFi.localIP());//输出IP地址
  278.     tft.setCursor(20, 100, 1);                //设置文字开始坐标(20,30)及1号字体
  279.     tft.setTextSize(1);
  280.     tft.println("WiFi Connected!");
  281. }
  282. //####################################################################################################
  283. //  mpu6050初始化
  284. //####################################################################################################
  285. void mpu6050_setup(){
  286. #define LED_PIN 13
  287.     Wire.begin();
  288.     Serial.begin(115200);
  289.     Serial.println("Initializing I2C devices...");
  290.     accelgyro.initialize();
  291.     Serial.println("Testing device connections...");
  292.     Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  293.     pinMode(LED_PIN, OUTPUT);
  294. }
  295. //####################################################################################################
  296. // 天气获取并显示
  297. //####################################################################################################
  298. void weather_api(){//天气API获取
  299.   if(client.connect("api.seniverse.com",80)==1)//连接服务器并判断是否连接成功,若成功就发送GET 请求数据下发      
  300.   {                                             //换成你自己在心知天气申请的私钥//改成你所在城市的拼音     
  301.    //client.print("GET  /v3/weather/now.json?key=*********&location=beijing&language=zh-Hans&unit=c HTTP/1.1\r\n"); //心知天气的URL格式   
  302.    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格式
  303.    client.print("Host:api.seniverse.com\r\n");
  304.    client.print("Accept-Language:zh-cn\r\n");
  305.    client.print("Connection:close\r\n\r\n"); //向心知天气的服务器发送请求。

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

  345. JsonObject& root = jsonBuffer.parseObject(content);

  346. JsonObject& results_0 = root["results"][0];

  347. JsonObject& results_daily0 = results_0["daily"][0];
  348. JsonObject& results_daily1 = results_0["daily"][1];
  349. JsonObject& results_daily2 = results_0["daily"][2];

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

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

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

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

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

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

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

  362. //atoi()函数将字符转换为数字
  363. weather_num[0] = atoi(results_0_now_code);
  364. weather_num[1] = atoi(results_1_now_code);

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


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

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

  371. drawSdJpeg(weather_num[0],25,25,1);//加载今天天气
  372. drawSdJpeg(weather_num[1],20,102,4);//加载明天天气

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


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

  379. }
  380. //####################################################################################################
  381. // 显示数字
  382. //####################################################################################################
  383. void tft_showstring(int x,int y,int c,String z){
  384.   tft.setCursor(x, y, c);
  385.   tft.setTextColor(TFT_BLACK,TFT_WHITE);
  386.   tft.println(z);
  387. }
  388. //####################################################################################################
  389. // 控制显示
  390. //####################################################################################################
  391. void jpg_draw(int bmp_screen_num){
  392.   //tft.setRotation(2);  //设置旋转
  393.   tft.fillScreen(0x0000);//背景颜色
  394.   drawSdJpeg(bmp_screen_num,0,0,0);     // This draws a jpeg pulled off the SD Card
  395.   //delay(5000);
  396. }
  397. /*******************开机画面****************/
  398. int image_num = 1;
  399. void magic() {

  400.   //播放magic,共128帧,每秒30帧
  401.   while(image_num<=128)
  402.   {
  403.     drawSdJpeg(image_num, 0, 0, 2);     // This draws a jpeg pulled off the SD Card
  404.     image_num=image_num+1;
  405.   }
  406. }
  407. //####################################################################################################
  408. //读取SD卡图片
  409. //####################################################################################################
  410. void drawSdJpeg(int bmp_screen_num, int xpos, int ypos,int mode_pic) {
  411.   char filename1[18];
  412.   int mode_ = 0;
  413.   switch(mode_pic){
  414.     case 0://加载照片
  415.       //filename = "/loge"+String(bmp_screen_num)+".jpg";
  416.       sprintf(filename1,"/loge%d.jpg",bmp_screen_num);
  417.       mode_ =1;
  418.        break;
  419.     case 1://加载64x64天气图片
  420.       //filename = "/img/64x64/"+String(bmp_screen_num)+".jpg";//重定向文件
  421.       sprintf(filename1,"/img/64x64/%d.jpg",bmp_screen_num);
  422.       break;
  423.     case 2://开机画面
  424.      //filename = "/magic/"+String(bmp_screen_num)+".jpg";
  425.      sprintf(filename1,"/magic/%d.jpg",bmp_screen_num);
  426.       break;
  427.     case 3://加载天气主页面图片
  428.       //filename = "/main.jpg";//重定向文件
  429.       sprintf(filename1,"/main.jpg",bmp_screen_num);
  430.       break;
  431.     case 4://加载40x40天气图片
  432.       //filename = "/img/40x40/"+String(bmp_screen_num)+".jpg";//重定向文件
  433.       sprintf(filename1,"/img/40x40/%d.jpg",bmp_screen_num);
  434.       break;
  435.     case 5://WIFI连接
  436.       //filename = "/wifi/"+String(bmp_screen_num)+".jpg";//重定向文件
  437.       sprintf(filename1,"/wifi/%d.jpg",bmp_screen_num);
  438.       break;  
  439.     }
  440.   const char *filename = filename1;
  441.   File jpegFile = SD.open(filename1,FILE_READ);  // or, file handle reference for SD library

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

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

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

  452.   if (decoded) {
  453.     // print information about the image to the serial port
  454.     jpegInfo();
  455.     // render the image onto the screen at given coordinates
  456.     jpegRender(xpos, ypos,mode_);
  457.   }
  458.   else {
  459.     Serial.println("Jpeg file format not supported!");
  460.   }
  461. }
  462. //####################################################################################################
  463. // 在TFT上绘图片
  464. //####################################################################################################
  465. void jpegRender(int xpos, int ypos,int mode_) {

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

  467.   uint16_t *pImg;
  468.   uint32_t mcu_w = JpegDec.MCUWidth;
  469.   uint32_t mcu_h = JpegDec.MCUHeight;
  470.   uint32_t max_x = JpegDec.width;
  471.   uint32_t max_y = JpegDec.height;
  472.   //调整选转角度并且居中显示
  473.   if(mode_ == 1)
  474.   {
  475.     if(max_x > max_y)
  476.     {
  477.       tft.setRotation(1);
  478.       xpos = (128-max_x)/2; //居中显示
  479.       ypos = (128-max_y)/2; //居中显示
  480.       if(xpos < 0 ||xpos > 128)
  481.        xpos = 0;
  482.       if(ypos < 0 || ypos >128)
  483.        ypos = 0;
  484.     }
  485.     else if(max_x <= max_y)
  486.     {
  487.       tft.setRotation(2);
  488.       xpos = (128-max_x)/2; //居中显示
  489.       ypos = (128-max_y)/2; //居中显示
  490.       if(xpos < 0 ||xpos > 128)
  491.        xpos = 0;
  492.       if(ypos < 0 || ypos >128)
  493.        ypos = 0;
  494.     }
  495.   }
  496.   else
  497.   {
  498.     tft.setRotation(2);
  499.   }
  500.   bool swapBytes = tft.getSwapBytes();
  501.   tft.setSwapBytes(true);


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

  508.   // save the current image block size
  509.   uint32_t win_w = mcu_w;
  510.   uint32_t win_h = mcu_h;
  511.   

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

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

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

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

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

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

  531.     // copy pixels into a contiguous block
  532.     if (win_w != mcu_w)
  533.     {
  534.       uint16_t *cImg;
  535.       int p = 0;
  536.       cImg = pImg + win_w;
  537.       for (int h = 1; h < win_h; h++)
  538.       {
  539.         p += mcu_w;
  540.         for (int w = 0; w < win_w; w++)
  541.         {
  542.           *cImg = *(pImg + w + p);
  543.           cImg++;
  544.         }
  545.       }
  546.     }

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

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

  555.   tft.setSwapBytes(swapBytes);
  556. }
  557. //####################################################################################################
  558. // 打印TFT上图片信息
  559. //####################################################################################################
  560. void jpegInfo() {
  561.   // Print information extracted from the JPEG file
  562.   Serial.println("JPEG image info");
  563.   Serial.println("===============");
  564.   Serial.print("Width      :");
  565.   Serial.println(JpegDec.width);
  566.   Serial.print("Height     :");
  567.   Serial.println(JpegDec.height);
  568.   Serial.print("Components :");
  569.   Serial.println(JpegDec.comps);
  570.   Serial.print("MCU / row  :");
  571.   Serial.println(JpegDec.MCUSPerRow);
  572.   Serial.print("MCU / col  :");
  573.   Serial.println(JpegDec.MCUSPerCol);
  574.   Serial.print("Scan type  :");
  575.   Serial.println(JpegDec.scanType);
  576.   Serial.print("MCU width  :");
  577.   Serial.println(JpegDec.MCUWidth);
  578.   Serial.print("MCU height :");
  579.   Serial.println(JpegDec.MCUHeight);
  580.   Serial.println("===============");
  581.   Serial.println("");
  582. }
  583. //####################################################################################################
  584. // 将上传的文件发送回SD卡
  585. //####################################################################################################
  586. bool handleFileRead(String path){
  587.   int upload_ = tft_num - 1;
  588.   if(upload_<0)
  589.     upload_ = 0;
  590.   path = "/loge"+String(upload_)+".jpg";//上传JPG文件
  591.   Serial.println("handleFileRead: " + path);
  592.   if(path.endsWith("/")) path += "index.htm";
  593.   String contentType = getContentType(path);
  594.   String pathWithGz = path + ".gz";
  595.   if(SD.exists(pathWithGz) || SD.exists(path)){
  596.     if(SD.exists(pathWithGz))
  597.       path += ".gz";
  598.     File file = SD.open(path, "r");
  599.     size_t sent = server.streamFile(file, contentType);
  600.     file.close();
  601.     upload_flag = false;//完成一次写入
  602.     return true;
  603.   }
  604.   upload_flag = false;//完成一次写入
  605.   return false;
  606. }
  607. //####################################################################################################
  608. // 文件上传SD卡
  609. //####################################################################################################
  610. void handleFileUpload(){//网络服务处理函数
  611.   upload_flag = true;//正在进行上传
  612.   if(server.uri() != "/") return;
  613.   HTTPUpload& upload = server.upload();
  614.   String filename;
  615.   char *file_sd;
  616.   if(upload.status == UPLOAD_FILE_START){//开启下载上传的文件
  617.     filename = upload.filename;
  618.     if(!filename.startsWith("/"))
  619.     {
  620.       filename = "/loge"+String(tft_num)+".jpg";//如果文件开头没有/则添加/ 并且对该图片添加计数尾缀
  621.       tft_num++;//文件数+1
  622.       EEPROM.write(20,tft_num);//将数据保存
  623.       EEPROM.commit();
  624.     }
  625.     Serial.print("handleFileUpload Name: "); Serial.println(filename);//打印文件名
  626.    
  627.     SD.remove(filename);
  628.     fsUploadFile = SD.open(filename, "w");//将上传的文件保存
  629.     filename = String();
  630.   } else if(upload.status == UPLOAD_FILE_WRITE){
  631.     if(fsUploadFile)
  632.       fsUploadFile.write(upload.buf, upload.currentSize);//将上传文件写入SD卡
  633.   } else if(upload.status == UPLOAD_FILE_END){
  634.     if(fsUploadFile)
  635.       fsUploadFile.close();
  636.   }
  637. }
  638. //####################################################################################################
  639. // 加载网页
  640. //####################################################################################################
  641. void handleRoot(){
  642.   upload_flag = true;//进入上传就绪状态(打开了网页)
  643.   server.send(200, "text/html", mainPageString);
  644.   server.client().stop();
  645. }
  646. //####################################################################################################
  647. // 上传完成函数
  648. //####################################################################################################
  649. void uplaodFinish(){
  650.   server.send(200, "text/html", uploadString);//重新发送网页
  651.   upload_flag = true;//上传完成,但是网页回复仍未完成
  652. }
  653. //####################################################################################################
  654. // 限幅函数
  655. //####################################################################################################
  656. uint8_t limit(){
  657.   if(flag_pic >= tft_num)
  658.   {
  659.     flag_pic = flag_pic - tft_num;
  660.   }
  661.   else if(flag_pic < 0)
  662.   {
  663.     flag_pic = flag_pic + tft_num;
  664.   }
  665. }
  666. //####################################################################################################
  667. // 文件格式获取
  668. //####################################################################################################
  669. String getContentType(String filename){
  670.   if(server.hasArg("download")) return "application/octet-stream";
  671.   else if(filename.endsWith(".htm")) return "text/html";
  672.   else if(filename.endsWith(".html")) return "text/html";
  673.   else if(filename.endsWith(".css")) return "text/css";
  674.   else if(filename.endsWith(".js")) return "application/javascript";
  675.   else if(filename.endsWith(".png")) return "image/png";
  676.   else if(filename.endsWith(".gif")) return "image/gif";
  677.   else if(filename.endsWith(".jpg")) return "image/jpeg";
  678.   else if(filename.endsWith(".ico")) return "image/x-icon";
  679.   else if(filename.endsWith(".xml")) return "text/xml";
  680.   else if(filename.endsWith(".pdf")) return "application/x-pdf";
  681.   else if(filename.endsWith(".zip")) return "application/x-zip";
  682.   else if(filename.endsWith(".gz")) return "application/x-gzip";
  683.   return "text/plain";
  684. }
  685. //####################################################################################################
  686. // 初始化函数
  687. //####################################################################################################
  688. void setup() {
  689.   mpu6050_setup();
  690.   SD_setup();
  691.   TFT_setup();
  692.   magic();  
  693.   WIFI_setup();
  694.   client.setTimeout(5000);//设置天气服务器连接超时时间
  695.   //EEPROM
  696.   EEPROM.begin(512);
  697.   tft_num =  EEPROM.read(20);
  698.   Serial.print("the tft number is");Serial.println(tft_num);
  699.   WEB_setup();
  700.   
  701. }
  702. //####################################################################################################
  703. // 主循环
  704. //####################################################################################################
  705. void loop(){
  706.   if(upload_flag == false)
  707.   {
  708.     if(flag_finsh == 0)//页面未加载
  709.     {
  710.       switch(flag_page % 2)
  711.       {
  712.         case 0://天气界面
  713.         {
  714.           flag_finsh = 1;//完成加载
  715.           weather_api();
  716.         }
  717.         break;
  718.         case 1://照片界面
  719.         {
  720.           flag_finsh = 1;//完成加载
  721.           limit();//形成循环
  722.           jpg_draw(flag_pic);
  723.         }
  724.         break;
  725.       }
  726.     }
  727.     else if(flag_finsh == 1)//页面已加载,进入扫描 和网络服务处理
  728.     {
  729.       mpu_update(100);
  730.         server.handleClient();
  731.         flag_finsh =0;
  732.       }
  733.     }
  734.   if(upload_flag == true)//防止未上传超时
  735.   {
  736.     t++;
  737.     delay(5);
  738.     server.handleClient();//上传图片服务处理
  739.   }
  740.   else
  741.   {
  742.     t=0;
  743.   }

  744.   if(t > 6000)
  745.   {
  746.     upload_flag = false;
  747.     t = 0;
  748.   }
  749.   Serial.print(t);
  750. }
复制代码

读取SD卡

读取SD卡
发表于 2022-5-17 22:10 | 显示全部楼层
发表于 2022-5-17 22:13 | 显示全部楼层
 楼主| 发表于 2022-5-18 17:28 | 显示全部楼层
topdog 发表于 2022-5-17 22:10
https://www.arduino.cn/thread-108079-1-1.html

谢谢,不过我想看的是批量显示图片,不是只显示一张,我没有看出我写的代码有哪些问题
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 05:40 , Processed in 0.088805 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表