ESP32从SD卡读取jpg显示去tft屏 一直重启-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3090|回复: 6

[未解决] ESP32从SD卡读取jpg显示去tft屏 一直重启

[复制链接]
发表于 2021-8-9 20:55 | 显示全部楼层 |阅读模式
代码从作者那拷贝过来的,只做了引脚定义的修改。

#define TFT_DC    27
#define TFT_RST   26
#define TFT_CS    5  
#define TFT_MOSI  23  
#define TFT_SCLK  18   

屏幕是ST7789的SPI屏

/*
*@功能:ESP32读取SD卡图片显示在1.14IPS屏幕上
*@作者:刘泽文
*@时间:2020/3/27
*/

//引用相关库
#include <SD.h>
#include <FS.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include <JPEGDecoder.h>


#define DEBUG

#ifdef DEBUG
#define DebugPrintln(message) Serial.println(message)
#else
#define DebugPrintln(message)
#endif

#ifdef DEBUG
#define DebugPrint(message) Serial.print(message)
#else
#define DebugPrint(message)
#endif

TFT_eSPI tft = TFT_eSPI(); // Invoke custom library

void drawSdJpeg(const char *filename, int xpos, int ypos);
void jpegRender(int xpos, int ypos);
void jpegInfo();
void showTime(uint32_t msTime);
void SD_read_Time(uint32_t msTime);

void setup()
{
  Serial.begin(9600);
  DebugPrintln();

  tft.init();
  SPIClass sdSPI(VSPI);
#define SD_MISO     13
#define SD_MOSI     12
#define SD_SCLK     17
#define SD_CS       14

  tft.setRotation(2);
  tft.fillScreen(TFT_WHITE);
  tft.setTextSize(1);
  tft.setTextColor(TFT_MAGENTA);
  tft.setCursor(0, 0);
  tft.setTextDatum(MC_DATUM);
  tft.setTextSize(1);
  tft.setSwapBytes(true);
  delay(500);



  //挂载文件系统
  sdSPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS, sdSPI))
  {
    DebugPrintln("存储卡挂载失败");
    return;
  }
  uint8_t cardType = SD.cardType();

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

  //打印存储卡信息
  Serial.printf("存储卡总大小是: %lluMB \n", SD.cardSize() / (1024 * 1024)); // "/ (1024 * 1024)"可以换成">> 20"
  Serial.printf("文件系统总大小是: %lluB \n", SD.totalBytes());
  Serial.printf("文件系统已用大小是: %lluB \n", SD.usedBytes());


   //测试壁纸
  for(int image_num = 1;image_num<=20;image_num++){
    char FileName[15];
    sprintf(FileName,"/gif/%d.jpg",image_num);
    drawSdJpeg(FileName, 0, 0);     // This draws a jpeg pulled off the SD Card
    //delay(00);
  }


}

void loop() {

}

void drawSdJpeg(const char *filename, int xpos, int ypos) {
  uint32_t readTime = millis();
  // Open the named file (the Jpeg decoder library will close it)
  File jpegFile = SD.open( filename, FILE_READ);  // or, file handle reference for SD library

  if ( !jpegFile ) {
    DebugPrint("ERROR: File \"");
    DebugPrint(filename);
    DebugPrintln ("\" not found!");
    return;
  }

  DebugPrintln("===========================");
  DebugPrint("Drawing file: "); DebugPrintln(filename);
  DebugPrintln("===========================");

  // 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)
  SD_read_Time(millis() - readTime);

  if (decoded) {
    // print information about the image to the serial port
    jpegInfo();
    // render the image onto the screen at given coordinates
    jpegRender(xpos, ypos);
  }
  else {
    DebugPrintln("Jpeg file format not supported!");
  }
}

//####################################################################################################
// Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit
//####################################################################################################
// This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not
// fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders.
void jpegRender(int xpos, int ypos) {
  // record the current time so we can measure how long it takes to draw an image
  uint32_t drawTime = millis();

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

  uint16_t *pImg;
  uint16_t mcu_w = JpegDec.MCUWidth;
  uint16_t mcu_h = JpegDec.MCUHeight;
  uint32_t max_x = JpegDec.width;
  uint32_t max_y = JpegDec.height;

  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 = (mcu_w<(max_x % mcu_w)?mcu_wmax_x % mcu_w));
  uint32_t min_h = (mcu_h<(max_y % mcu_h)?mcu_hmax_y % mcu_h));

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

  // 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);

  showTime(millis() - drawTime); //将图片显示到屏幕所用的时间(ms)
}

