御坂10032号 发表于 4 天前

FireBeetle 2 ESP32-C5 驱动ST7735 SPI 1.8寸屏幕

简介
在上一篇文章中,我们已经完成了 BH1750 光照传感器的数据采集与 MQTT 上报,并对 I²C 通讯协议 进行了功能验证。本篇文章将继续扩展项目功能 —— 我们将使用一块 1.8 寸 TFT 彩色显示屏(驱动芯片:ST7735) 来 实时显示传感器数据,同时借此机会 实践并测试 SPI 通讯协议 的使用。




ST7735 是一款由 Sitronix 出品的 TFT-LCD 控制驱动芯片,常用于 1.44~1.8 寸的彩色显示屏。该芯片通过 SPI 接口 与主控(如 ESP32)通信, 而这次我们使用是Arduino进行的编程,得益于强大的库管理器,所以并不需要担心如何编写驱动。只需要按照对应的PIN将杜邦线连接成功即可。 幸运的又是这个ESP32C5的底板非常nice,已经将所有C5的Pin全部引出了,而且还标注了SPI的定义PIN。


1- 首先我们在程序中定义这次我们需要使用到的PIN以便于使用ST7735库
#define TFT_CS   3   // 片选(Chip Select)
#define TFT_DC   4   // 数据/命令选择
#define TFT_RST25// 硬件复位
#define TFT_BL   2   // 背光控制
#define TFT_SCLK 23// SPI 时钟
#define TFT_MOSI 24// SPI 主输出从输入
我这块屏幕是几年前买某宙的,其中SCLK在屏幕上的定义是SCL, MOSI在屏幕上的定义是SDA (因为ESP32-C5作为主机设备,所以连接Master out slaver IN MOSI)

2- 初始化屏幕
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 打开背光
SPI.begin(TFT_SCLK, -1, TFT_MOSI);
tft.initR(INITR_BLACKTAB);
首先对屏幕进行初始化,这个背光的PIN如果不适用的话可以直接接3.3V或者悬空,这样就可以节省出来一个IO。

3- 初始化屏幕方向显示
tft.setRotation(3);
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("ST7735 Ready!");
屏幕方向的话可以使用tft.setRotation(); 的函数进行设置。


4- 在主循环中持续读取数据,并且更新显示
tft.fillScreen(ST77XX_BLACK);
tft.setCursor(10, 15);
tft.setTextSize(1);
tft.setTextColor(ST77XX_CYAN);
tft.println("ESP32 Sensor");

tft.setCursor(10, 35);
tft.setTextSize(2);
tft.setTextColor(ST77XX_GREEN);
tft.printf("Lux: %.1f", lux);
5- 显示WIFI的状态信息
tft.setTextSize(1);
tft.setCursor(10, 65);
tft.setTextColor(wifi_connected ? ST77XX_YELLOW : ST77XX_RED);
tft.printf("WiFi: %s", wifi_connected ? "Connected" : "Disconnected");

tft.setCursor(10, 80);
tft.setTextColor(mqtt.connected() ? ST77XX_YELLOW : ST77XX_RED);
tft.printf("MQTT: %s", mqtt.connected() ? "OK" : "Retrying...");


完整代码如下:

#include <WiFi.h>
#include <WiFiClient.h>
#include <MQTT.h>         
#include <Wire.h>
#include <BH1750.h>      
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

// ===== WiFi 配置 =====
#define STA_SSID"ImmortalWrt-5G"
#define STA_PASS"mazha1997"
#define AP_SSID   "esp32-v6"

// ===== MQTT 配置 =====
#define MQTT_HOST "192.168.1.153"
#define MQTT_PORT 1884
#define MQTT_USER "root"
#define MQTT_PASS "123456"
#define MQTT_CLIENT_ID "esp32-client"

// ===== ST7735 引脚定义 =====
#define TFT_CS   3
#define TFT_DC   4
#define TFT_RST25
#define TFT_BL   2
#define TFT_SCLK 23
#define TFT_MOSI 24

// ===== 全局对象 =====
WiFiClient net;
MQTTClient mqtt(256);
BH1750 lightMeter;
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// ===== 全局状态 =====
static volatile bool wifi_connected = false;

// ===== MQTT 回调函数 =====
void mqttMessageReceived(String &topic, String &payload) {
Serial.print("MQTT message received: ");
Serial.print(topic);
Serial.print(" => ");
Serial.println(payload);
}

