1. 项目概述与核心价值如果你手头有一块闲置的树莓派想给它配个小屏幕做个状态监控器、迷你信息站或者DIY一个便携游戏机那么连接一块TFT显示屏几乎是必经之路。但当你真正动手时可能会被一堆引脚、SPI、驱动芯片这些术语搞得头大。别担心这正是我们今天要彻底搞明白的事情。简单来说这个项目就是用树莓派的SPI接口通过Python代码来点亮并控制一块TFT显示屏。它不像HDMI那样“即插即用”需要你手动接线、配置软件但换来的是极致的灵活性和对硬件的深度掌控。你不再仅仅是把树莓派当成一台小电脑而是真正把它当作一个嵌入式系统的核心去驱动一个定制化的显示终端。无论是显示一张图片、绘制几个图形还是实时刷新系统状态比如CPU温度、内存使用率你都能用几行Python代码轻松实现。这个方案的核心价值在于“降维打击”。过去在单片机上驱动显示屏往往要跟寄存器、时序图死磕写一堆底层C代码。而现在借助Adafruit CircuitPython RGB Display库和Pillow这样的成熟Python库我们把复杂的硬件通信和图像处理封装成了简洁易懂的API。你只需要关心“我想画什么”而不用太操心“数据是怎么一位一位送过去的”。这极大地降低了嵌入式图形开发的门槛让创意能更快地落地。接下来我会带你从硬件连接到软件编程完整走一遍流程。无论你用的是常见的ILI93412.2寸到3.5寸屏、小巧的ST77891.3寸、1.54寸IPS屏还是OLED屏SSD1331、SSD1351其核心思路都是一致的。我们会重点拆解三个经典示例显示图片、绘制图形文字、以及实时显示系统信息。在这个过程中我会穿插我实际调试中踩过的坑和总结的技巧让你少走弯路。2. 硬件连接从引脚定义到安全上电在写第一行代码之前正确的硬件连接是成功的一半。这一步错了后面全是徒劳。我们先来彻底理解SPI接口和各个引脚的作用。2.1 SPI接口与引脚功能解析SPISerial Peripheral Interface是一种同步、全双工的串行通信总线。你可以把它想象成一条多车道的高速公路主设备树莓派控制着交通信号灯时钟指挥数据车辆比特流在两条独立的车道MOSI和MISO上同时进出从设备显示屏。对于我们的TFT屏通常只用到主设备发送数据到从设备所以MISO线经常不用接。树莓派上的硬件SPI接口有两组SPI0和SPI1。最常用的是SPI0对应的引脚是SCLK (GPIO11/物理引脚23): 串行时钟。由树莓派产生所有数据传输都跟随着这个时钟的节拍。时钟频率波特率决定了通信速度。MOSI (GPIO10/物理引脚19): 主设备输出从设备输入。树莓派通过这根线向显示屏发送命令和数据。MISO (GPIO9/物理引脚21): 主设备输入从设备输出。显示屏可以通过这根线向树莓派回传数据但在单纯显示场景下通常不用。CE0 (GPIO8/物理引脚24) 和 CE1 (GPIO7/物理引脚26): 片选引脚。当总线上挂载了多个SPI设备时用这个引脚来“点名”要和哪个设备通信。我们通常用CE0。除了这些标准的SPI引脚驱动TFT屏还需要几个额外的GPIODC (Data/Command): 这是最关键的控制线之一。它告诉显示屏当前从MOSI线发过来的数据是一个“命令”比如设置显示区域、旋转方向还是一帧要显示的“图像数据”。显示屏内部有两个寄存器就靠这个引脚的电平高低来区分写入哪一个。RST (Reset): 复位引脚。给一个低电平脉冲可以让显示屏内部状态机复位从头开始初始化。在程序启动时或屏幕显示异常时非常有用。VCC和GND: 电源和地。特别注意绝大多数3.3V供电的TFT屏其逻辑电平也是3.3V必须接树莓派的3.3V引脚物理引脚1或17和任意GND引脚。接错5V很可能烧毁屏幕或树莓派GPIOBL (Backlight): 背光控制。有些屏幕的背光是常亮的接VCC即可有些则可以通过一个GPIO单独控制其开关或PWM调光这能有效省电。2.2 不同驱动芯片的接线实战根据你屏幕的主控芯片不同接线可能略有差异。下面这个表格汇总了最常见几种屏幕的接线方法你可以对号入座。接线前请务必断开树莓派电源屏幕类型/主控芯片树莓派引脚 (物理引脚编号)屏幕引脚备注通用SPI TFT (ILI9341, ST7789, ST7735等)3.3V (Pin 1)VCC / Vin核心电源必须接3.3VGND (Pin 6, 9, 14, 20, 25等)GND接任意地线GPIO11/SCLK (Pin 23)SCL / CLK时钟线GPIO10/MOSI (Pin 19)SDA / MOSI数据线GPIO8/CE0 (Pin 24)CS / SS片选低电平有效GPIO25 (Pin 22)DC / RS / A0数据/命令选择GPIO24 (Pin 18)RST / RESET复位可接可不接程序控制带独立背光控制的屏幕GPIO26 (Pin 37) 或其他GPIOBL / LED背光控制高电平点亮需要切换模式的屏幕 (如某些2.8寸屏)3.3V (Pin 1)IM0, IM1等查阅屏幕背面通过跳线帽或焊点将其接到3.3V以切换到SPI模式实操心得关于电源的坑我遇到过最隐蔽的问题就是电源。一块3.5寸屏在工作电流较大时如果仅通过杜邦线从树莓派取电可能会因为线阻导致屏幕端的电压被拉低造成花屏或无法启动。如果你的屏幕比较大或者连接线比较长强烈建议使用外部3.3V稳压模块单独给屏幕供电并将地与树莓派共地。这能从根本上杜绝因供电不足导致的玄学问题。接线完成后先别急着上电。花一分钟做一次安全检查目视检查所有杜邦线插接牢固没有金属部分裸露短路的风险。逻辑检查VCC确认接的是3.3V不是5V。DC、RST等信号线接的是GPIO不是电源。上电测试先只接VCC和GND通电观察屏幕背光是否正常点亮有无异常发热或异味。如果正常再断电接上所有信号线。3. 软件环境搭建与核心库解析硬件准备就绪现在我们来武装树莓派的软件系统。这一步的目标是让树莓派能用Python通过SPI“说话”并且有处理图像的能力。3.1 启用SPI接口与安装基础依赖树莓派默认是关闭SPI接口的我们需要先打开它。启用SPI 在终端中输入sudo raspi-config用方向键选择Interface Options-SPI-Yes来启用SPI。完成后重启树莓派sudo reboot。验证SPI已启用 重启后在终端输入ls /dev/spi*。如果看到/dev/spidev0.0和/dev/spidev1.0如果有的话说明SPI驱动加载成功。spidev0.0就对应着我们使用的SPI0总线CE0片选。安装Python3和pip 最新的Raspberry Pi OS通常已预装。但为了确保可以更新并安装sudo apt update sudo apt install python3 python3-pip -y3.2 安装核心Python库我们的项目依赖于三个核心库它们分工明确Adafruit-Blinka这是CircuitPython在标准PythonCPython环境下的兼容层。你可以理解为它是一套“翻译器”把CircuitPython那套操作硬件的友好API翻译成树莓派Linux系统能理解的底层操作比如读写/dev/spidev设备文件。没有它我们的Python代码就无法直接控制SPI和GPIO引脚。sudo pip3 install adafruit-blinkaAdafruit CircuitPython RGB Display这是今天的主角库。它包含了ILI9341、ST7789、ST7735、HX8357、SSD1351、SSD1331等几乎所有常见TFT/OLED显示屏的驱动。它利用Blinka与硬件通信并提供了统一的、高级的接口来操作屏幕。sudo pip3 install adafruit-circuitpython-rgb-display注意如果你之前为了使用“PiTFT”等内核驱动而安装过相关软件可能需要先卸载它们以免冲突。因为内核驱动会独占SPI设备导致我们的Python库无法访问。通常运行sudo apt remove --purge pitft之类的命令可以清理。Pillow (PIL Fork)Python图像处理库的现代版本。我们的绘图、文字渲染、图片缩放裁剪等所有图形操作都依赖于它。rgb-display库最终会把Pillow生成的图像数据发送到屏幕。sudo apt install python3-pil -y # 如果通过pip安装Pillow可能需要额外系统库 # sudo apt install libopenjp2-7 libtiff5 libatlas-base-dev -y安装字体可选但推荐 第二个示例中需要用到TrueType字体。DejaVu字体是常用选择sudo apt install fonts-dejavu -y3.3 库的工作原理与选型思考你可能会问为什么用这个“CircuitPython”的库而不是直接找某个芯片的“Python SPI”库这里涉及到嵌入式开发的一个权衡抽象层级。最底层是直接操作Linux的spidev你需要自己构造每个命令和数据帧非常繁琐且容易出错。中间层是一些针对特定芯片如luma.oled的库封装了基础命令。而Adafruit的rgb-display库属于较高层级的抽象它最大的优势是统一性和易用性。统一性无论你手头是ILI9341还是ST7789初始化屏幕的代码只有一行不同就是disp 后面那个类名。绘图、显示图像的API完全一致。这意味着你的应用代码可以轻松在不同屏幕间移植。易用性它直接整合了Pillow。你不需要关心颜色格式转换RGB565 vs RGB888、内存缓冲区管理你只需要用熟悉的Pillow接口ImageDraw画图然后调用disp.image()显示即可。这大大降低了开发难度。当然高抽象层级会带来一点点性能开销因为它可能不是为最高帧率优化的。但对于绝大多数信息显示、UI界面、监控面板应用来说其性能绰绰有余。所以除非你在做需要极高刷新率的游戏或动画否则adafruit-circuitpython-rgb-displayPillow是最佳选择。4. 基础显示示例深度剖析环境搭好了我们来敲代码。我会把官方示例拆开揉碎不仅告诉你“怎么写”更解释清楚“为什么这么写”。4.1 示例一显示一张图片自动缩放与居中裁剪这个示例的完整代码在开头的材料里已经给出。我们逐段分析其精妙之处。第一部分导入与硬件配置import board import digitalio from PIL import Image, ImageDraw from adafruit_rgb_display import ili9341 # 以ILI9341为例 # 引脚配置 - 这是与硬件接线对应的逻辑映射 cs_pin digitalio.DigitalInOut(board.CE0) # 片选接物理引脚24 dc_pin digitalio.DigitalInOut(board.D25) # 数据/命令接物理引脚22 reset_pin digitalio.DigitalInOut(board.D24) # 复位接物理引脚18 # 波特率设置24MHz是很多SPI屏的极限速度稳妥起见可以从低开始试 BAUDRATE 24000000 # 24 MHz # 初始化硬件SPI总线 spi board.SPI()board.CE0,board.D25这些是Blinka库定义的常量它们对应树莓派BCM编号的GPIO而不是物理引脚号。这保证了代码在不同派系树莓派如Zero, 3B, 4B上的通用性。BAUDRATE通信速度。不是越高越好过高的速率可能导致长线传输时数据出错花屏。如果出现花屏尝试降低到1200000012MHz或80000008MHz。第二部分显示屏对象初始化disp ili9341.ILI9341( spi, rotation90, # 屏幕旋转90度 cscs_pin, dcdc_pin, rstreset_pin, baudrateBAUDRATE, )rotation参数至关重要。它决定了屏幕的坐标系原点0,0在哪里。90通常表示竖屏模式原点在左上角X轴向右Y轴向下。如果你发现图片方向不对修改这个值0, 90, 180, 270即可。对于其他型号屏幕只需注释掉ili9341.ILI9341这一行取消注释对应你屏幕的那一行。例如对于1.3寸ST7789屏# disp ili9341.ILI9341(...) disp st7789.ST7789(spi, height240, y_offset80, rotation180)这里的height和y_offset是因为这块屏幕的驱动IC实际可控制区域与物理面板有偏移需要参数校正。这些参数通常能在屏幕的规格书或卖家提供的示例代码里找到。第三部分图像处理的核心算法缩放与裁剪这是本示例最核心、最值得学习的部分。它的目标是让任意尺寸的图片都能完美填充任意尺寸的屏幕不留黑边也不丢失图片主体。# 获取屏幕尺寸考虑旋转后的逻辑尺寸 if disp.rotation % 180 90: height disp.width # 旋转后逻辑高度等于物理宽度 width disp.height # 逻辑宽度等于物理高度 else: width disp.width height disp.height # 计算图片和屏幕的宽高比 image_ratio image.width / image.height screen_ratio width / height # 决定缩放策略 if screen_ratio image_ratio: # 屏幕比图片“更瘦长”。以高度为基准缩放宽度会超出。 scaled_width image.width * height // image.height scaled_height height else: # 屏幕比图片“更矮胖”。以宽度为基准缩放高度会超出。 scaled_width width scaled_height image.height * width // image.width # 执行缩放使用高质量的双三次插值算法 image image.resize((scaled_width, scaled_height), Image.BICUBIC) # 计算裁剪区域使图片居中 x scaled_width // 2 - width // 2 y scaled_height // 2 - height // 2 image image.crop((x, y, x width, y height))算法逻辑解读 假设屏幕是240x320竖屏图片是800x600。屏幕比例screen_ratio 240/320 0.75图片比例image_ratio 800/600 ≈ 1.333因为0.75 1.333屏幕更“瘦”。所以选择匹配高度进行缩放。scaled_height 320scaled_width 800 * 320 // 600 ≈ 426缩放后图片变成426x320。宽度(426)大于屏幕宽度(240)。居中裁剪从缩放后图片的( (426-240)//2, (320-320)//2 )即(93, 0)这个点开始裁剪出240x320的区域。 最终效果图片被等比缩放并裁掉左右多余的部分完美填充屏幕高度且主要内容居中。避坑指南图片路径与权限代码中Image.open(blinka.jpg)假设图片和Python脚本在同一目录。如果报错FileNotFoundError请使用绝对路径如Image.open(/home/pi/project/blinka.jpg)。同时确保运行脚本的用户如pi有该文件的读取权限。4.2 示例二绘制图形与文字构建静态UI这个示例展示了用代码“画”出界面的基本方法。它对于创建仪表盘、按钮、标签等静态元素非常有用。核心代码段解析from PIL import ImageFont # 定义常量方便调整UI布局 BORDER 20 FONTSIZE 24 # 1. 画一个绿色背景全屏矩形 draw.rectangle((0, 0, width, height), fill(0, 255, 0)) disp.image(image) # 可以立即显示也可以最后一起显示 # 2. 在绿色背景上画一个紫色的内框矩形 # 矩形左上角坐标(BORDER, BORDER)右下角坐标(width-BORDER-1, height-BORDER-1) draw.rectangle((BORDER, BORDER, width - BORDER - 1, height - BORDER - 1), fill(170, 0, 136)) # 3. 加载字体并绘制居中文字 font ImageFont.truetype(/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf, FONTSIZE) text Hello World! # 获取文字占据的像素大小这是实现居中的关键 (font_width, font_height) font.getsize(text) # 计算文字左上角的起始坐标使其位于屏幕正中央 text_x width // 2 - font_width // 2 text_y height // 2 - font_height // 2 draw.text((text_x, text_y), text, fontfont, fill(255, 255, 0)) # 黄色文字关键点与技巧颜色表示Pillow中颜色可以用RGB元组(R, G, B)每个值0-255也可以用十六进制字符串如#FF00FF甚至可以直接写red等颜色名。坐标系统原点(0,0)在左上角X轴向右Y轴向下。这与常见的数学坐标系不同画图时要注意。getsize()方法在绘制动态文本或需要精确布局时必须先获取文本的渲染尺寸。font.getsize(text)返回一个元组(width, height)。注意在Pillow较新版本如9.x以上中getsize()已被弃用需改用font.getbbox(text)[2:]或font.getlength(text)结合font.getmetrics()来获取尺寸。这是一个常见的兼容性问题。立即显示 vs 批量显示你可以每画一个元素就调用一次disp.image(image)来立即更新屏幕效率低可能闪烁也可以等所有元素画完最后调用一次来更新推荐无闪烁。4.3 示例三动态显示系统信息打造监控面板这是最实用的例子将树莓派变成一个实时系统监控器。其核心思路是在一个循环中不断获取系统信息清空画布重新绘制然后刷新屏幕。循环结构与信息获取import subprocess import time while True: # 1. 清屏 draw.rectangle((0, 0, width, height), outline0, fill0) # 2. 使用shell命令获取系统信息 # 获取IP地址 cmd hostname -I | cut -d -f1 IP IP: subprocess.check_output(cmd, shellTrue).decode(utf-8).strip() # 获取CPU负载1分钟平均值 cmd top -bn1 | grep load | awk {printf \CPU Load: %.2f\, $(NF-2)} CPU subprocess.check_output(cmd, shellTrue).decode(utf-8) # 获取内存使用率 cmd free -m | awk NR2{printf \Mem: %s/%s MB %.2f%%\, $3,$2,$3*100/$2 } MemUsage subprocess.check_output(cmd, shellTrue).decode(utf-8) # 获取根目录磁盘使用率 cmd df -h | awk \$NF/{printf Disk: %d/%d GB %s, $3,$2,$5}\ Disk subprocess.check_output(cmd, shellTrue).decode(utf-8) # 获取CPU温度 cmd cat /sys/class/thermal/thermal_zone0/temp | awk {printf \CPU Temp: %.1f C\, $1 / 1000} Temp subprocess.check_output(cmd, shellTrue).decode(utf-8) # 3. 逐行绘制文本 y padding # 从顶部开始 draw.text((x, y), IP, fontfont, fill#FFFFFF) y font.getsize(IP)[1] # 移动到下一行 draw.text((x, y), CPU, fontfont, fill#FFFF00) y font.getsize(CPU)[1] # ... 绘制其他行 # 4. 更新屏幕并短暂休眠 disp.image(image) time.sleep(0.5) # 控制刷新频率例如每0.5秒更新一次深度优化与问题排查性能与闪烁在while循环中不断清屏、绘图、刷新如果处理速度慢可能会看到明显的闪烁。优化方法双缓冲Off-screen Buffer我们已经在做了所有绘图操作都在内存中的image对象上完成最后调用disp.image(image)一次性传输到屏幕。这是消除撕裂和闪烁的关键。减少不必要的重绘如果信息变化不快如IP地址可以不用每次循环都获取和重绘。调整休眠时间time.sleep(0.5)将刷新率控制在2Hz对于系统监控足够了。提高刷新率减小sleep值会增加CPU负担。subprocess的安全与效率频繁调用shellTrue的subprocess是有开销和潜在风险的。对于生产环境可以考虑使用Python标准库获取信息如psutil库需安装pip3 install psutil来获取CPU、内存、磁盘信息更高效安全。将IP地址获取等不常变的信息移到循环外。字体渲染优化如果文字边缘有锯齿可以尝试使用更大的字体尺寸进行渲染然后缩放到需要的大小或者使用抗锯齿字体。Pillow的ImageFont.truetype默认质量不错。5. 进阶技巧与深度优化掌握了基础显示后我们可以玩点更花的让显示效果和性能更上一层楼。5.1 背光与电源管理很多屏幕的背光BL引脚是可以通过PWM脉冲宽度调制来控制亮度的这不仅能保护视力、适应不同环境光还能省电。import board import digitalio import pwmio # 用于PWM控制 # 假设背光接在GPIO18 (PWM0通道) backlight_pin board.D18 # 创建PWM对象频率500Hz对于背光调节足够 backlight pwmio.PWMOut(backlight_pin, frequency500, duty_cycle0) # 设置亮度为50% (65535是16位PWM的最大值) backlight.duty_cycle 65535 // 2 # 在程序退出前可以关闭背光以省电 # backlight.duty_cycle 0技巧你可以根据环境光传感器如BH1750的读数动态调整背光亮度或者设置一个定时器在无操作一段时间后自动调暗或关闭背光。5.2 局部刷新与动画优化全屏刷新即使只改了一个像素对于SPI屏来说数据量也很大。如果只是更新部分区域如一个数字、一个进度条可以只刷新那一块。# 假设我们只更新屏幕右上角一个80x40的区域显示一个变化的数字 update_region (width-80, 0, width, 40) # (left, top, right, bottom) # 1. 在这个区域画新的内容先在内存图像上操作 draw.rectangle(update_region, fill(0,0,0)) # 先清空该区域 draw.text((width-75, 10), new_value, fontfont, fill(255,255,255)) # 2. 从内存图像中裁剪出这个区域 partial_image image.crop(update_region) # 3. 告诉显示屏只更新这个区域需要驱动库支持部分刷新有些基础驱动可能不支持 # 通常需要发送设置列地址和行地址的命令然后只发送这部分数据。 # Adafruit库的image()方法默认是全屏更新。对于高级局部刷新可能需要直接操作底层framebuffer或寻找支持局部刷新的驱动变体。对于简单动画如进度条一个取巧的办法是在内存中准备好下一帧的完整图像然后一次性disp.image()更新。虽然传输了全屏数据但避免了在屏幕上进行多次局部绘制造成的闪烁观感更平滑。5.3 多屏幕管理与驱动扩展如果你需要驱动两块甚至更多同型号的屏幕可以利用SPI总线的多片选特性。import board import digitalio import busio # 使用busio可以更灵活地配置SPI # 定义两个片选引脚 cs_pin_1 digitalio.DigitalInOut(board.CE0) # 屏幕1 cs_pin_2 digitalio.DigitalInOut(board.CE1) # 屏幕2 dc_pin digitalio.DigitalInOut(board.D25) reset_pin digitalio.DigitalInOut(board.D24) # 初始化SPI总线 spi busio.SPI(board.SCLK, board.MOSI, board.MISO) # 显式指定引脚 # 创建两个显示对象使用不同的CS引脚 disp1 ili9341.ILI9341(spi, cscs_pin_1, dcdc_pin, rstreset_pin, baudrate24000000) disp2 ili9341.ILI9341(spi, cscs_pin_2, dcdc_pin, rstreset_pin, baudrate24000000) # 使用时分别对disp1和disp2调用image()方法即可注意硬件SPI总线是共享的同一时间只能和一个设备通信。库内部通过控制CS引脚的电平来切换设备。你需要确保在操作一个屏幕时另一个屏幕的CS引脚处于“未选中”高电平状态。Adafruit库在每次通信时会自动管理CS引脚所以直接使用上述方法是安全的。6. 常见问题排查与实战心得折腾硬件没有不踩坑的。下面是我总结的一些典型问题及其解决方法。6.1 问题速查表现象可能原因排查步骤与解决方案屏幕全白/全黑/无反应1. 电源问题电压不足或接错2. 复位信号问题3. 主控芯片型号不对1.万用表检查测量屏幕VCC和GND之间电压是否为稳定的3.3V。2.检查RST引脚在代码初始化后尝试手动控制RST引脚拉低再拉高进行硬复位。3.核对驱动芯片查看屏幕背面或卖家资料确认主控芯片型号如ILI9341、ST7789并确保代码中初始化的类名与之匹配。花屏、条纹、乱码1. SPI波特率过高2. 接线松动或过长3. 电源干扰1.降低波特率将BAUDRATE从24000000逐步降至12000000、8000000试试。2.检查接线确保杜邦线接触良好尤其是CLK和MOSI。信号线尽量短20cm。3.加强电源滤波在屏幕的VCC和GND之间并联一个10uF~100uF的电解电容和一个0.1uF的陶瓷电容靠近屏幕引脚焊接。显示内容错位、偏移1. 屏幕初始化参数错误x_offset, y_offset2. 旋转方向设置错误1.查找屏幕资料搜索你的屏幕具体型号如“1.54寸 ST7789 偏移”找到正确的x_offset和y_offset参数。2.调整rotation尝试0, 90, 180, 270四个值。运行代码报错ModuleNotFoundErrorPython库未安装或安装位置不对1. 确认使用pip3 list查看adafruit-circuitpython-rgb-display和adafruit-blinka是否存在。2. 尝试使用sudo pip3 install --upgrade --force-reinstall重新安装。3. 检查Python解释器路径确保不是虚拟环境问题。图片显示颜色异常颜色格式不匹配BGR vs RGB在初始化显示屏对象时尝试添加bgrTrue参数例如disp st7735.ST7735R(spi, bgrTrue, ...)。有些屏幕驱动IC内部颜色顺序是BGR。文字显示为乱码或方框1. 字体文件路径错误2. 字体文件损坏或格式不支持3. Pillow版本问题1. 使用绝对路径指定字体文件如/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf。2. 尝试换一个系统自带的字体如/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf。3. 对于中文需要支持中文的TTF字体文件并确保文件路径正确。6.2 调试心法与实战技巧分步测试法不要一次性写完所有代码。先写一个最简单的测试脚本初始化屏幕然后只画一个全屏的纯色比如红色fill(255,0,0)。如果这能成功说明硬件连接和基础驱动是好的。然后再逐步增加功能。逻辑分析仪是你的朋友如果遇到顽固的花屏或通信问题有条件的话可以用逻辑分析仪或示波器抓一下SPI的CLK、MOSI、CS、DC波形。看时钟是否稳定数据在CS有效期间是否同步DC电平在发送命令和数据时是否正确切换。这是定位硬件/时序问题的终极手段。利用好print()调试在代码关键位置如初始化成功、开始绘图前添加print()语句输出当前状态、变量值。这能帮你确认程序执行到了哪一步。注意内存占用Pillow处理的图像对象是放在树莓派内存中的。一张240x320的RGB图像需要240 * 320 * 3 ≈ 230KB内存。如果你需要处理多张图片或高分辨率图片要注意树莓派尤其是Zero或1代的内存是否够用。及时使用del释放不再需要的图像对象。长期运行的稳定性对于需要7x24小时运行的信息屏要在代码中加入异常捕获和恢复机制。例如用try...except包裹主循环如果发生错误如SPI通信超时可以记录日志、尝试重新初始化屏幕而不是让整个程序崩溃。最后别忘了享受创造的乐趣。当你的代码成功点亮屏幕显示出第一句“Hello World”时那种成就感是无与伦比的。从这个基础项目出发你可以扩展出无数应用智能家居控制面板、复古游戏机、照片相框、网络天气站……硬件世界的大门就此敞开。