void jpegInfo() {
  DebugPrintln("JPEG image info");
  DebugPrintln("===============");
  DebugPrint("Width      :");
  DebugPrintln(JpegDec.width);
  DebugPrint("Height     :");
  DebugPrintln(JpegDec.height);
  DebugPrint("Components :");
  DebugPrintln(JpegDec.comps);
  DebugPrint("MCU / row  :");
  DebugPrintln(JpegDec.MCUSPerRow);
  DebugPrint("MCU / col  :");
  DebugPrintln(JpegDec.MCUSPerCol);
  DebugPrint("Scan type  :");
  DebugPrintln(JpegDec.scanType);
  DebugPrint("MCU width  :");
  DebugPrintln(JpegDec.MCUWidth);
  DebugPrint("MCU height :");
  DebugPrintln(JpegDec.MCUHeight);
  DebugPrintln("===============");
  DebugPrintln("");
}

void showTime(uint32_t msTime) {
  DebugPrint(F(" JPEG drawn in "));
  DebugPrint(msTime);
  DebugPrintln(F(" ms "));
}

void SD_read_Time(uint32_t msTime) {
  Serial.print(F(" SD JPEG read in "));
  Serial.print(msTime);
  Serial.println(F(" ms "));
}



问题出在了
   //测试壁纸
  for(int image_num = 1;image_num<=20;image_num++){
    char FileName[15];
    sprintf(FileName,"/gif/%d.jpg",image_num);
    drawSdJpeg(FileName, 0, 0);     // This draws a jpeg pulled off the SD Card

   这段代码 放step()里面能够跑,哪怕for循环10次也可以。但是一放在loop里面 就会一直报错重启
求助 求助!!!!    解决了的话 可以发小红包


 楼主| 发表于 2021-8-9 21:15 | 显示全部楼层
AF⸮        ~S⸮1⸮!!!⸮4⸮J~⸮⸮ 9⸮%!⸮
Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400d9323  PS      : 0x00060130  A0      : 0x800d32d8  A1      : 0x3ffb0d70  
A2      : 0x3ffbdc88  A3      : 0x3ffb0dd9  A4      : 0x00000006  A5      : 0x00000040  
A6      : 0x00000010  A7      : 0x3ffb0060  A8      : 0x00000002  A9      : 0x00000000  
A10     : 0x00000002  A11     : 0x43f64ffc  A12     : 0x00ffffff  A13     : 0x00ffffff  
A14     : 0xff000000  A15     : 0x00000006  SAR     : 0x0000000a  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00ffffff  LBEG    : 0x400d94d4  LEND    : 0x400d9536  LCOUNT  : 0x00000002  

ELF file SHA256: 0000000000000000

Backtrace: 0x400d9323:0x3ffb0d70 0x400d32d5:0x3ffb0d90 0x400d1a17:0x3ffb0db0 0x400d1bac:0x3ffb0e00 0x400d2099:0x3ffb0e20 0x400ecbc5:0x3ffb0e50 0x400e9b8c:0x3ffb0e70 0x400eb0a8:0x3ffb0eb0 0x400d2411:0x3ffb0ef0 0x400d1640:0x3ffb1f30 0x400d1130:0x3ffb1f60 0x400d9f22:0x3ffb1fb0 0x400862a9:0x3ffb1fd0

  这个是报错信息
 楼主| 发表于 2021-8-9 21:29 | 显示全部楼层
大佬呢 大佬呢
 楼主| 发表于 2021-8-10 12:02 | 显示全部楼层
y有人吗有人吗
发表于 2021-8-11 08:14 | 显示全部楼层

回帖奖励 +1 金币

666666666666
发表于 2021-8-24 13:58 | 显示全部楼层
程序中SD卡用的是VSPI,但是TFT-eSPI默认用的也是VSPI,这样造成冲突。
应该在User_Setup.h文件中启用HSPI选项。
// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default.
// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam)
// then uncomment the following line:
#define USE_HSPI_PORT

点评

SPI可以挂多个设备。。。。。只要CS分别控制即可  发表于 2021-8-24 14:07
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-11-29 01:35 , Processed in 0.081048 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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