ywxywx_ 2025-10-31 21:18 采纳率: 53.3%
浏览 4
已结题

TFT显示屏与ESP32连接白屏


#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "SPI.h"
#include "TFT_eSPI.h"
#include "U8g2_for_TFT_eSPI.h"

// ------------------- 手动定义颜色(解决TFT_DARKBLUE未定义问题) -------------------
#define TFT_DARKBLUE 0x0010  // 自定义深蓝色(RGB565格式:0x0010)
#define TFT_CYAN     0x07FF  // 青色
#define TFT_GREEN    0x07E0  // 绿色
#define TFT_RED      0xF800  // 红色
#define TFT_WHITE    0xFFFF  // 白色
#define TFT_BLACK    0x0000  // 黑色

// ------------------- 屏幕与触摸引脚配置(修正冲突+对齐手册) -------------------
#define ILI9341_DRIVER
#define TFT_WIDTH  320 
#define TFT_HEIGHT 240 

#define TFT_MISO 19          // 对应模块SDO(MISO),无需读取可悬空
#define TFT_MOSI 4           // 对应模块SDI(MOSI),手册提示部分板标注"SDA"
#define TFT_SCLK 5           // 对应模块SCK,SPI时钟
#define TFT_CS   17          // 修正:原16与水泵引脚冲突,改为ESP32-S3空闲引脚17(模块CS)
#define TFT_DC   6           // 对应模块DC/RS,数据/命令控制
#define TFT_RST  -1          // 复位引脚,可接ESP32-S3复位引脚(-1=不单独接)
#define TFT_BL   7           // 对应模块LED,背光控制(高电平点亮)
#define TFT_BACKLIGHT_ON HIGH
#define TOUCH_CS 15          // 对应模块T_CS,触摸屏片选

TFT_eSPI tft = TFT_eSPI();  // 屏幕对象
U8g2_for_TFT_eSPI u8f;      // 字体对象
#define FONT u8g2_font_wqy16_t_gb2312  // 中文字体

// ------------------- 水泵控制引脚(原16无冲突,保留) -------------------
#define PUMP_PIN 16          // 水泵继电器控制引脚(已避开TFT_CS)
const unsigned long WATER_DURATION = 4000;  // 加水时长4秒
bool isWatering = false;                    // 加水状态
unsigned long waterStartTime = 0;           // 加水开始时间

// ------------------- 加水按钮区域 -------------------
#define WATER_BTN_X1 220    // 按钮左上角X
#define WATER_BTN_Y1 180    // 按钮左上角Y
#define WATER_BTN_X2 300    // 按钮右下角X
#define WATER_BTN_Y2 230    // 按钮右下角Y

// ------------------- 触摸校准参数 -------------------
#define TOUCH_MIN_X 370
#define TOUCH_MAX_X 3551
#define TOUCH_MIN_Y 237
#define TOUCH_MAX_Y 3612

// ------------------- WiFi配置 -------------------
const char* ssid = "Galaxy S22 Ultra";
const char* password = "11223344";

// ------------------- NTP时间配置 -------------------
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 8 * 3600, 60000);  // 时区+8

// ------------------- 功能函数(无修改) -------------------
// 绘制加水按钮
void drawWaterButton() {
  if (isWatering) {
    tft.fillRoundRect(WATER_BTN_X1, WATER_BTN_Y1, 
                     WATER_BTN_X2 - WATER_BTN_X1, 
                     WATER_BTN_Y2 - WATER_BTN_Y1, 10, TFT_RED);
    u8f.setBackgroundColor(TFT_RED);
    u8f.setCursor(WATER_BTN_X1 + 10, WATER_BTN_Y1 + 30);
    u8f.print("加水中");
  } else {
    tft.fillRoundRect(WATER_BTN_X1, WATER_BTN_Y1, 
                     WATER_BTN_X2 - WATER_BTN_X1, 
                     WATER_BTN_Y2 - WATER_BTN_Y1, 10, TFT_DARKBLUE);
    u8f.setBackgroundColor(TFT_DARKBLUE);
    u8f.setCursor(WATER_BTN_X1 + 5, WATER_BTN_Y1 + 30);
    u8f.print("点击加水");
  }
  u8f.setForegroundColor(TFT_WHITE);
}

// 显示当前时间
void drawTime() {
  String timeStr = timeClient.getFormattedTime();
  String dateStr;
  
  unsigned long epochTime = timeClient.getEpochTime();
  struct tm *ptm = gmtime((time_t *)&epochTime);
  int month = ptm->tm_mon + 1;
  int day = ptm->tm_mday;
  int weekday = ptm->tm_wday;
  const char* weekdays[] = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
  
  dateStr = String(month) + "月" + String(day) + "日 " + weekdays[weekday];
  
  tft.fillRect(10, 60, 200, 60, TFT_BLACK);
  
  u8f.setBackgroundColor(TFT_BLACK);
  u8f.setForegroundColor(TFT_CYAN);
  u8f.setFont(u8g2_font_logisoso32_tf);
  u8f.setCursor(10, 90);
  u8f.print(timeStr);
  
  u8f.setFont(FONT);
  u8f.setForegroundColor(TFT_GREEN);
  u8f.setCursor(10, 120);
  u8f.print(dateStr);
}

// 开始加水
void startWatering() {
  if (isWatering) return;
  isWatering = true;
  waterStartTime = millis();
  digitalWrite(PUMP_PIN, LOW);
  drawWaterButton();
}

// 停止加水
void stopWatering() {
  isWatering = false;
  digitalWrite(PUMP_PIN, HIGH);
  drawWaterButton();
}

