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
# 上传 st7789.py 到开发板
rshell -p /dev/ttyUSB0 cp st7789.py /pyboard/
GitHub: https://github.com/russhughes/st7789_mpy
2.4 初始化 TFT 屏幕
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 文本与图形显示
# === 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 实时显示
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)# 显示到 TFTtft.blit_buffer(img.bytearray(),0, 0,240, 240,st7789.RGB565)# 显示 FPSfps = 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 推理结果
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
库
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 双缓冲机制(防撕裂)
# 创建两个缓冲区
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 背光控制(节能)
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
数组)
# 图标示例(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)
- 避免频繁全屏刷新
- 优先更新局部区域