// ===== MQTT 初始化连接 =====
void mqttConnect() {
Serial.print("Connecting to MQTT... ");
while (!mqtt.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASS)) {
    Serial.print(".");
    delay(1000);
}
Serial.println("\nMQTT connected!");
mqtt.subscribe("esp32/test");
mqtt.publish("esp32/status", "ESP32 connected successfully!");
}

// ===== WiFi 事件处理 =====
void wifiOnConnect() {
Serial.println("STA Connected");
Serial.print("STA IPv4: ");
Serial.println(WiFi.localIP());

mqtt.begin(MQTT_HOST, MQTT_PORT, net);
mqtt.onMessage(mqttMessageReceived);
mqttConnect();
}

void wifiOnDisconnect() {
Serial.println("STA Disconnected");
delay(1000);
WiFi.begin(STA_SSID, STA_PASS);
}

void WiFiEvent(WiFiEvent_t event) {
switch (event) {
    case ARDUINO_EVENT_WIFI_AP_START:
      WiFi.softAPsetHostname(AP_SSID);
      break;
    case ARDUINO_EVENT_WIFI_STA_START:
      WiFi.setHostname(AP_SSID);
      break;
    case ARDUINO_EVENT_WIFI_STA_GOT_IP:
      wifi_connected = true;
      wifiOnConnect();
      break;
    case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
      wifi_connected = false;
      wifiOnDisconnect();
      break;
    default:
      break;
}
}

// ===== 初始化 =====
void setup() {
Serial.begin(115200);
Serial.println("ESP32 Booting...");

// ===== 初始化 ST7735 =====
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 打开背光
SPI.begin(TFT_SCLK, -1, TFT_MOSI);
tft.initR(INITR_BLACKTAB);

tft.setRotation(3);
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.println("ST7735 Ready!");

// ===== 初始化 I2C & BH1750 =====
Wire.begin(9, 10); // SDA=9, SCL=10
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
    Serial.println("BH1750 initialized successfully.");
} else {
    Serial.println("BH1750 not detected! Check wiring.");
    tft.setTextColor(ST77XX_RED);
    tft.println("BH1750 ERROR!");
}

// ===== 初始化 Wi-Fi =====
WiFi.disconnect(true);
WiFi.onEvent(WiFiEvent);
WiFi.mode(WIFI_MODE_APSTA);
WiFi.softAPenableIPv6();
WiFi.softAP(AP_SSID);
WiFi.enableIPv6();
WiFi.begin(STA_SSID, STA_PASS);
}

// ===== 主循环 =====
void loop() {
if (wifi_connected) {
    mqtt.loop();
    if (!mqtt.connected()) {
      mqttConnect();
    }

    static unsigned long lastMsg = 0;
    if (millis() - lastMsg > 10000) {
      lastMsg = millis();

      // ===== 读取 BH1750 光照强度 =====
      float lux = lightMeter.readLightLevel();
      Serial.printf("Light intensity: %.2f lux\n", lux);

      // ===== MQTT 发布数据 =====
      String payload = String("{\"lux\":") + String(lux, 2) + "}";
      mqtt.publish("esp32/bh1750", payload);
      Serial.println("Published: " + payload);

      // ===== 更新 ST7735 屏幕显示 =====
      tft.fillScreen(ST77XX_BLACK);
      tft.setCursor(10, 15);
      tft.setTextSize(1);
      tft.setTextColor(ST77XX_CYAN);
      tft.println("ESP32 Sensor");

      tft.setCursor(10, 35);
      tft.setTextSize(2);
      tft.setTextColor(ST77XX_GREEN);
      tft.printf("Lux: %.1f", lux);

      tft.setTextSize(1);
      tft.setCursor(10, 65);
      tft.setTextColor(wifi_connected ? ST77XX_YELLOW : ST77XX_RED);
      tft.printf("WiFi: %s", wifi_connected ? "Connected" : "Disconnected");

      tft.setCursor(10, 80);
      tft.setTextColor(mqtt.connected() ? ST77XX_YELLOW : ST77XX_RED);
      tft.printf("MQTT: %s", mqtt.connected() ? "OK" : "Retrying...");
    }
}

while (Serial.available()) {
    Serial.write(Serial.read());
}
}


至此便完成了ST7735的驱动。库管理器就是好用,不用费尽心思去调试驱动。还没有测试,不知道Mind + 支不支持这个板子,如果支持的话Block类的编程将会更简单上手。

页: [1]
查看完整版本: FireBeetle 2 ESP32-C5 驱动ST7735 SPI 1.8寸屏幕