ESP32-S3, 教學資訊

【ESP32-S3 教學】ESP32-S3 + ILI9341 2.8吋觸控螢幕製作打地鼠遊戲|Arduino IDE 從接線、觸控校正到遊戲實作完整教學

DIY ESP32 Whack-a-Mole game on ILI9341 TFT touch screen display fully wired hardware circuit

使用 ESP32-S3 與 2.8吋 ILI9341 觸控螢幕製作互動小遊戲

想學習 ESP32-S3 圖形介面開發嗎?本篇教學將帶您使用 ESP32-S3 搭配 2.8 吋 ILI9341 TFT 觸控螢幕,打造一款經典的「打地鼠遊戲(Whack-a-Mole)」。

透過本教學,您將學會:

  • ESP32-S3 SPI TFT 螢幕驅動
  • ILI9341 顯示器設定
  • XPT2046 觸控控制器應用
  • TFT_eSPI 函式庫使用技巧
  • 觸控座標校正
  • 遊戲介面設計
  • 觸控事件判斷
  • Arduino IDE 開發流程

 

本次使用硬體

ESP32-S3 N16R8 開發板

ESP32-S3 N16R8 開發板

特色:

  • 雙核心 Xtensa LX7
  • WiFi + Bluetooth
  • 16MB Flash
  • 8MB PSRAM
  • 支援 Arduino IDE
  • 適合 GUI 與 IoT 專案

2.8吋 ILI9341 TFT 觸控螢幕

2.8吋 ILI9341 SPI TFT 觸控螢幕

規格:

  • 解析度:240×320
  • 驅動 IC:ILI9341
  • 觸控 IC:XPT2046
  • SPI 介面
  • 支援 MicroSD

 

專案成果展示

本專案完成後可實現:

✅ 隨機地鼠出現

✅ 觸控擊打得分

✅ 30秒倒數計時

✅ 遊戲結束畫面

✅ 最終分數統計

 

Arduino IDE 環境配置與程式庫安裝

Step1 安裝 Arduino IDE

建議版本:

  • Arduino IDE :1.8.19
  • ESP32 Core :2.0.13

Step2 安裝函式庫

在開始編寫程式之前,我們需要安裝專門處理觸控螢幕的第三方程式庫。

建議版本:

  • TFT_eSPI :2.4.79
  • XPT2046_Touchscreen:1.4

 

TFT_eSPI :

  1. 開啟您的 Arduino IDE 開發環境。

  2. 點選左側的「程式庫管理員」圖示(或至選單:工具 > 管理程式庫)。

  3. 在搜尋欄輸入 TFT_eSPI

  4. 找到對應的程式庫後,選擇2.4.79版本,點選 [安裝]

XPT2046_Touchscreen:

  1. 開啟您的 Arduino IDE 開發環境。

  2. 點選左側的「程式庫管理員」圖示(或至選單:工具 > 管理程式庫)。

  3. 在搜尋欄輸入 XPT2046_Touchscreen。

  4. 找到對應的程式庫後,選擇1.4版本,點選 [安裝]

 

ESP32-S3 與 ILI9341 接線圖

TFT 顯示器接線:

TFT模組

ESP32-S3

VCC

3V3

GND

GND

LCD_CS

GPIO10

LCD_RST

GPIO14

LCD_RS(DC)

GPIO9

SDI(MOSI)

GPIO11

SCK

GPIO12

SDO(MISO)

GPIO13

LED

3V3

 

XPT2046 觸控接線(獨立 SPI):

TOUCH

ESP32-S3

T_CS

GPIO16

T_CLK

GPIO6

T_DIN

GPIO4

T_DO

GPIO5

T_IRQ

不接

 

Wiring diagram and SPI pinout mapping table for ESP32-S3 connected to ILI9341 TFT display and XPT2046 touch controller

TFT_eSPI 設定

找到:

Documents/Arduino/libraries/TFT_eSPI/User_Setup.h

修改:User_Setup.h

#define ILI9341_DRIVER

#define TFT_MISO 13
#define TFT_MOSI 11
#define TFT_SCLK 12

#define TFT_CS   10
#define TFT_DC   9
#define TFT_RST  14

#define SPI_FREQUENCY       40000000
#define SPI_READ_FREQUENCY  20000000

 

觸控校正程式 

程式載點:Touch Calibration Code

#include <SPI.h> 
#include <XPT2046_Touchscreen.h> 
#include <TFT_eSPI.h> 

TFT_eSPI tft = TFT_eSPI();

// Touch SPI
SPIClass touchSPI(FSPI);

#define TOUCH_SCLK 6
#define TOUCH_MISO 5
#define TOUCH_MOSI 4
#define TOUCH_CS   16

