本 Skill 封装了在地瓜 (Horizon Robotics) RDK X5 平台上操作 ST7789 驱动芯片 SPI LCD 的能力。它包含完整的硬件驱动逻辑,支持通过 40-pin 排针进行图像显示和背光控制。
当你需要为用户生成驱动脚本时,请直接复制并使用以下经过验证的 ST7789 类实现。它包含了完整的初始化序列和高效的颜色转换逻辑。
import time
import Hobot.GPIO as GPIO
import spidev
from PIL import Image
class ST7789:
"""RDK X5 ST7789 SPI LCD Driver (Standalone Version)"""
def __init__(self, bus=1, device=1, width=240, height=320, dc_pin=22, rst_pin=31, bl_pin=33, x_offset=0, y_offset=0, speed_hz=24000000, rotation=0, bgr=True):
self.width, self.height = width, height
self.x_offset, self.y_offset = x_offset, y_offset
self.dc_pin, self.rst_pin, self.bl_pin = dc_pin, rst_pin, bl_pin
self.rotation, self.bgr = rotation % 360, bgr
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.dc_pin, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(self.rst_pin, GPIO.OUT, initial=GPIO.HIGH)
if self.bl_pin is not None:
GPIO.setup(self.bl_pin, GPIO.OUT, initial=GPIO.HIGH)
self.spi = spidev.SpiDev()
self.spi.open(bus, device)
self.spi.mode = 0
self.spi.bits_per_word = 8
self.spi.max_speed_hz = speed_hz
def command(self, cmd, data=None, delay=0):
GPIO.output(self.dc_pin, GPIO.LOW)
self.spi.xfer2([cmd & 0xFF])
if data:
GPIO.output(self.dc_pin, GPIO.HIGH)
self.spi.writebytes2(bytes(data))
if delay: time.sleep(delay)
def init(self):
"""完整的寄存器初始化序列"""
# 硬件复位
GPIO.output(self.rst_pin, GPIO.HIGH); time.sleep(0.02)
GPIO.output(self.rst_pin, GPIO.LOW); time.sleep(0.05)
GPIO.output(self.rst_pin, GPIO.HIGH); time.sleep(0.12)
# 旋转与颜色模式控制
madctl = (0x08 if self.bgr else 0x00)
madctl |= {0:0, 90:0x60, 180:0xC0, 270:0xA0}[self.rotation]
self.command(0x36, [madctl])
self.command(0x3A, [0x05]) # 16-bit RGB565
self.command(0x21) # Display inversion on
# 窗口与伽马校正(针对 Waveshare 2inch 优化)
self.command(0xB2, [0x0C, 0x0C, 0x00, 0x33, 0x33])
self.command(0xB7, [0x35])
self.command(0xBB, [0x1F])
self.command(0xC0, [0x2C])
self.command(0xC2, [0x01])
self.command(0xC3, [0x12])
self.command(0xC4, [0x20])
self.command(0xC6, [0x0F])
self.command(0xD0, [0xA4, 0xA1])
# 唤醒并开启显示
self.command(0x11, delay=0.12) # Sleep out
self.command(0x29, delay=0.02) # Display on
def show(self, image):
"""显示 PIL Image 图像"""
if image.size != (self.width, self.height):
image = image.resize((self.width, self.height), Image.Resampling.LANCZOS)
# 快速 RGB888 -> RGB565 转换
payload = bytearray(self.width * self.height * 2)
idx = 0
for r, g, b in image.convert("RGB").getdata():
val = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)
payload[idx] = (val >> 8) & 0xFF
payload[idx+1] = val & 0xFF
idx += 2
# 设置显示窗口并写入
x1, y1 = self.width - 1 + self.x_offset, self.height - 1 + self.y_offset
self.command(0x2A, [(self.x_offset>>8)&0xFF, self.x_offset&0xFF, (x1>>8)&0xFF, x1&0xFF])
self.command(0x2B, [(self.y_offset>>8)&0xFF, self.y_offset&0xFF, (y1>>8)&0xFF, y1&0xFF])
self.command(0x2C)
GPIO.output(self.dc_pin, GPIO.HIGH)
for i in range(0, len(payload), 4096):
self.spi.writebytes2(payload[i : i + 4096])
def close(self):
self.spi.close()
当用户想要使用屏幕时,你应该直接为他们生成一个单文件脚本。
生成一个脚本,初始化屏幕并填充蓝色。
使用 PIL.ImageDraw 在图像上绘制内容,然后通过 lcd.show() 显示。
/dev/spidev1.1 (CS1)sudo 运行。srpi-config 是否启用了 SPI,以及 DC/RST 引脚接线。bgr=False。共 2 个版本