用MicroPython点亮你的第一块彩屏:ST7789实战手记
你有没有过这样的经历?手头有个小项目,想加个屏幕显示点信息——温度、状态、菜单,甚至一张笑脸。可一查资料,发现驱动TFT屏要配寄存器、写初始化序列、处理RGB时序……头都大了。
别急,今天我要分享的这个组合——ST7789 + MicroPython,就是专治这类“嵌入式显示恐惧症”的良方。
我们不堆术语,不翻数据手册逐行解码,而是直接上手:从零开始,让一块小小的240x240彩色屏幕在几秒内亮起来,显示出文字和图形。整个过程,就像写一段普通的Python脚本一样自然。
为什么是 ST7789?
市面上能用的TFT驱动芯片不少,比如老将ILI9341、中端选手ST7735,但如果你手上是一块1.3英寸或1.54英寸的方形/圆形彩屏,那大概率它的心脏就是ST7789。
这块芯片有点“聪明”:
- 原生支持240×240 分辨率,不用再忍受320×240裁一半的尴尬;
- 内置升压电路和振荡器,外围元件少,模块做得非常紧凑;
- 支持多种接口,最常用的是四线SPI,仅需SCK、MOSI、DC、CS、RST五根控制线就能跑起来;
- 色彩用的是标准RGB565 格式,65K色表现足够细腻;
- 功耗低,待机时电流不到10μA,适合电池供电的小设备。
更重要的是,它的寄存器配置虽然复杂,但已经被社区“驯服”了。你现在完全不需要懂0x11是睡眠退出、0x3A是接口格式设置——这些都被封装好了。
为什么选 MicroPython?
以前做嵌入式GUI,得会C、懂RTOS、会DMA刷屏,调试靠逻辑分析仪抓波形。但现在不一样了。
MicroPython 把这一切简化成了“写Python”的体验。你在树莓派Pico或者ESP32上烧个固件,连根USB线,打开串口终端,敲一行代码就能点亮LED。同样的方式,也能操控一块TFT屏。
关键是:有库可用,而且好用。
GitHub上有成熟的st7789.py驱动库,作者 Rus Hughes 做了一件了不起的事——把所有底层细节打包成一个不到10KB的模块,提供清晰直观的API。你只需要关心“我想画什么”,而不是“怎么送数据到GRAM”。
GRAM(Graphic RAM)是ST7789内部的一块显存区域,你写进去的颜色值会直接映射到屏幕上每个像素点。你可以把它想象成一块240×240的网格画布,每一个格子填一个颜色数字就行。
接线很简单:SPI五线制搞定
我用的是最常见的接法,主控是Raspberry Pi Pico,屏幕是某宝常见的1.3寸ST7789模组(背面标着”GC9A01”?别信,多半还是ST7789)。
| 屏幕引脚 | 连接到 Pico 引脚 | 功能说明 |
|---|---|---|
| VCC | 3V3 | 3.3V供电 |
| GND | GND | 地线 |
| SCL | GP2 (SPI0_SCK) | SPI时钟 |
| SDA | GP3 (SPI0_MOSI) | 主发从收 |
| RES | GP0 | 复位信号 |
| DC | GP4 | 数据/命令选择 |
| CS | GP5 | 片选信号 |
| BLK / LED | GP1 | 背光控制 |
注意:
- 所有电平均为3.3V,Pico原生兼容,无需电平转换。
- BLK引脚如果直接接高,则背光常亮;若接GPIO,可用PWM调光节能。
- 使用硬件SPI端口(如SPI0),性能更稳,速率可达80MHz。
第一行代码:让屏幕“活”过来
准备好环境后,先上传st7789.py和字体文件(比如vga1_8x16.py)到Pico的文件系统中。然后运行以下代码:
import machine import st7789 import time from fonts import vga1_8x16 as font # 初始化SPI spi = machine.SPI(0, baudrate=80_000_000, sck=machine.Pin(2), mosi=machine.Pin(3)) # 创建显示屏对象 display = st7789.ST7789( spi, 240, 240, reset=machine.Pin(0, machine.Pin.OUT), dc=machine.Pin(4, machine.Pin.OUT), cs=machine.Pin(5, machine.Pin.OUT), backlight=machine.Pin(1, machine.Pin.OUT), rotation=0 ) # 开始操作! display.fill(st7789.BLACK) # 全黑清屏 time.sleep(0.5) display.text(font, "Hello!", 100, 100, st7789.WHITE)几秒钟后,屏幕上跳出白色的 “Hello!” —— 恭喜,你已经跨过了最难的门槛!
关键参数解读:那些你该知道的坑
✅ SPI波特率设多高合适?
理论上ST7789支持高达150MHz的SPI输入(模式0),但实际受布线质量限制。我的经验是:
- 板载短距离连接:可尝试60~80MHz
- 排线超过5cm:建议降到40MHz 以内
- 初次调试:用20MHz保稳定
太高频率会导致花屏、乱码,尤其是复位后第一次刷新容易出错。
✅ rotation 参数有什么用?
这可是神器!ST7789支持四个方向旋转:0°、90°、180°、270°。只需改一个参数:
rotation=1 # 顺时针旋转90度库会自动调整坐标系映射,原本的(x,y)变成(y, 239-x)这种麻烦事全由底层处理。再也不用手动重算UI布局了。
✅ 颜色怎么表示?
所有颜色都是RGB565 16位整数,例如:
| 颜色 | 值 |
|---|---|
| BLACK | 0x0000 |
| RED | 0xF800(高5位红) |
| GREEN | 0x07E0(中间6位绿) |
| BLUE | 0x001F(低5位蓝) |
| WHITE | 0xFFFF |
你也可以自定义混合色:
CYAN = st7789.color565(0, 255, 255) # Python函数生成✅ 中文能显示吗?
可以,但需要额外工作。标准字体只支持ASCII字符。要显示中文,有两种方案:
- 预生成字模:用工具将汉字转为点阵数组,类似OLED的做法;
- 加载TrueType字体:配合
ttf库动态渲染,资源消耗大,Pico上较难实现。
目前更实用的是前者,做一个简单的“问候语”菜单绰绰有余。
实战技巧:不只是“Hello World”
🖼 图片显示:BMP最快
想在屏幕上放个Logo或图标?推荐使用16位BMP图像(RGB565格式)。准备一张240x240或更小的BMP文件,保存为原始格式(无压缩),然后通过以下方式加载:
display.jpg("logo.bmp", 0, 0) # 注意:方法名可能是 bitmap() 或 jpeg()具体取决于你用的库版本。有些分支支持.bmp直接读取,效率很高。
小贴士:图片太大容易内存溢出。Pico只有264KB RAM,建议单张图不超过30KB,或采用分块传输。
⏱ 提升刷屏速度的秘诀
默认.text()、.rect()等方法是逐像素发送命令+数据,效率不高。批量操作要用:
def fast_fill_rect(display, x, y, w, h, color): display.fill_rect(x, y, w, h, color) # 底层优化过的填充这是连续写GRAM区域,比一个个点快几十倍。
另外,非必要不频繁清屏。可以用局部刷新替代全屏重绘。
常见问题与避坑指南
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
| 屏幕全白/全黑无反应 | 复位没接好或SPI接反 | 检查RST是否拉低后再释放;确认SCK/MOSI是否接对 |
| 文字模糊、颜色错乱 | 电源不稳或电压不足 | 单独供电,避免与电机共用电源;加0.1μF去耦电容 |
| 刷屏慢、卡顿 | SPI速率太低或频繁调用小函数 | 提高速率至40MHz以上;合并绘图操作 |
| 背光一闪就灭 | BLK脚被误配置为输入 | 明确设置为输出,并保持高电平 |
| 旋转后坐标错位 | rotation参数未生效 | 确保调用了.init()之后才开始绘图 |
一个经典错误:忘记在创建
ST7789实例时传入cs=参数。结果每次通信都缺少片选控制,看似正常实则不稳定。
它适合做什么项目?
别小看这块小屏,潜力不小:
- 🌡️ 温湿度监控仪:搭配DHT22,实时曲线+数值显示;
- 🔊 MP3播放器界面:歌曲名、进度条、专辑封面轮播;
- 📍 GPS轨迹记录仪:经纬度、海拔、卫星数量可视化;
- 🎮 简易游戏机:贪吃蛇、俄罗斯方块都能跑;
- 🏠 智能家居面板:开关灯、调节亮度、查看能耗。
我见过有人拿它做个“电子相框”,每天换一张老婆的照片,插USB就能用——浪漫又实用。
写在最后:技术的意义在于让人轻松创造
回过头看,十年前要实现这样一个功能,可能需要一周时间研究数据手册、调试SPI时序、编写DMA传输逻辑。而现在,三分钟写完代码,五分钟连好线,八分钟后屏幕亮了。
这就是抽象的力量。MicroPython + 开源驱动库,把复杂的硬件交互变成人人可参与的创作工具。
下次当你犹豫“要不要加个屏”的时候,不妨试试ST7789。也许那一抹色彩,就是你项目灵魂闪现的第一道光。
如果你也正在玩这块屏幕,欢迎留言交流心得。遇到问题?贴出你的接线图和报错信息,我们一起 debug。