XPT2046_Touchscreen ts(TOUCH_CS);

void waitTouchRelease()
{
  while(ts.touched())
  {
    delay(10);
  }
}

void getCalibrationPoint(
  const char* text,
  int px,
  int py,
  uint16_t color,
  int &rawX,
  int &rawY
)
{
  tft.fillScreen(TFT_BLACK);

  tft.setTextColor(TFT_WHITE);
  tft.setTextSize(2);

  tft.drawString(text, 20, 20);

  tft.fillCircle(px, py, 10, color);

  while(!ts.touched())
  {
    delay(10);
  }

  TS_Point p = ts.getPoint();

  rawX = p.x;
  rawY = p.y;

  Serial.printf(
    "%s : X=%d Y=%d Z=%d\n",
    text,
    p.x,
    p.y,
    p.z
  );

  waitTouchRelease();

  delay(500);
}

void setup()
{
  Serial.begin(115200);

  tft.init();
  tft.setRotation(1);

  touchSPI.begin(
    TOUCH_SCLK,
    TOUCH_MISO,
    TOUCH_MOSI,
    TOUCH_CS
  );

  ts.begin(touchSPI);

  int x1,y1;
  int x2,y2;
  int x3,y3;
  int x4,y4;

  getCalibrationPoint(
    "Touch TOP LEFT",
    20,
    20,
    TFT_RED,
    x1,
    y1
  );

  getCalibrationPoint(
    "Touch TOP RIGHT",
    300,
    20,
    TFT_GREEN,
    x2,
    y2
  );

  getCalibrationPoint(
    "Touch BOTTOM LEFT",
    20,
    220,
    TFT_BLUE,
    x3,
    y3
  );

  getCalibrationPoint(
    "Touch BOTTOM RIGHT",
    300,
    220,
    TFT_YELLOW,
    x4,
    y4
  );

  tft.fillScreen(TFT_BLACK);

  Serial.println();
  Serial.println("===== Calibration Result =====");

  Serial.printf("TOP LEFT     : X=%d Y=%d\n", x1, y1);
  Serial.printf("TOP RIGHT    : X=%d Y=%d\n", x2, y2);
  Serial.printf("BOTTOM LEFT  : X=%d Y=%d\n", x3, y3);
  Serial.printf("BOTTOM RIGHT : X=%d Y=%d\n", x4, y4);

  Serial.println("==============================");

  tft.drawString("Calibration Done", 50, 100);
}

void loop()
{
}

 

點擊四角:

TOP LEFT
TOP RIGHT
BOTTOM LEFT
BOTTOM RIGHT

觸控校正數值

實測校正結果:

#define TS_MINX 608
#define TS_MAXX 3714

#define TS_MINY 544
#define TS_MAXY 3545

 

轉換為螢幕座標:

int tx = map(
p.x,
TS_MAXX,
TS_MINX,
0,
320
);
  
int ty = map(
p.y,
TS_MAXY,
TS_MINY,
0,
240
);

 

打地鼠遊戲核心功能

程式載點:Whack A Mole Code

洞穴繪製

tft.fillCircle(x, y, 35, TFT_DARKGREY);

 

地鼠繪製

tft.fillCircle(x, y, 28, TFT_BROWN);

 

擊中判斷

int dx = tx - holes[moleIndex].x;
int dy = ty - holes[moleIndex].y;

if ((dx * dx + dy * dy) < 900)
{
    score++;
}

 

倒數計時

int remain =
30 - ((millis() - gameStart) / 1000);

 

遊戲結束

if ((millis() - gameStart) >= 30000)
{
    showGameOver();
}

 

常見問題 FAQ

ILI9341 螢幕沒有顯示?

請確認:

  • TFT_CS 腳位正確
  • TFT_DC 腳位正確
  • TFT_eSPI 設定檔已修改
  • SPI 頻率未設過高

XPT2046 觸控沒反應?

請確認:

  • T_CS 是否正確
  • 是否執行校正程式
  • Touch SPI 是否獨立設定

為什麼 ESP32-S3 與 XPT2046 要分開 SPI?

原因是部分 ILI9341 模組共用 SPI 容易造成:

  • 螢幕閃爍
  • 觸控失效
  • 座標飄移

採用獨立 SPI 可提高穩定度。

 

結語

透過本教學,您已成功使用 ESP32-S3 搭配 ILI9341 觸控螢幕完成一個互動式打地鼠遊戲。不僅學會 TFT 圖形介面設計,也掌握了 XPT2046 觸控應用技巧,未來可延伸至智慧家居控制面板、IoT 顯示器、教育互動設備、AI 人機介面等各種專案。

更多 ESP32、Arduino、樹莓派與電子模組教學,歡迎持續關注:

** 米羅科技 Mirotek**