// 引入SD卡功能库 - 让开发板能读取SD卡中的文件
#include <SD.h>       // 提供SD卡文件系统操作功能
#include <SPI.h>      // SPI通信协议库,用于与SD卡通信
#include <TFT_eSPI.h> // TFT显示屏驱动库
#include <TJpg_Decoder.h> // JPEG图片解码库

#define SD_CS 5           // 定义SD卡的片选引脚为5号
const int maxFiles = 100;  // 最多存储100个图片文件名

TFT_eSPI tft = TFT_eSPI(); // 创建显示屏对象
String jpgFiles[maxFiles];  // 存储JPG文件名称的数组

int fileCount = 0;         // 当前找到的JPG文件数量
String folder = "/test";   // 图片存放的文件夹路径

// JPEG解码回调函数,将解码后的图像块显示到屏幕
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap) {
  if (y >= tft.height()) return 0;  // 如果图像超出屏幕底部则停止解码
  tft.pushImage(x, y, w, h, bitmap); // 将图像块推送到屏幕指定位置
  return 1;                          // 返回继续解码信号
}

// 遍历指定文件夹,查找并记录所有JPG文件
void listJpgFiles(String dir) {
  File root = SD.open(dir);         // 打开指定目录
  if (!root) {                      // 检查目录是否成功打开
    Serial.println("文件夹打开失败"); // 打印错误信息
    return;                         // 目录打开失败则退出函数
  }

  Serial.println("正在扫描JPG文件:"); // 提示开始扫描文件
  
  while (true) {                    // 无限循环,直到遍历完所有文件
    File file = root.openNextFile(); // 获取下一个文件
    if (!file) break;               // 没有更多文件时退出循环
    
    // 检查是否为文件且为JPG格式
    if (!file.isDirectory() && isJpgFile(file.name())) {
      Serial.print("找到文件: ");     // 打印找到的文件名
      Serial.println(file.name());
      
      if (fileCount < maxFiles) {     // 检查是否超过最大文件数
        jpgFiles[fileCount] = file.name(); // 保存文件名到数组
        fileCount++;                 // 文件计数加1
      } else {
        Serial.println("已达到最大文件数限制"); // 提示文件数量已达上限
        break;                       // 退出循环
      }
    }
    file.close();                    // 关闭当前文件
  }
  root.close();                      // 关闭目录
}

// 缩放并显示指定路径的JPG图片
void scalePic(String fileName) {
  tft.fillScreen(TFT_BLACK);         // 清屏为黑色
  
  uint16_t w = 0, h = 0;             // 定义变量存储图片宽高
  TJpgDec.getSdJpgSize(&w, &h, fileName); // 获取图片尺寸
  
  Serial.print("图片尺寸: ");         // 打印图片原始尺寸
  Serial.print(w);
  Serial.print("x");
  Serial.println(h);
  
  // 计算图片高度与屏幕高度的比例
  float heightRatio = static_cast<float>(h) / tft.height();
  
  // 根据比例设置缩放因子
  if (heightRatio > 4) {
    TJpgDec.setJpgScale(8);          // 高度超过屏幕4倍时,缩放8倍
  } else if (heightRatio > 2) {
    TJpgDec.setJpgScale(4);          // 高度超过屏幕2倍时,缩放4倍
  } else if (heightRatio > 1) {
    TJpgDec.setJpgScale(2);          // 高度超过屏幕时,缩放2倍
  } else {
    TJpgDec.setJpgScale(1);          // 高度小于屏幕时,不缩放
  }
  
  Serial.print("缩放比例: ");         // 打印缩放比例
  Serial.println(heightRatio);
  
  // 从SD卡读取并绘制JPG图片,从坐标(0,0)开始
  TJpgDec.drawSdJpg(0, 0, fileName);
}

// 判断文件是否为JPG格式
bool isJpgFile(String name) {
  // 检查文件名是否以常见JPG扩展名结尾,且不是隐藏文件
  return !name.startsWith(".") && 
         (name.endsWith(".jpg") || name.endsWith(".JPG") || 
          name.endsWith(".jpeg") || name.endsWith(".JPEG"));
}

// 开发板启动时执行的初始化函数
void setup() {
  Serial.begin(115200);              // 初始化串口通信,波特率115200
  
  SPI.begin();                       // 初始化SPI通信
  if (!SD.begin(SD_CS)) {            // 初始化SD卡
    Serial.println("SD卡初始化失败");  // SD卡初始化失败提示
    return;                          // 失败则退出setup函数
  }
  Serial.println("SD卡初始化成功");    // SD卡初始化成功提示
  
  tft.begin();                       // 初始化TFT显示屏
  tft.fillScreen(TFT_BLACK);         // 清屏为黑色
  tft.setSwapBytes(true);            // 设置字节交换,确保颜色显示正确
  tft.setRotation(0);                // 设置屏幕旋转角度为0度
  
  // 设置JPEG解码器的回调函数为tft_output
  TJpgDec.setCallback(tft_output);
  
  // 扫描指定文件夹中的JPG文件
  listJpgFiles(folder);
  Serial.print("共找到 ");           // 打印找到的文件数量
  Serial.print(fileCount);
  Serial.println(" 个JPG文件");
}

// 开发板主循环,不断重复执行
void loop() {
  // 遍历所有找到的JPG文件
  for (int i = 0; i < fileCount; i++) {
    String filePath;
    
    // 构建完整文件路径
    if (folder == "/") {
      filePath = "/" + jpgFiles[i];  // 根目录下的文件
    } else {
      filePath = folder + "/" + jpgFiles[i]; // 子目录下的文件
    }
    
    scalePic(filePath);              // 显示当前图片
    Serial.print("显示图片: ");       // 打印当前显示的图片名称
    Serial.println(filePath);
    
    delay(5000);                     // 延时5秒后切换下一张
  }
}

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