点亮第一帧:手把手教你用Arduino驱动ST7789彩屏
你有没有遇到过这种情况——买了一块炫酷的圆形TFT屏幕,插上Arduino却死活不亮?要么全黑、要么花屏、要么颜色发紫得像外星科技……别急,这几乎每个玩嵌入式显示的人都踩过的坑。
今天我们就来彻底解决这个问题。主角是现在最火的小尺寸彩屏驱动芯片:ST7789。它常见于1.3英寸240x240圆角屏、240x320矩形屏,被广泛用于智能手表、DIY掌机、WiFi配置界面等项目中。而我们的目标很明确:从零开始,让你在30分钟内成功点亮这块屏幕,并理解背后的工作原理。
为什么是ST7789?
市面上的TFT驱动不少,比如老将ILI9341、OLED专用的SSD1306,但如果你最近买了新型小尺寸彩屏,大概率它的“心脏”就是ST7789。
为什么它这么受欢迎?三个字:小、快、省。
- 小:支持240x240这类紧凑分辨率,特别适合圆形或方形表盘设计;
- 快:SPI最高可达60MHz,刷图流畅,动画不卡顿;
- 省:内置升压电路,3.3V单电源供电就能点亮背光和LCD偏压,省掉额外DC-DC模块。
更重要的是,它和Arduino生态配合得天衣无缝,尤其是搭配 TFT_eSPI库 ,几行代码就能出图,堪称“嵌入式GUI入门神芯”。
硬件接线:别再接错5V了!
先说最重要的一点:ST7789是3.3V器件!
虽然有些模块自带电平转换,但很多便宜屏没做保护,直接接Arduino Uno的5V会烧毁芯片。所以请务必确认:
✅ VCC接3.3V
❌ 不要接5V!
以下是标准四线SPI模式下的引脚连接表(适用于大多数开发板):
| ST7789引脚 | 功能说明 | 推荐连接(Arduino Uno/Nano) |
|---|---|---|
| VCC | 电源输入(3.3V) | 3.3V |
| GND | 地 | GND |
| SCL/SCK | SPI时钟 | D13 或 SCK |
| SDA/SDI/MOSI | 数据输入 | D11 或 MOSI |
| CS | 片选 | D10(可自定义) |
| DC | 命令/数据选择 | D5(常用) |
| RES | 复位 | D4(建议固定) |
| BLK/LED | 背光控制 | 3.3V(常亮)或PWM引脚调光 |
📌关键提示:
- 如果使用ESP32,推荐使用硬件SPI并启用DMA以提升刷新速度。
-BLK脚如果不接,屏幕可能完全无光。想实现亮度调节?把它接到PWM引脚(如D9),用analogWrite()控制。
软件准备:选对库事半功倍
Arduino平台上有两个主流图形库:
Adafruit_GFX + Adafruit_ST7735
兼容性好,学习资料多,但对ST7789支持较弱,初始化需手动调整。TFT_eSPI(强烈推荐)
专为高速TFT优化,原生支持ST7789、多种分辨率、旋转方向,性能强且配置灵活。
我们选第二个。安装方法很简单:
- 打开Arduino IDE → “工具” → “管理库”
- 搜索
TFT_eSPI,安装Bodmer版本 - 安装完成后,进入库路径找到
UserSetup.h
⚠️ 这一步很多人忽略,结果屏幕不亮——必须修改UserSetup.h中的配置!
打开文件后,取消注释对应屏幕型号的行,例如:
#define ST7789_DRIVER #define TFT_WIDTH 240 #define TFT_HEIGHT 240 #define CGRAM_OFFSET // 若显示偏移可用此宏修正再设置引脚(以常见NodeMCU ESP-12模板为例):
#define TFT_MISO -1 // ST7789通常不用MISO #define TFT_MOSI 23 #define TFT_SCLK 18 #define TFT_CS 5 #define TFT_DC 2 #define TFT_RST 4保存后重新编译上传即可生效。
第一个程序:让屏幕说话
现在终于可以写代码了。下面是一个完整的“Hello World”示例,包含清屏、文字、图形绘制:
#include <TFT_eSPI.h> TFT_eSPI tft = TFT_eSPI(); // 创建对象 void setup() { tft.init(); // 自动初始化 tft.setRotation(1); // 横屏显示(0~3可选) tft.fillScreen(TFT_BLACK); // 黑色背景 // 设置字体样式 tft.setTextColor(TFT_WHITE, TFT_BLACK); tft.setTextSize(2); tft.setCursor(30, 50); tft.println("Hello, ST7789!"); // 画个红圈和绿线 tft.drawCircle(120, 150, 40, TFT_RED); tft.drawLine(0, 0, 240, 240, TFT_GREEN); } void loop() { delay(1000); }💡 小技巧:setRotation(1)是关键。不同外壳安装方向不同,这个函数会自动重映射坐标系,无需改硬件。
上传后如果一切正常,你会看到屏幕亮起,出现白色文字、红色圆圈和一条斜穿屏幕的绿线——恭喜,你的ST7789已经成功被征服!
屏幕为何不亮?深入初始化流程
但如果你还是黑屏,请不要怀疑人生。我们来拆解一下tft.init()背后到底发生了什么。
初始化的本质:发命令+等时序
ST7789不像OLED那样“即插即显”,它需要一系列精确的寄存器配置才能进入工作状态。整个过程就像给一台老式电视机“预热+调台”。
核心步骤如下:
复位芯片
- 发送低电平持续一段时间(约10ms),模拟硬件复位
- 或通过软件命令0x01触发内部复位退出睡眠模式
cpp writeCommand(0x11); // Sleep Out delay(120); // 必须等待至少120ms!这是坑王之王设置色彩格式
cpp writeCommand(0x3A); writeData(0x05); // RGB565格式(16位色)
⚠️ 错这里会导致紫色/粉色异常,因为默认可能是6-6-6模式。电源与电压配置
cpp writeCommand(0xC3); writeData(0x19); // VREG1L writeCommand(0xC4); writeData(0x20); // VREG2L writeCommand(0xBB); writeData(0x3B); // VCOM开启显示
cpp writeCommand(0x29); // Display ON
这些命令序列藏在TFT_eSPI的Init_ST7789.cpp里,一般不需要改动。但如果换了个冷门屏幕,可能需要根据厂商提供的初始化代码替换部分内容。
🔧调试建议:
- 加长延时试试(如把120ms改成200ms)
- 用逻辑分析仪抓SPI信号,看是否发出正确指令
- 检查DC脚是否正确切换“命令/数据”状态
颜色怎么不对?GRAM与MADCTL详解
另一个常见问题是:“我画了个白点,怎么变成黄的?”或者“整个画面反了”。
这多半是GRAM访问方式出了问题。
GRAM是什么?
Graphic RAM(显存),是ST7789内部一块存储像素数据的区域。你要画的东西最终都要写进这里。写入前必须指定范围:
writeCommand(0x2A); // CASET: Column Address Set writeData(0x00); writeData(0x00); // 起始列 writeData(0x00); writeData(0xF0); // 结束列(240) writeCommand(0x2B); // RASET: Row Address Set writeData(0x00); writeData(0x00); writeData(0x01); writeData(0x40); // 行结束(320) writeCommand(0x2C); // RAMWR: Memory Write // 开始连续发送RGB565数据...顺序不能错,否则地址错乱导致花屏。
MADCTL:旋转的秘密
你想横屏?竖屏?倒着装?靠的就是MADCTL寄存器(0x36)。
它有多个控制位,其中最重要的是:
| 位 | 名称 | 功能 |
|---|---|---|
| 7 | MY | 行地址递增方向 |
| 6 | MX | 列地址递增方向 |
| 5 | MV | 行列交换(转置) |
| 3 | ML | 扫描方向(从下往上) |
| 2 | RGB | 接口颜色顺序 |
例如:
-0x00:正常竖屏
-0x70:横屏(右转90°)
-0xA0:上下翻转
-0xC0:180°旋转
TFT_eSPI的setRotation()会自动计算这些值,但如果你自己写底层驱动,就得亲自算bit。
实战避坑指南:那些年我们一起踩过的雷
🔴 问题1:屏幕一闪就灭
- 原因:初始化太快,
Sleep Out后没等够时间 - 解决方案:确保
delay(120)在0x11之后
🟡 问题2:花屏、条纹、雪花
- 原因:SPI速率过高或干扰
- 解决方案:降低SPI频率(TFT_eSPI中修改
TFT_FREQUENCY为20000000)
🟣 问题3:整体偏紫/发红
- 原因:色彩格式错误
- 解决方案:检查
COLMOD (0x3A)是否设为0x05(RGB565)
🟢 问题4:触摸与显示错位
- 原因:TFT旋转了,但触摸芯片(如XPT2046)没同步
- 解决方案:在Touch library中也调用
setRotation()
⚪ 问题5:背光不亮
- 原因:
BLK脚悬空或接错 - 解决方案:接到3.3V或PWM引脚;部分模块需拉高使能
更进一步:不只是“点亮”
一旦你能稳定驱动ST7789,接下来的可能性就打开了:
✅ 数据可视化仪表盘
用drawArc()画弧形进度条,实时显示温度、湿度、电量。
✅ 图片显示(SPIFFS + .raw/.png解码)
将图片转成RGB565数组存入Flash,用tft.pushImage()播放。
✅ 简易UI框架
结合按钮检测、菜单导航,打造属于自己的HMI系统。
✅ 低功耗休眠唤醒
利用writeCommand(0x10)进入睡眠模式,外部中断唤醒,适合电池设备。
甚至有人用它做了:
- 复古贪吃蛇游戏机
- WiFi信号扫描仪
- BLE信标显示器
- 心率监测腕带
写在最后:从点亮到创造
点亮一块屏幕,看似只是显示几个字、几根线,但它代表的是你掌握了嵌入式GUI的第一道门槛:如何与复杂的外设通信,如何解读时序,如何调试底层协议。
ST7789不是一个简单的模块,它是现代小型化人机交互的核心组件之一。掌握它,意味着你可以自信地构建任何需要视觉反馈的项目。
下次当你看到一块小小的圆形彩屏时,不要再问“为什么我不亮”,而是思考:“我能用它表达什么?”
毕竟,真正的魔法不是让屏幕亮起来,而是让它说出你想说的话。
💬互动时间:你在驱动ST7789时遇到过哪些奇葩问题?是怎么解决的?欢迎在评论区分享你的“踩坑日记”!