
简介本资源是一套经实测验证的MicroPython GC9A01 TFT显示屏驱动方案专为ESP32开发者设计解决嵌入式项目中SPI屏驱动开发门槛高、调试耗时等痛点适用于物联网终端、智能手表、便携HMI等需彩色显示的进阶应用。压缩包共25个文件含19个Python源码如屏幕初始化gc9a01_spi.py、帧缓冲操作gc9a01fb_spi.py、图形绘制draw.py、文字渲染text.py、BMP/RAW图像加载及滚动显示等示例、2个预编译mpy字体库、1个raw格式图像、1个bmp测试图、1份LICENSE与1份README说明文档整体仅233KB轻量易集成。已有187人学习下载资源结构清晰分层examples目录提供即跑即验的典型用例for_examples子目录配套字体与位图素材便于快速验证基础显示功能并拓展自定义UI。读者可直接复用完整驱动逻辑省去SPI时序配置、寄存器初始化及色彩空间适配等底层工作专注上层交互逻辑开发。1. 项目概述为什么GC9A01与MicroPython是绝配如果你正在ESP32、RP2040这类微控制器上折腾图形界面或者想给一个小型物联网设备加个炫酷的显示屏那你大概率绕不开圆形TFT屏。而在众多圆形屏里GC9A01驱动的1.28英寸IPS屏凭借其240x240的分辨率、出色的色彩表现和相对亲民的价格几乎成了Maker圈里的“网红屏”。但硬件到手只是第一步如何让它“亮”起来并且能方便地显示点东西才是真正的挑战。我最近在几个项目里深度使用了GC9A01驱动方案从Arduino C换到了MicroPython。说实话一旦用上MicroPython那种“所见即所得”的快速开发体验真的就回不去了。今天分享的就是我在这个过程中从踩坑到稳定运行最终打磨出来的一套亲测好用的MicroPython GC9A01屏驱方案。它不仅包含了基础的显示功能更整合了我在实际项目中积累的优化技巧、常见问题的排查方法以及如何利用MicroPython的特性比如framebuf、LVGL来提升开发效率。无论你是刚拿到屏幕的新手还是想优化现有驱动性能的老鸟相信这些“干货”都能给你带来直接的帮助。2. 驱动方案核心选型与设计思路2.1 硬件接口的权衡SPI vs 并口GC9A01芯片本身支持多种接口但市面上最常见的1.28英寸模块为了节省引脚和成本几乎清一色地采用了4线SPI接口。这对于MicroPython开发者来说是个好消息因为SPI接口在MicroPython中得到了很好的支持且对MCU的引脚需求少通常只需4-6个接线简单。为什么坚持用SPI首先对于240x240这种分辨率的屏幕SPI的带宽在驱动芯片的加持下已经足够。GC9A01内部有显存MCU只需要通过SPI发送绘图指令和颜色数据实际的像素刷新由驱动芯片自己完成这大大减轻了MCU的负担。其次MicroPython的machine.SPI类成熟稳定时钟频率可以轻松推到40MHz甚至更高足以保证刷屏流畅度。最后引脚节省意味着你可以将更多的IO用于传感器、按键或其他外设这对于资源紧张的嵌入式项目至关重要。引脚定义与连接要点典型的4线SPI连接需要以下引脚SCK (Serial Clock): 时钟线。MOSI (Master Out Slave In): 主设备输出用于发送数据和命令到屏幕。DC (Data/Command): 关键引脚用于区分发送的是命令拉低还是数据拉高。很多驱动不工作的问题都出在这里。CS (Chip Select): 片选低电平有效。如果只有一个SPI设备可以接到GND但在代码中仍需正确控制。RST (Reset): 复位引脚用于硬件复位屏幕。强烈建议保留这是解决“花屏”或初始化失败的最后手段。BL (Backlight): 背光控制通常接一个GPIO通过PWM调光或者直接接VCC常亮。注意务必查阅你屏幕模块的具体引脚图。有些模块的DC引脚可能标记为D/C或A0MOSI可能标记为SDA本质相同但连接时需一一对应。2.2 软件驱动层的选择从裸写寄存器到高级框架在MicroPython生态中驱动一个SPI屏幕你有几个不同层次的选项最底层直接操作SPI和GPIO。你需要自己查阅GC9A01的数据手册编写初始化命令序列并通过DC引脚区分命令/数据来发送。这种方式最灵活但工作量巨大且容易出错不推荐新手直接尝试。中间层使用Framebuf库。MicroPython内置了framebuf模块它提供了一个帧缓冲区的抽象。你需要做的是编写一个继承自framebuf.FrameBuffer的类并实现show()等方法将帧缓冲区的内容通过SPI发送到GC9A01。这是目前社区最常见、也最推荐的方式。它平衡了灵活性和易用性让你能直接使用framebuf提供的画线、画矩形、填充、显示文本等基础功能。高层集成LVGL等图形库。如果你的项目需要复杂的UI如按钮、列表、动画等那么LVGL是一个强大的选择。你需要一个为GC9A01适配的display driver它底层通常也是基于framebuf或直接SPI操作然后向上为LVGL提供统一的接口。这种方式功能强大但系统开销也相对较大需要MCU有足够的RAM和性能如ESP32-S3。我的方案选择经过多个项目的实践我选择以**“基于framebuf的驱动”为核心**进行分享和优化。原因如下普适性强从ESP8266到RP2040只要支持MicroPython和SPI都能运行。性能足够对于大多数信息显示、简单动画的需求framebuf性能完全够用。易于理解和调试代码结构清晰出现问题容易定位。掌握了它再去看LVGL的驱动也会更容易理解。生态友好网上有大量基于framebuf的屏幕驱动示例方便学习和交流。3. 驱动代码深度解析与优化3.1 驱动类结构设计与初始化序列一个健壮的驱动类不仅仅是让屏幕亮起来更要考虑稳定性、可移植性和性能。下面是我优化后的驱动类核心结构解析。import machine import framebuf import time class GC9A01_SPI(framebuf.FrameBuffer): def __init__(self, spi, dc, cs, rst, blNone, width240, height240): # 1. 引脚对象保存 self.spi spi self.dc dc self.cs cs self.rst rst self.bl bl self.width width self.height height # 2. 初始化GPIO方向 self.dc.init(machine.Pin.OUT) self.cs.init(machine.Pin.OUT) self.rst.init(machine.Pin.OUT) if self.bl: self.bl.init(machine.Pin.OUT) # 3. 硬件复位关键步骤 self.reset() # 4. 发送初始化命令序列 self._init_display() # 5. 创建帧缓冲区buffer self.buffer bytearray(self.width * self.height * 2) # RGB565格式每个像素2字节 super().__init__(self.buffer, self.width, self.height, framebuf.RGB565) # 6. 开启显示并设置背光 self._write_cmd(0x29) # 开启显示 if self.bl: self.bl.value(1) # 开启背光 time.sleep_ms(100) self.fill(0) # 清屏为黑色 self.show()关键点解析硬件复位 (reset())这是一个至关重要的鲁棒性设计。在__init__最开始或发送初始化命令前执行一个完整的复位时序拉低RST-延时-拉高RST-延时可以确保屏幕从已知的硬件状态开始工作避免因上次操作未完成导致的初始化失败。缓冲区格式RGB565是彩色TFT屏最常用的格式。R(5位)G(6位)B(5位)共16位2字节在色彩丰富度和内存占用间取得了很好的平衡。bytearray的大小是宽*高*2字节对于240x240的屏幕约为115.2KB。这是内存占用的大头在选择MCU如ESP32 vs ESP8266时必须考虑。初始化序列 (_init_display)这是驱动屏幕的“密码本”。它是一系列预先定义好的命令和参数用于设置屏幕的扫描方向、颜色模式、亮度等。不同厂家、批次的GC9A01模块初始化序列可能略有差异。如果屏幕能亮但颜色不对或显示错位首先应该检查或替换这个序列。我提供的序列是经过多个模块验证的通用性较强的版本。3.2 核心通信方法与性能优化驱动类最核心的两个底层方法是_write_cmd和_write_data它们负责与GC9A01芯片通信。def _write_cmd(self, cmd): self.dc.value(0) # 拉低DC表示发送命令 self.cs.value(0) self.spi.write(bytearray([cmd])) self.cs.value(1) def _write_data(self, buf): self.dc.value(1) # 拉高DC表示发送数据 self.cs.value(0) self.spi.write(buf) self.cs.value(1)性能优化技巧SPI频率设置在初始化machine.SPI对象时baudrate参数至关重要。对于ESP32可以尝试设置为40_000_00040MHz或80_000_00080MHz。但要注意过高的频率可能导致通信不稳定特别是接线较长或质量一般时。建议从20MHz开始测试逐步提高。spi machine.SPI(1, baudrate40_000_000, polarity0, phase0, bits8, firstbitmachine.SPI.MSB)批量数据传输_write_data方法接收一个buf参数。在show()方法中我们需要将整个帧缓冲区115.2KB发送出去。绝对不要使用循环逐个像素发送。正确的做法是直接调用self.spi.write(self.buffer)。MicroPython的SPI底层驱动会对大数据块进行高效传输。show()方法的实现这是将内存中画好的图形“刷新”到屏幕上的方法。def show(self): # 设置窗口为全屏 self._write_cmd(0x2A) # 列地址设置命令 self._write_data(bytearray([0, 0, 0, self.width-1])) # 起始列0结束列239 self._write_cmd(0x2B) # 行地址设置命令 self._write_data(bytearray([0, 0, 0, self.height-1])) # 起始行0结束行239 self._write_cmd(0x2C) # 内存写入命令 # 一次性发送整个帧缓冲区数据 self._write_data(self.buffer)这里的一个优化点是如果只更新了屏幕的一部分可以只发送对应区域的窗口数据而不是全屏数据这被称为“局部刷新”能极大提升速度。但对于framebuf库实现局部刷新逻辑稍复杂通常在全屏刷新速度可接受时ESP32上全刷约60-100ms优先使用全刷保持代码简洁。3.3 初始化命令序列详解初始化序列是驱动屏幕的“魔法咒语”。下面是一个典型序列的拆解了解其含义有助于调试。def _init_display(self): init_cmds [ (0xEF, None), # 空命令有时用于同步 (0xEB, b\x14), # 设置内部参数 (0xFE, None), # (0xEF, None), (0xEB, b\x14), (0x84, b\x40), (0x85, b\xFF), (0x86, b\xFF), (0x87, b\xFF), (0x88, b\x0A), (0x89, b\x21), (0x8A, b\x00), (0x8B, b\x80), (0x8C, b\x01), (0x8D, b\x01), (0x8E, b\xFF), (0x8F, b\xFF), (0xB6, b\x00\x20), # 显示功能控制 (0x36, b\x08), # 内存访问控制 (MADCTL) - 关键控制旋转和颜色顺序 (0x3A, b\x55), # 像素格式设置 (0x5516bits/pixel, RGB565) (0x90, b\x08\x08\x08\x08), # 显示方向控制 (0xBD, b\x06), (0xBC, b\x00), (0xFF, b\x60\x01\x04), (0xC3, b\x13), (0xC4, b\x13), (0xC9, b\x22), (0xBE, b\x11), (0xE1, b\x10\x0E), (0xDF, b\x21\x0c\x02), (0xF0, b\x45\x09\x08\x08\x26\x2A), (0xF1, b\x43\x70\x72\x36\x37\x12), (0xF2, b\x45\x09\x08\x08\x26\x2A), (0xF3, b\x43\x70\x72\x36\x37\x12), (0xED, b\x1B\x0B), (0xAE, b\x77), (0xCD, b\x63), (0x70, b\x07\x07\x04\x0E\x0F\x09\x07\x08\x03), # 伽马调整 (0xE8, b\x34), (0x62, b\x18\x0D\x71\xED\x70\x70\x18\x0D\x71\xEF\x70\x70), (0x63, b\x18\x11\x71\xF1\x70\x70\x18\x11\x71\xF3\x70\x70), (0x64, b\x28\x29\xF1\x01\xF1\x00\x07), (0x66, b\x3C\x00\xCD\x67\x45\x45\x17\x00\x00\x00), (0x67, b\x00\x3C\x00\x00\x00\x01\x54\x10\x32\x98), (0x74, b\x10\x85\x80\x00\x00\x4E\x00), (0x98, b\x3e\x07), (0x35, b\x00), # 开 tearing effect 输出如果使用 (0x21, None), # 关闭显示反转 (0x11, None, 120), # 退出睡眠模式并延时120ms (0x29, None, 120), # 开启显示并延时120ms ] for cmd, data, *delay in init_cmds: self._write_cmd(cmd) if data: self._write_data(data) if delay: time.sleep_ms(delay[0])你需要关注的关键命令0x36 (MADCTL)内存访问控制。这个命令的参数决定了屏幕的旋转方向、颜色RGB/BGR顺序、行列地址更新顺序。例如b\x08是默认的横屏模式。如果你发现屏幕颜色红蓝反了可能就是BGR/RGB顺序不对如果显示内容旋转了90度就需要修改这个参数。常见的值有0x00竖屏、0x60旋转180度、0xC0旋转270度。0x3A像素格式。b\x55对应16位RGB565这是我们使用的格式。务必确认这里设置正确。0x11和0x29退出睡眠和开启显示。它们后面的延时120ms非常重要给屏幕足够的时间完成内部状态切换跳过或缩短延时可能导致初始化不完整屏幕无显示或显示异常。4. 从零开始的完整接线与烧录实操4.1 硬件准备与接线图假设我们使用一块ESP32开发板如ESP32-WROOM-32和一块GC9A01 1.28英寸圆形SPI屏幕。所需材料清单ESP32开发板 x1GC9A01 1.28英寸 SPI TFT屏 x1杜邦线母对母若干可选面包板用于固定连接接线对照表GC9A01屏幕引脚ESP32 GPIO引脚功能说明VCC3.3V电源务必接3.3V接5V会烧毁屏幕GNDGND电源地SCL (SCK)GPIO 18SPI时钟线SDA (MOSI)GPIO 23SPI数据线主出从入RES (RST)GPIO 4复位引脚低电平有效DC (D/C)GPIO 2数据/命令选择引脚CSGPIO 5片选引脚低电平有效BLGPIO 12 (或接3.3V)背光控制。接GPIO可通过代码调光接3.3V则常亮。实操心得GPIO的选择有一定灵活性除了几个专用的SPI引脚ESP32的SPI1: SCK18, MOSI23, MISO19其他如RST、DC、CS可以接任何空闲的GPIO。但建议避开一些有特殊启动功能的引脚如GPIO0, GPIO2, GPIO15等或者确保在启动时它们处于正确的电平状态以免导致ESP32无法启动。上表中的选择是经过验证的稳定组合。4.2 MicroPython固件烧录与驱动部署烧录MicroPython固件到ESP32从MicroPython官网下载最新的ESP32通用固件.bin文件。使用esptool.py工具进行烧录。连接ESP32按住BOOT键再按一下EN键进入下载模式。执行命令请根据你的串口修改COMxesptool.py --chip esp32 --port COM3 --baud 460800 write_flash -z 0x1000 esp32-xxx.bin烧录成功后使用串口工具如PuTTY、Thonny连接ESP32看到提示符即表示成功。上传驱动文件将前面编写的完整驱动代码保存为一个文件例如gc9a01.py。使用Thonny IDE、VS Code with Pymakr插件或ampy命令行工具将gc9a01.py文件上传到ESP32的根目录。上传一个简单的测试脚本main.pyimport machine import gc9a01 import time # 初始化SPI spi machine.SPI(1, baudrate40000000, polarity0, phase0, bits8, firstbitmachine.SPI.MSB) # 初始化引脚 dc machine.Pin(2, machine.Pin.OUT) cs machine.Pin(5, machine.Pin.OUT) rst machine.Pin(4, machine.Pin.OUT) bl machine.Pin(12, machine.Pin.OUT) # 背光控制 # 创建屏幕对象 tft gc9a01.GC9A01_SPI(spi, dc, cs, rst, bl) # 测试显示 tft.fill(tft.rgb(255,0,0)) # 填充红色 tft.show() time.sleep(1) tft.fill(tft.rgb(0,255,0)) # 填充绿色 tft.show() time.sleep(1) tft.fill(tft.rgb(0,0,255)) # 填充蓝色 tft.show() time.sleep(1) tft.fill(0) # 填充黑色 tft.show() # 显示文字 tft.text(Hello GC9A01!, 40, 100, tft.rgb(255,255,255)) tft.show()上传main.py后重启ESP32屏幕应该依次显示红、绿、蓝三色最后显示“Hello GC9A01!”文字。5. 高级应用与性能提升技巧5.1 利用framebuf内置图形功能一旦驱动层工作正常你就可以充分利用MicroPythonframebuf库的所有功能来绘制图形界面而无需自己计算像素点。# 假设tft是已初始化的GC9A01_SPI对象 # 1. 绘制基本形状 tft.rect(10, 10, 100, 50, tft.rgb(255, 255, 0)) # 画黄色矩形框 (x, y, w, h, color) tft.fill_rect(50, 70, 60, 40, tft.rgb(0, 255, 255)) # 填充青色矩形 tft.line(0, 0, 239, 239, tft.rgb(255, 0, 255)) # 画一条品红色对角线 tft.ellipse(120, 120, 50, 30, tft.rgb(0, 255, 0), True) # 画一个填充的绿色椭圆 # 2. 显示文本 (注意framebuf内置字体是8x8像素很小) tft.text(Temp: 25.6C, 20, 200, tft.rgb(255,255,255)) # 3. 显示图像 # 需要先将图像转换为字节数组RGB565格式。可以使用离线工具转换。 # image_data b\x... # 很长的字节数组 # tft.blit(framebuf_obj, x, y) # 但framebuf.blit需要另一个framebuf对象 # 更常见的是使用image2py之类的工具生成.py文件直接包含数据。 # 4. 双缓冲与局部刷新高级优化 # framebuf本身不支持双缓冲。但你可以创建两个buffer和FrameBuffer对象。 buffer1 bytearray(240*240*2) buffer2 bytearray(240*240*2) fb1 framebuf.FrameBuffer(buffer1, 240, 240, framebuf.RGB565) fb2 framebuf.FrameBuffer(buffer2, 240, 240, framebuf.RGB565) # 在fb1上绘图然后快速切换显示fb2的内容可以减少闪烁。但实现稍复杂且内存占用翻倍。5.2 集成LVGL图形库构建复杂UI对于需要滑块、按钮、图表等复杂交互的项目LVGL是终极选择。下面是在ESP32上为GC9A01配置LVGL的简要步骤。准备LVGL MicroPython库从LVGL官方GitHub仓库下载或通过mip安装LVGL的MicroPython绑定。import mip mip.install(github:lvgl/lv_micropython)创建显示驱动接口你需要编写一个类将我们的GC9A01_SPI驱动适配到LVGL所需的接口。核心是实现一个flush回调函数这个函数负责将LVGL绘制好的区域数据拷贝到屏幕上。import lvgl as lv import gc9a01 # 我们自己的驱动 # 初始化硬件同上 spi machine.SPI(...) tft gc9a01.GC9A01_SPI(spi, ...) # 初始化LVGL lv.init() # 创建显示缓冲区双缓冲推荐 disp_buf lv.disp_draw_buf_t() buf1 bytearray(240*10*2) # 缓冲区1可存储10行像素 buf2 bytearray(240*10*2) # 缓冲区2 disp_buf.init(buf1, buf2, len(buf1)//2) # 创建显示驱动 disp_drv lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.draw_buf disp_buf disp_drv.flush_cb disp_flush # 这是关键的回调函数 disp_drv.hor_res 240 disp_drv.ver_res 240 lv.disp_drv_register(disp_drv) # 实现flush回调函数 def disp_flush(drv, area, color_p): # 将LVGL生成的color_p数据写入tft的指定区域(area) x1, y1, x2, y2 area.x1, area.y1, area.x2, area.y2 # 这里需要实现将color_p指向的数据通过tft驱动写入屏幕从(x1,y1)到(x2,y2)的矩形区域。 # 通常需要调用tft驱动的_set_window和_write_data方法。 # 伪代码如下 # tft._set_window(x1, y1, x2, y2) # tft._write_data(color_p) # 注意数据格式转换 lv.disp_flush_ready(drv) # 必须调用通知LVGL刷新完成实现完整的disp_flush函数需要深入驱动底层涉及到窗口设置和内存数据搬运。网上有成熟的gc9a01 lvgl适配示例建议直接参考这些成熟代码。使用LVGL创建UI驱动注册成功后你就可以使用LVGL丰富的控件了。# 创建一个按钮 btn lv.btn(lv.scr_act()) btn.set_size(100, 50) btn.center() label lv.label(btn) label.set_text(Click Me!)运行后屏幕上就会显示一个居中的按钮。LVGL会处理触摸或按键输入并更新UI。注意事项在ESP32上运行LVGL特别是使用双缓冲时对内存PSRAM和CPU要求较高。如果出现内存不足错误需要减小缓冲区大小、简化UI或使用带有PSRAM的ESP32型号如ESP32-S3。6. 疑难杂症排查与实战经验即使按照步骤操作也难免会遇到问题。下面是我在调试过程中遇到的一些典型问题及解决方法。6.1 屏幕完全不亮无背光检查电源首先用万用表测量屏幕VCC和GND之间是否有3.3V电压。ESP32的3.3V引脚输出能力有限如果同时驱动多个外设可能导致电压被拉低。尝试单独给屏幕供电。检查背光引脚如果BL引脚接的是GPIO确认代码里将其设置为高电平输出bl.value(1)。如果BL直接接3.3V则背光应常亮。检查复位时序确保rst引脚在初始化时执行了正确的复位操作低-延时-高。可以尝试在代码中手动执行一次复位。rst.value(0) time.sleep_ms(100) rst.value(1) time.sleep_ms(100)6.2 屏幕亮但无显示白屏、花屏、条纹检查SPI通信这是最常见的问题。首先确认SCK、MOSI、DC、CS引脚连接是否正确且牢固。然后尝试降低SPI波特率从1_000_0001MHz开始测试排除因接线质量问题导致的高速通信失败。检查初始化序列初始化序列不正确或延时不够是导致花屏的主因。确保0x11和0x29命令后有足够的延时120ms。可以尝试在网上搜索其他版本的GC9A01初始化序列进行替换测试。检查MADCTL参数0x36命令的参数错误可能导致显示内容在屏幕外或颜色通道错乱。尝试改为b\x00或b\x60等常见值。检查像素格式确认0x3A命令的参数是b\x5516位RGB565。检查缓冲区大小确认创建的bytearray大小是width * height * 2。计算错误会导致内存越界和随机花屏。6.3 显示内容错位、旋转或颜色异常旋转问题修改0x36 (MADCTL)命令的参数。常见值0x00: 竖屏0度旋转。0x60: 横屏180度旋转。0xC0: 竖屏270度旋转。0xA0: 横屏0度旋转镜像需要测试。颜色问题红蓝互换同样是MADCTL命令其中有一位控制RGB/BGR顺序。尝试将参数0x08改为0x00或反之。也可以尝试在驱动代码中交换rgb()函数中R和B分量的位置。显示区域不对检查show()方法中的窗口设置命令0x2A,0x2B参数是否正确。起始和结束地址应该是(0, 0, width-1, height-1)。6.4 性能问题刷新慢、闪烁提高SPI波特率在确保稳定的前提下逐步提高machine.SPI的baudrate参数。ESP32可以尝试80_000_000。优化show()方法确保是全屏一次性数据传输避免循环。检查是否有不必要的延时。使用局部刷新如果只更新屏幕一小部分如一个数字可以修改驱动只发送对应区域的像素数据而不是全屏。这需要维护一个“脏矩形”区域并计算对应的内存偏移实现较复杂但对性能提升巨大。MicroPython固件优化使用最新的MicroPython固件有时包含了性能改进。对于ESP32可以尝试启用“OTA优化”或使用专门针对性能编译的固件。6.5 MicroPython内存不足缓冲区是内存大户一个240x240 RGB565的帧缓冲区需要115.2KB内存。ESP32无PSRAM的可用内存可能只有100多KB这几乎会被全部占用。解决方案使用分辨率更低的屏幕。使用单色模式每像素1位但这对于GC9A01这样的彩色屏没有意义。使用ESP32-S3等带有外部PSRAM的型号。如果使用LVGL使用较小的双缓冲区如1/10屏幕大小并让LVGL分块刷新。及时垃圾回收在大量创建临时对象如字符串、字节数组后手动调用gc.collect()回收内存。冻结字节码将驱动库等不常变化的代码“冻结”到固件中可以节省RAM。但这需要自己编译MicroPython固件。驱动一块屏幕就像和它对话初始化序列是问候语SPI时钟是语速数据是沟通的内容。一开始的生疏和误解各种花屏、不亮都是正常的。耐心检查每一句“问候”初始化命令确保“语速”对方能跟上SPI频率并且用对方能理解的语言RGB565格式最终一定能建立起稳定流畅的沟通。这套驱动代码我在智能手表、桌面天气站、便携游戏机好几个项目里都用过稳定性是经过考验的。如果你在移植到其他MCU比如RP2040时遇到问题重点检查SPI配置和引脚初始化逻辑都是相通的。本文还有配套的精品资源点击获取