1. ESP32驱动1.8寸TFT LCD显示模块全攻略
最近在做一个物联网项目时,需要用到1.8寸TFT LCD显示屏作为人机交互界面。经过一番调研,我选择了ST7735驱动芯片的128x160分辨率屏幕,搭配ESP32开发板使用。这种组合性价比极高,1.8寸屏价格通常在20元以内,ESP32更是物联网开发的性价比之王。下面就把完整的驱动方法和避坑经验分享给大家。
这种小尺寸TFT屏非常适合需要紧凑显示的项目,比如便携设备、智能家居控制面板等。ST7735作为成熟驱动芯片,支持SPI接口,与ESP32的硬件SPI配合能实现流畅的显示效果。我实测刷新率能达到30fps以上,完全满足大多数嵌入式场景需求。
2. 硬件准备与连接
2.1 所需材料清单
要完成这个项目,你需要准备以下硬件:
- ESP32开发板(任何型号均可,我使用的是ESP32 DevKitC)
- 1.8寸TFT LCD显示屏(ST7735驱动,128x160分辨率)
- 杜邦线若干(建议使用母对母)
- 面包板(可选,方便调试)
- USB数据线(用于供电和烧录程序)
特别注意:市面上有些1.8寸屏使用的是ILI9163或ILI9341驱动芯片,购买时一定要确认是ST7735驱动的版本。我最初就买错了型号,导致调试了半天才发现驱动不兼容。
2.2 引脚连接详解
ST7735采用SPI接口通信,与ESP32的连接方式如下:
| TFT引脚 | ESP32引脚 | 功能说明 |
|---|---|---|
| VCC | 3.3V | 电源正极 |
| GND | GND | 电源地 |
| CS | GPIO5 | 片选信号 |
| RESET | GPIO4 | 复位信号 |
| DC/RS | GPIO2 | 数据/命令选择 |
| MOSI | GPIO23 | SPI数据线 |
| SCK | GPIO18 | SPI时钟线 |
| BL | 3.3V | 背光控制 |
注意:BL引脚如果不接会导致屏幕无显示,但不会影响通信。有些屏幕的BL引脚需要PWM控制亮度,这种情况下可以连接到ESP32的PWM引脚。
实际连接时,建议先用万用表确认屏幕的引脚定义,不同厂家的排针顺序可能有差异。我就遇到过两个看似相同的屏幕,引脚排列却完全相反的情况。
3. 软件环境配置
3.1 安装必要库文件
在Arduino IDE中安装TFT_eSPI库的步骤如下:
- 打开Arduino IDE
- 点击"工具"->"管理库..."
- 搜索"TFT_eSPI"
- 选择最新版本安装
这个库由Bodmer维护,支持多种TFT驱动芯片,特别优化了ESP32的性能。安装完成后,可以在Arduino的库管理器中看到版本号,我使用的是2.4.79版本。
3.2 库配置文件修改
这是最关键也最容易出错的一步。TFT_eSPI库需要通过配置文件指定屏幕参数和引脚定义。具体操作:
-
找到Arduino库安装目录下的TFT_eSPI文件夹
- Windows通常位于:
C:\Users\你的用户名\Documents\Arduino\libraries\TFT_eSPI - MacOS通常位于:
~/Documents/Arduino/libraries/TFT_eSPI
- Windows通常位于:
-
在
User_Setups子文件夹中新建Setup_my_ESP32_ST7735_128x160.h文件,内容如下:
cpp复制#define USER_SETUP_ID 999
#define ST7735_DRIVER
#define TFT_WIDTH 128
#define TFT_HEIGHT 160
#define ST7735_REDTAB // 重要!指定屏幕版本
// SPI引脚配置
#define TFT_MOSI 23
#define TFT_SCLK 18
#define TFT_CS 5
#define TFT_DC 2
#define TFT_RST 4
#define SPI_FREQUENCY 10000000 // SPI时钟频率
// 启用所需字体
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
#define SMOOTH_FONT
- 修改同目录下的
User_Setup_Select.h文件:- 注释掉
#include <User_Setup.h> - 添加
#include <User_Setups/Setup_my_ESP32_ST7735_128x160.h>
- 注释掉
常见问题:如果屏幕显示颜色异常或镜像,可能是
ST7735_REDTAB定义不正确。有些屏幕需要使用ST7735_GREENTAB或ST7735_BLACKTAB,需要根据实际屏幕版本调整。
4. 基础显示功能实现
4.1 初始化与Hello World
下面是一个最简单的示例,展示如何在屏幕上显示文字:
cpp复制#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
tft.init();
tft.setRotation(0); // 设置显示方向
tft.fillScreen(TFT_BLACK); // 清屏
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextSize(1);
tft.setCursor(5, 5);
tft.println("Hello ESP32");
tft.setTextSize(2);
tft.setCursor(20, 30);
tft.println("1.8\" TFT");
}
void loop() {
}
上传代码后,你应该能看到屏幕显示两行文字。如果出现白屏或乱码,请检查:
- 引脚连接是否正确
- SPI频率是否设置过高(可尝试降低到5MHz)
- 屏幕背光是否开启
4.2 显示方向调整
setRotation()函数可以调整显示方向,参数范围0-3,对应不同旋转角度。我发现不同屏幕的旋转方向可能不一致,需要实际测试:
cpp复制// 测试不同旋转方向
for(int r=0; r<4; r++) {
tft.setRotation(r);
tft.fillScreen(TFT_BLACK);
tft.setCursor(10, 10);
tft.print("Rotation: ");
tft.println(r);
delay(2000);
}
5. 高级功能实现
5.1 图形绘制
TFT_eSPI库支持多种图形绘制功能,下面是一些实用示例:
cpp复制// 绘制矩形
tft.drawRect(10, 10, 50, 30, TFT_RED);
// 填充矩形
tft.fillRect(70, 10, 50, 30, TFT_BLUE);
// 绘制圆形
tft.drawCircle(40, 80, 20, TFT_GREEN);
// 填充圆形
tft.fillCircle(90, 80, 20, TFT_YELLOW);
// 绘制三角形
tft.drawTriangle(10, 120, 30, 150, 60, 130, TFT_CYAN);
5.2 位图显示
显示位图需要先将图片转换为C数组。推荐使用Img2Lcd或LCD Image Converter工具:
- 准备一张128x160像素的图片
- 使用工具转换为16位色(RGB565)的C数组
- 在代码中调用
tft.pushImage()显示
cpp复制// 示例位图显示
#include "my_image.h" // 包含转换后的图像数据
tft.pushImage(0, 0, 128, 160, (uint16_t *)my_image);
性能提示:ESP32的PSRAM版本可以先将图片存入PSRAM,减少内存压力。使用
tft.pushImage()比tft.drawBitmap()性能更好。
5.3 字体使用
TFT_eSPI支持多种内置字体和自定义字体:
cpp复制// 使用内置字体
tft.loadFont(AA_FONT_SMALL); // 加载小号抗锯齿字体
tft.setCursor(10, 10);
tft.println("Anti-aliased Text");
tft.unloadFont(); // 释放字体内存
// 使用自定义字体
#include <NotoSansBold15.h> // 先导入字体文件
tft.loadFont(NotoSansBold15);
tft.setTextColor(TFT_WHITE);
tft.setCursor(20, 50);
tft.println("Custom Font");
tft.unloadFont();
6. 性能优化技巧
6.1 SPI优化设置
默认10MHz的SPI速度可能不是最优的,可以通过以下方式调整:
cpp复制// 在Setup文件中调整SPI频率
#define SPI_FREQUENCY 27000000 // 提升到27MHz
// 或者在代码中动态设置
tft.init();
tft.setSPISpeed(27000000); // 设置SPI速度
注意:过高的SPI频率可能导致显示异常,需要根据屏幕质量调整。我的屏幕最高能稳定工作在30MHz。
6.2 双缓冲技术
对于动画或游戏等需要流畅显示的场景,可以使用双缓冲技术:
cpp复制// 创建第二个Sprite作为缓冲区
TFT_eSprite buffer = TFT_eSprite(&tft);
void setup() {
tft.init();
buffer.createSprite(128, 160); // 创建与屏幕同尺寸的缓冲区
buffer.fillScreen(TFT_BLACK);
buffer.setTextColor(TFT_WHITE);
buffer.drawString("Double Buffering", 10, 10);
buffer.pushSprite(0, 0); // 将缓冲区内容一次性推送到屏幕
}
void loop() {
// 在缓冲区绘制内容
buffer.fillCircle(random(128), random(160), 10, random(0xFFFF));
buffer.pushSprite(0, 0); // 更新显示
delay(100);
}
这种方法可以避免屏幕闪烁,提高显示流畅度。
7. 常见问题与解决方案
7.1 屏幕无显示
- 检查背光(BL)引脚是否接3.3V
- 确认所有电源连接正常(VCC和GND)
- 用万用表测量各引脚电压
- 尝试降低SPI频率
7.2 显示颜色异常
- 检查
ST7735_REDTAB/ST7735_GREENTAB定义是否正确 - 确认RGB颜色顺序设置
- 检查TFT_eSPI库版本是否最新
7.3 显示内容错位
- 调整
setRotation()参数 - 检查屏幕分辨率定义是否正确
- 确认
TFT_WIDTH和TFT_HEIGHT设置
7.4 内存不足
- 使用
tft.unloadFont()释放字体内存 - 对于大图像,考虑使用PSRAM版本ESP32
- 优化代码,减少内存占用
8. 实际项目应用示例
8.1 物联网状态显示器
结合ESP32的WiFi功能,可以制作一个网络状态显示器:
cpp复制#include <WiFi.h>
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
Serial.begin(115200);
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
WiFi.begin("your_SSID", "your_password");
tft.setTextColor(TFT_WHITE);
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
tft.print(".");
}
tft.setCursor(10, 30);
tft.print("Connected! IP: ");
tft.println(WiFi.localIP());
}
void loop() {
// 显示网络状态等信息
}
8.2 简易示波器
利用ESP32的ADC和TFT屏,可以制作一个简易示波器:
cpp复制// 省略部分代码...
void loop() {
static uint16_t x = 0;
uint16_t y = analogRead(34) / 16; // 读取ADC值并缩放
tft.drawPixel(x, y, TFT_GREEN);
if(++x >= 128) {
x = 0;
tft.fillScreen(TFT_BLACK);
}
delay(10);
}
这个项目展示了如何将ESP32的模拟输入可视化,你可以进一步添加触发、缩放等功能。