// 触摸检测
void checkTouch() {
  uint16_t x = 0, y = 0;
  if (tft.getTouch(&x, &y)) {
    x = 320 - x;
    y = 240 - y;
    
    if (x >= WATER_BTN_X1 && x <= WATER_BTN_X2 && 
        y >= WATER_BTN_Y1 && y <= WATER_BTN_Y2) {
      if (!isWatering) startWatering();
    }
  }
}

void setup() {
  Serial.begin(115200);
  
  // 初始化水泵引脚
  pinMode(PUMP_PIN, OUTPUT);
  digitalWrite(PUMP_PIN, HIGH);

  // 初始化屏幕(添加背光控制初始化)
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);  // 点亮背光
  tft.begin();
  uint16_t calData[5] = {370, 3551, 237, 3612, 7};
  tft.setTouch(calData);
  tft.setRotation(3);
  tft.fillScreen(TFT_BLACK);
  
  // 初始化字体
  u8f.begin(tft);
  u8f.setFont(FONT);
  u8f.setForegroundColor(TFT_WHITE);

  // 连接WiFi
  tft.fillRoundRect(0, 0, 320, 40, 8, TFT_DARKBLUE);
  u8f.setBackgroundColor(TFT_DARKBLUE);
  u8f.setCursor(10, 30);
  u8f.print("连接WiFi中...");
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  // WiFi连接成功
  tft.fillRoundRect(0, 0, 320, 40, 8, TFT_DARKBLUE);
  u8f.setCursor(10, 30);
  u8f.print("WiFi已连接");
  delay(1000);
  
  // 初始化NTP时间
  timeClient.begin();
  timeClient.update();
  
  // 绘制初始界面
  tft.fillRoundRect(0, 0, 320, 40, 8, TFT_DARKBLUE);
  u8f.setCursor(10, 30);
  u8f.print("智能加水系统");
  drawWaterButton();
}

void loop() {
  timeClient.update();
  drawTime();
  checkTouch();
  
  if (isWatering && (millis() - waterStartTime >= WATER_DURATION)) {
    stopWatering();
  }
  
  delay(100);
}

这个为什么屏幕显示白屏

  • 写回答

3条回答 默认 最新

  • 紫雾凌寒 新星创作者: 人工智能技术领域 2025-10-31 21:35
    关注

    让 “紫雾凌寒” 来帮你回答,本回答结合 DeepSeek

    如果还有问题,请评论或点击头像私信,如果有帮助到您, 请关注、采纳、点赞

    1. 问题关键点分析:
      - 仅从提供的代码片段来看,无法明确完整的程序逻辑,但白屏问题可能涉及多个方面。
      - 硬件连接方面,TFT显示屏与ESP32的SPI接口连接是否正确是关键,可能存在引脚连接错误、SPI时钟极性或相位设置不当等硬件配置问题。
      - 软件方面,初始化TFT显示屏的代码可能存在错误,例如初始化参数不正确,或者在后续使用中对显示内容的绘制等操作有误。
    2. 解决方案:
      - 硬件检查
      • 确认TFT显示屏与ESP32的SPI引脚连接正确。例如,ESP32的SPI引脚通常为SCK(时钟)、MOSI(主输出从输入)、MISO(主输入从输出)、CS(片选)等,要与TFT显示屏相应引脚一一对应。
      • 检查电源连接是否稳定,确保TFT显示屏有足够且稳定的供电。
      • 软件方面
      • 以下是一个简单的TFT显示屏初始化及显示文本的示例代码(假设使用Adafruit_GFX库和Adafruit_ST7735库):
    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_ST7735.h>
    
    #define TFT_CS 15
    #define TFT_RST 4
    #define TFT_DC 2
    
    Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
    
    void setup() {
      Serial.begin(115200);
      tft.initR(INITR_BLACKTAB);
      tft.fillScreen(ST7735_BLACK);
      tft.setTextSize(2);
      tft.setTextColor(ST7735_WHITE);
      tft.setCursor(0, 0);
      tft.print("Hello, TFT!");
    }
    
    void loop() {
      // 这里可以添加其他显示逻辑
    }
    
     - 检查初始化函数调用是否正确,例如上述代码中的`tft.initR(INITR_BLACKTAB)`,要根据TFT显示屏的型号选择正确的初始化模式。
     - 确认绘制显示内容的代码逻辑无误,比如绘制文本、图形等操作的参数是否正确设置。
    
    1. 不同解决方案的优缺点:
      - 硬件优先检查
      • 优点:如果是硬件连接问题导致白屏,通过检查硬件可以直接定位并解决问题,避免在软件上浪费过多时间。
      • 缺点:需要仔细检查硬件连接,可能需要使用万用表等工具,对于一些不太熟悉硬件的开发者来说可能有一定难度。
      • 软件调试
      • 优点:相对硬件检查更容易进行,通过逐步调试代码可以快速定位软件中可能存在的问题,例如初始化参数错误、显示函数调用错误等。
      • 缺点:如果硬件本身存在问题,仅靠软件调试可能无法发现根本原因,可能会陷入反复检查软件代码的循环中。
    2. 总结:
      TFT显示屏与ESP32连接白屏问题需要从硬件和软件两方面进行排查。硬件连接的正确性至关重要,要确保引脚连接无误且电源稳定。软件方面则要仔细检查初始化代码和显示操作代码,通过正确的初始化和合理的显示内容绘制来解决白屏问题。

    请注意,以上代码示例基于特定的库,实际应用中需要根据所使用的TFT显示屏型号及相关库进行调整。

    希望以上解答对您有所帮助。如果您有任何疑问,欢迎在评论区提出。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月6日
  • 已采纳回答 11月6日
  • 创建了问题 10月31日