K230基础-显示画面

第十三章 显示画面-K230图形显示与人机交互

🎯 本章目标

掌握 K230 上驱动各类显示屏的方法,学会使用 LCD 屏幕(TFT)、OLED 屏幕 进行图像、文本、图形的显示,实现本地人机交互界面,完成"从摄像头采集 → 处理 → 显示"的完整视觉闭环。


1. 显示设备概述

在嵌入式系统中,常见的显示设备有:

类型 优点 缺点 适用场景
TFT LCD 彩色、高分辨率、亮度高 需背光、功耗高 人机界面、图像显示
OLED 自发光、高对比度、响应快 寿命有限、怕烧屏 小型设备、低功耗显示
ePaper 超低功耗、阳光下可读 刷新慢、黑白为主 电子标签、仪表盘

📌 本章重点:TFT LCD 与 OLED 显示驱动。


2. TFT LCD 屏幕驱动(SPI 接口)

2.1 常见型号与接口

  • 驱动芯片:ST7789、ILI9341、GC9A01
  • 接口:SPI(4线或3线)
  • 分辨率
    • ST7789:240×240、320×240
    • ILI9341:320×240
    • GC9A01:240×240(圆形屏)

2.2 硬件连接(以 ST7789 为例)

屏幕引脚 K230 引脚 说明
VCC 3.3V 电源
GND GND
SCL/SCK SPI SCLK 时钟
SDA/MOSI SPI MOSI 数据
RES 任意 GPIO 复位(低电平复位)
DC 任意 GPIO 数据/命令选择
CS 任意 GPIO 片选(低有效)
BLK 3.3V 或 PWM 背光控制

2.3 使用 st7789 库驱动 TFT

bash 复制代码
# 上传 st7789.py 到开发板
rshell -p /dev/ttyUSB0 cp st7789.py /pyboard/

GitHub: https://github.com/russhughes/st7789_mpy


2.4 初始化 TFT 屏幕

python 复制代码
from machine import SPI, Pin
import st7789
import vga1_8x8 as font
import vga1_16x32 as font2

# 引脚定义
SCLK_PIN = 6
MOSI_PIN = 8
CS_PIN   = 7
DC_PIN   = 10
RST_PIN  = 11

# FPIOA 映射 SPI
from fpioa_manager import fm
fm.register(SCLK_PIN, fm.fpioa.SPI1_SCLK)
fm.register(MOSI_PIN, fm.fpioa.SPI1_D0)
fm.register(CS_PIN,   fm.fpioa.GPIOHS0)
fm.register(DC_PIN,   fm.fpioa.GPIOHS1)
fm.register(RST_PIN,  fm.fpioa.GPIOHS2)

# 创建 SPI 对象
spi = SPI(SPI.SPI1, baudrate=40_000_000, polarity=0, phase=0)

# 初始化屏幕
cs = Pin(CS_PIN, Pin.OUT, value=1)
dc = Pin(DC_PIN, Pin.OUT, value=0)
rst = Pin(RST_PIN, Pin.OUT, value=1)

# 创建 ST7789 对象(240x240 圆形屏)
tft = st7789.ST7789(
    spi,
    240,
    240,
    reset=rst,
    dc=dc,
    cs=cs,
    backlight=None,
    rotation=0  # 0, 90, 180, 270
)

# 清屏
tft.fill(st7789.BLACK)

3. 实战项目一:TFT 文本与图形显示

python 复制代码
# === 1. 显示文本 ===
tft.text(font, "Hello K230", 10, 10, st7789.YELLOW)
tft.text(font2, "Display", 10, 40, st7789.WHITE)

# === 2. 画图形 ===
tft.pixel(100, 100, st7789.RED)                    # 画点
tft.line(50, 50, 150, 150, st7789.GREEN)           # 画线
tft.rect(200, 20, 60, 40, st7789.BLUE)             # 空心矩形
tft.fill_rect(200, 80, 60, 40, st7789.CYAN)        # 实心矩形
tft.circle(120, 120, 50, st7789.MAGENTA)           # 圆
tft.fill_circle(120, 120, 20, st7789.RED)          # 实心圆

# === 3. 显示颜色块 ===
tft.fill_rect(0, 200, 80, 40, st7789.RED)
tft.fill_rect(80, 200, 80, 40, st7789.GREEN)
tft.fill_rect(160, 200, 80, 40, st7789.BLUE)

4. 实战项目二:TFT 显示摄像头画面

4.1 摄像头 + TFT 实时显示

python 复制代码
import sensor
import time

# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)  # 320x240
sensor.skip_frames(time=2000)

clock = time.clock()

