亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

Arduino 2.4″ TFT LCD 扩展板显示 SD 卡 BMP 图片教程

元件清单

Arduino UNO×1
2.4 英寸 TFT LCD 触摸扩展板(含 SD 卡槽)×1
Micro SD 卡(FAT32 格式)×1

项目简介

本教程延续前两期《2.4″ TFT LCD 扩展板接线与触摸修正》和《绘图与触摸按钮实现》,重点讲解如何从 SD 卡读取 BMP 图片并在屏幕上显示。

准备工作

  1. 将 SD 卡插入电脑,格式化为 FAT32
  2. 准备 24 位 BMP 格式图片,分辨率需匹配屏幕方向:
    • setRotation(0)(默认竖屏):240×320 像素
    • setRotation(1)(横屏):320×240 像素
  3. 将图片复制到 SD 卡根目录,记下文件名(如 Img1.bmp)
  4. 将 SD 卡插入扩展板卡槽
  5. Arduino 2.4″ TFT LCD 扩展板显示 SD 卡 BMP 图片教程
    Arduino 2.4″ TFT LCD 扩展板显示 SD 卡 BMP 图片教程

    库文件

    使用 SPFD5408_Adafruit_GFX 与 SPFD5408_Adafruit_TFTLCD 库(随教程提供)。若示例代码出现白屏,请尝试更换适配你屏幕驱动 IC 的库版本。

    代码示例 1:循环播放多张图片

    #include <SPFD5408_Adafruit_GFX.h>
    #include <SPFD5408_Adafruit_TFTLCD.h>
    #include <SPI.h>
    #include <SD.h>
    
    #define LCD_CS A3
    #define LCD_CD A2
    #define LCD_WR A1
    #define LCD_RD A0
    #define SD_CS 10
    
    Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4);
    
    void setup() {
      Serial.begin(9600);
      tft.reset();
      uint16_t identifier = tft.readID();
      pinMode(10, OUTPUT); digitalWrite(10, HIGH);
      tft.begin(identifier);
      if (!SD.begin(SD_CS)) { progmemPrintln(PSTR("failed!")); return; }
    }
    
    void loop() {
      bmpDraw("Logo.bmp", 0, 0); delay(2000);
      bmpDraw("Img2.bmp", 0, 0); delay(2000);
      bmpDraw("Img3.bmp", 0, 0); delay(2000);
    }
    
    // BMP 绘制核心函数(勿动)
    #define BUFFPIXEL 20
    void bmpDraw(char *filename, int x, int y) {
      File bmpFile;
      int bmpWidth, bmpHeight;
      uint8_t bmpDepth;
      uint32_t bmpImageoffset, rowSize;
      uint8_t sdbuffer[3*BUFFPIXEL];
      uint16_t lcdbuffer[BUFFPIXEL];
      uint8_t buffidx = sizeof(sdbuffer);
      boolean goodBmp = false, flip = true;
      int w, h, row, col;
      uint8_t r, g, b;
      uint32_t pos = 0, startTime = millis();
      uint8_t lcdidx = 0;
      boolean first = true;
    
      if((x >= tft.width()) || (y >= tft.height())) return;
    
      Serial.println(); progmemPrint(PSTR("Loading image '")); Serial.print(filename); Serial.println("'");
    
      if ((bmpFile = SD.open(filename)) == NULL) { progmemPrintln(PSTR("File not found")); return; }
    
      if(read16(bmpFile) == 0x4D42) { // BMP 签名
        progmemPrint(PSTR("File size: ")); Serial.println(read32(bmpFile));
        (void)read32(bmpFile); // 忽略创建者字节
        bmpImageoffset = read32(bmpFile);
        progmemPrint(PSTR("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
        progmemPrint(PSTR("Header size: ")); Serial.println(read32(bmpFile));
        bmpWidth = read32(bmpFile); bmpHeight = read32(bmpFile);
    
        if(read16(bmpFile) == 1) { // 平面数=1
          bmpDepth = read16(bmpFile);
          progmemPrint(PSTR("Bit Depth: ")); Serial.println(bmpDepth);
          if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 24位无压缩
            goodBmp = true;
            progmemPrint(PSTR("Image size: ")); Serial.print(bmpWidth); Serial.print('x'); Serial.println(bmpHeight);
            rowSize = (bmpWidth * 3 + 3) & ~3; // 4字节对齐
    
            if(bmpHeight < 0) { bmpHeight = -bmpHeight; flip = false; }
    
            w = bmpWidth; h = bmpHeight;
            if((x+w-1) >= tft.width()) w = tft.width() - x;
            if((y+h-1) >= tft.height()) h = tft.height() - y;
    
            tft.setAddrWindow(x, y, x+w-1, y+h-1);
    
            for (row=0; row= sizeof(sdbuffer)) {
                  if(lcdidx > 0) { tft.pushColors(lcdbuffer, lcdidx, first); lcdidx = 0; first = false; }
                  bmpFile.read(sdbuffer, sizeof(sdbuffer)); buffidx = 0;
                }
                b = sdbuffer[buffidx++]; g = sdbuffer[buffidx++]; r = sdbuffer[buffidx++];
                lcdbuffer[lcdidx++] = tft.color565(r,g,b);
              }
            }
            if(lcdidx > 0) tft.pushColors(lcdbuffer, lcdidx, first);
            progmemPrint(PSTR("Loaded in ")); Serial.print(millis() - startTime); Serial.println(" ms");
          }
        }
      }
      bmpFile.close();
      if(!goodBmp) progmemPrintln(PSTR("BMP format not recognized."));
    }
    
    // 读取 16/32 位小端数据
    uint16_t read16(File f) { uint16_t result; ((uint8_t *)&result)[0] = f.read(); ((uint8_t *)&result)[1] = f.read(); return result; }
    uint32_t read32(File f) { uint32_t result; ((uint8_t *)&result)[0] = f.read(); ((uint8_t *)&result)[1] = f.read(); ((uint8_t *)&result)[2] = f.read(); ((uint8_t *)&result)[3] = f.read(); return result; }
    
    void progmemPrint(const char *str) { char c; while(c = pgm_read_byte(str++)) Serial.print(c); }
    void progmemPrintln(const char *str) { progmemPrint(str); Serial.println(); }
    

    代码示例 2:触摸切换图片(幻灯片模式)

    #include <SPFD5408_Adafruit_GFX.h>
    #include <SPFD5408_Adafruit_TFTLCD.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SPFD5408_TouchScreen.h>
    
    #if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
    #endif
    
    // 触摸屏引脚(根据你的扩展板调整)
    #define YP A3
    #define XM A2
    #define YM 9
    #define XP 8
    
    // 触摸校准值(需先运行校准程序获取)
    #define TS_MINX 176
    #define TS_MINY 159
    #define TS_MAXX 921
    #define TS_MAXY 884
    #define MINPRESSURE 10
    #define MAXPRESSURE 1000
    
    TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
    
    #define LCD_CS A3
    #define LCD_CD A2
    #define LCD_WR A1
    #define LCD_RD A0
    #define SD_CS 10
    
    Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, A4);
    char x[] = "x1.bmp"; // 文件名数组,通过修改 x[1] 实现 x1~x4.bmp 切换
    
    void setup() {
      Serial.begin(9600);
      tft.reset();
      uint16_t identifier = tft.readID();
      pinMode(10, OUTPUT); digitalWrite(10, HIGH);
      tft.begin(identifier);
      if (!SD.begin(SD_CS)) { progmemPrintln(PSTR("failed!")); return; }
      tft.setRotation(1); // 横屏
      bmpDraw(x, 0, 0);
    }
    
    void loop() {
      // 限制文件名范围 x1~x4
      if(x[1] < '1') x[1] = '1';
      if(x[1] > '4') x[1] = '4';
    
      TSPoint p = ts.getPoint();
      pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); // 恢复引脚模式
    
      if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
        p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
        p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
    
        // 屏幕左右两侧作为翻页按钮
        if(p.y > 0 && p.y < 100) { // 左侧:上一张
          Serial.println("Left"); x[1]--; bmpDraw(x, 0, 0); delay(300);
        } else if(p.y > 200 && p.y < 320) { // 右侧:下一张
          Serial.println("Right"); x[1]++; bmpDraw(x, 0, 0); delay(300);
        }
      }
    }
    
    // bmpDraw 函数同示例 1,此处省略
    

    接线说明

    本扩展板直插 Arduino UNO,无需额外接线。LCD 控制引脚固定为 A0-A3,SD 卡片选引脚为 D10,触摸屏使用 A2、A3、D8、D9。

制造工艺

  1. 贺卡产业:历史、生产与未来趋势
  2. 信用卡:历史、设计、制造与未来趋势
  3. 液晶显示器(LCD):技术、制造与未来展望
  4. Primal Display:树莓派 LCD 温度监测仪
  5. Kuman 3.5″ TFT 显示屏在 RetroPie 上安装全步骤指南
  6. ILI9341 2.4 英寸 TFT 触摸屏扩展板位图动画专业指南
  7. DIY 蓝牙控制 Arduino 间谍小车
  8. DIY Arduino LCD 游戏机:16x2 字符屏打造“躲避防守队员”足球小游戏
  9. AI从文本食谱生成逼真菜肴图片:Stacked GAN跨模态嵌入新突破
  10. DATA MODUL 推出 23.1 英寸超薄 TFT 显示器,支持智能 Wi-Fi 控制
  11. Distec 推出 Ortustech 7 英寸半透反射式 TFT 显示屏:坚固耐用、阳光下可读、低功耗
  12. Nuvo-7160GC:坚固 GPU PC 交付 6 TFLOPS、支持 120W GPU 与 4K 输出,面向机器视觉、VR 与自动化