while True:
    clock.tick()

    # 拍摄图像
    img = sensor.snapshot()

    # 缩放以适应 240x240 屏幕
    img.resize(240, 240)

    # 显示到 TFT
    tft.blit_buffer(
        img.bytearray(),
        0, 0,
        240, 240,
        st7789.RGB565
    )

    # 显示 FPS
    fps = clock.fps()
    tft.fill_rect(0, 0, 100, 20, st7789.BLACK)
    tft.text(font, f"FPS: {fps:.1f}", 0, 0, st7789.YELLOW)

效果:实现"实时监控"画面。


5. 实战项目三:TFT 显示 AI 推理结果

python 复制代码
import kpu
import sensor

# 加载模型(假设已加载)
model = kpu.load("/sd/face_detect.kmodel")
kpu.set_outputs(model, 0, 1, 1, 2)

# 摄像头初始化
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time=2000)

while True:
    img = sensor.snapshot()

    # AI 推理
    fmap = kpu.run_with_output(model, img)
    plist = kpu.fmap_to_list(fmap)

    # 在图像上画框
    if plist:
        for r in plist:
            x, y, w, h = int(r[0]), int(r[1]), int(r[2]), int(r[3])
            img.draw_rectangle(x, y, w, h, color=(255, 0, 0))
            img.draw_string(x, y-10, "Face", color=(0, 255, 0))

    # 缩放并显示
    img.resize(240, 240)
    tft.blit_buffer(img.bytearray(), 0, 0, 240, 240, st7789.RGB565)

6. OLED 显示(I2C 接口)

6.1 使用 ssd1306

python 复制代码
from machine import I2C, Pin
from fpioa_manager import fm
import ssd1306

# FPIOA 映射
fm.register(2, fm.fpioa.I2C1_SDA)
fm.register(3, fm.fpioa.I2C1_SCL)

i2c = I2C(I2C.I2C1, freq=400_000, sda=Pin(2), scl=Pin(3))
oled = ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C)

oled.fill(0)
oled.text("K230 OLED", 0, 0)
oled.text("Camera + AI", 0, 20)
oled.show()

7. 高级技巧与优化

7.1 双缓冲机制(防撕裂)

python 复制代码
# 创建两个缓冲区
buf1 = bytearray(240 * 240 * 2)
buf2 = bytearray(240 * 240 * 2)
current_buf = buf1

# 在后台填充缓冲区,前台显示
tft.blit_buffer(current_buf, 0, 0, 240, 240, st7789.RGB565)

适用于动画、高刷新率场景。


7.2 背光控制(节能)

python 复制代码
fm.register(12, fm.fpioa.PWM0_OUT)
backlight = PWM(PWM.PWM0, freq=1000, duty=50, pin=12)

# 调节亮度
backlight.duty(10)  # 10% 亮度

7.3 字体与图标显示

  • 使用自定义字体(如 writer 模块)
  • 显示小图标(用 bitmap 数组)
python 复制代码
# 图标示例(16x16 心形)
heart = [
    0x00,0x7C,0xC6,0xC6,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xC6,0xC6,0x7C,0x00
]

8. 常见问题与调试

❌ 问题1:屏幕无显示

排查

  • 电源是否正常?
  • CS/DC/RST 是否正确连接?
  • SPI 时钟是否正常?

❌ 问题2:显示花屏或乱码

解决

  • 检查 blit_buffer 参数(格式、尺寸)
  • 确保图像数据是 RGB565 格式
  • 降低 SPI 速率测试

❌ 问题3:OLED 无反应

检查

  • I2C 地址是 0x3C 还是 0x3D
  • 是否调用 oled.show()
  • 上拉电阻是否正常?

9. 性能与限制

操作 耗时(240x240)
blit_buffer ~20ms(40MHz SPI)
文本显示 < 1ms
图形绘制 1~5ms

建议

  • 使用高速 SPI(40MHz)
  • 避免频繁全屏刷新
  • 优先更新局部区域

相关推荐
A9better8 小时前
嵌入式开发学习日志31——stm32之外部中断与定时器中断的差别与选择
stm32·单片机·学习
沐欣工作室_lvyiyi9 小时前
基于物联网的个人健康管理系统(论文+源码)
单片机·物联网·毕业设计·健康管理
蒋楼丶9 小时前
stm32和Zynq的中断抢占机制
stm32·单片机·嵌入式硬件
xyx-3v10 小时前
已知三极管的类型(NPN/PNP)和基极引脚,如何区分集电极(c)和发射极(e)
单片机·嵌入式硬件·学习
随机惯性粒子群11 小时前
STM32控制开发学习笔记【基于STM32 HAL库】
笔记·stm32·嵌入式硬件·学习
来生硬件工程师11 小时前
CH582 GPIO
c语言·开发语言·单片机
liujing1023292913 小时前
Day04_总线驱动
stm32
会编程的果子君13 小时前
面向对象实现LED灯
单片机·嵌入式硬件
阿华学长单片机设计15 小时前
【开源】基于STM32的新疆地区棉花智能种植系统
stm32·嵌入式硬件·开源