- 操作系统
- 嵌入式
- 物联网
- 嵌入式OS
- RTOS
【免费下载链接】rt-thread
RT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/
本篇技术指南聚焦 RT-Thread 开源仓库中bsp/gd32/arm/gd32470z-lckfbBSP 的板级扩展模块 —— 立创·梁山派开发板配套 RGB LCD 屏幕驱动(board/ports目录)。该驱动由 LCKFB 开发、godmial 移植并重构为符合 RT-Thread 编码规范的代码,覆盖了 GD32F470 的 TLI 显示控制器、SDRAM 帧缓冲、GPU(IPA) 外设、FT5206 电容触摸以及一个可直接运行的"画板"示例。读完本文,你将掌握如何在 ENV 中一键开启该 LCD 驱动、理解其 TLI 时序与层配置、SDRAM 帧缓冲布局、触摸芯片的软件 I2C 通信原理,并学会排查刷新抖动、触摸连点等常见问题。
1. 驱动概述与文件构成
在 board/ports 目录下,本驱动由以下文件组成:
| 文件 | 职责 |
|---|---|
| drv_lcd.c | TLI 显示控制器初始化、显示时序/层配置,以及点、线、矩形、圆、三角形、字符、图片等绘制 API |
| drv_lcd.h | LCD 分辨率、时序参数、帧缓冲地址、颜色宏定义与编译器兼容声明 |
| drv_touch.c | FT5206 电容触摸芯片驱动:软件 I2C 时序、寄存器读写、扫描与自测命令 |
| drv_touch.h | 触摸引脚宏、I2C 命令/寄存器地址、触摸点数据结构_m_tp_dev |
| draw_panel.c | "画板"示例:实现清屏/选色/笔刷大小/橡皮擦四个按钮与触摸绘画交互 |
| font.h | ASCII 字符点阵字库(16x8),供字符串显示使用 |
| SConscript | 按宏开关将上述源文件按条件加入编译 |
其中SConscript清晰地体现了各功能模块的编译依赖关系:
if GetDepend('BSP_USING_LCD'): src += ['drv_lcd.c'] if GetDepend('BSP_USING_TOUCH'): src += ['drv_touch.c'] if GetDepend('BSP_USING_DRAW_PANEL_EXAMPLE'): src += ['draw_panel.c']也就是说,drv_lcd.c是否参与编译取决于BSP_USING_LCD,触摸与画板示例分别受BSP_USING_TOUCH与BSP_USING_DRAW_PANEL_EXAMPLE控制,与下文 ENV 菜单一一对应。
2. 在 ENV 中开启 LCD 驱动
进入bsp/gd32/arm/gd32470z-lckfb目录,在终端打开 ENV 工具并执行menuconfig,按如下路径配置(原文档建议全部开启):
Hardware Drivers Config ---> Board extended module Drivers ---> Enable LCD ---> - [*]Enable TLI - [*]Enable SDRAM - [*]Enable TOUCH - [*]Enable GPU - [*]Enable DRAW PANEL EXAMPLE对应的 Kconfig 实现位于 board/Kconfig 的menu "Board extended module Drivers"段中,各选项作用如下:
| 菜单项 | Kconfig 宏 | 默认值 | 作用 |
|---|---|---|---|
| Enable LCD | BSP_USING_LCD | n | 总开关,同时select RT_USING_LCD,不开启则本目录驱动完全不参与编译 |
| Enable TLI | BSP_USING_TLI | y | 开启 TLI 显示控制器初始化与绘制代码 |
| Enable SDRAM | BSP_USING_SDRAM | y | 开启外部 SDRAM(帧缓冲存放地),select RT_USING_SDRAM |
| Enable TOUCH | BSP_USING_TOUCH | n | 开启 FT5206 触摸驱动,select RT_USING_TOUCH |
| Enable GPU | BSP_USING_GPU | y | 开启 IPA(图像处理加速器)时钟与中断使能,select RT_USING_GPU |
| Enable DRAW PANEL EXAMPLE | BSP_USING_DRAW_PANEL_EXAMPLE | n | 开启画板示例程序,select RT_USING_DRAW_PANEL_EXAMPLE |
提示:
Enable LCD总开关下,TLI、SDRAM、GPU 默认即开启,触摸与画板示例默认关闭,需要手动勾选。配置完成后保存退出,在 BSP 根目录重新执行scons即可编译。
3. 硬件平台与帧缓冲布局
3.1 板级资源背景
依据 gd32470z-lckfb/README.md,梁山派开发板搭载GD32F470ZGT6(ARM Cortex-M4,主频最高 240MHz,1024KB FLASH / 512KB RAM),板载W9825G6KH-6I SDRAM与 RGB/MCU 双接口 TFT-LCD,支持 RGB 屏幕直接点亮。
SDRAM 的地址范围定义在 board/board.h 中:
#define EXT_SDRAM_BEGIN (0xC0000000U) /* the begining address of external SDRAM */ #define EXT_SDRAM_END (EXT_SDRAM_BEGIN + (32U * 1024 * 1024)) /* 32MB 结束地址 */而 LCD 帧缓冲首地址在 drv_lcd.h 中定义为LCD_FRAME_BUF_ADDR 0xC0000000,即 SDRAM 起始地址 —— 显存直接落在外部 SDRAM 中,避免占用宝贵的片内 SRAM。
3.2 显示规格与颜色定义
驱动面向一块800x480的 RGB 接口屏幕,像素格式为RGB565(每像素 2 字节)。drv_lcd.h中给出了完整的时序与帧缓冲参数:
#define LCD_WIDTH 800 #define LCD_HEIGHT 480 /* 水平同步 */ #define HORIZONTAL_SYNCHRONOUS_PULSE 10 #define HORIZONTAL_BACK_PORCH 150 #define ACTIVE_WIDTH 800 #define HORIZONTAL_FRONT_PORCH 15 /* 垂直同步 */ #define VERTICAL_SYNCHRONOUS_PULSE 10 #define VERTICAL_BACK_PORCH 140 #define ACTIVE_HEIGHT 480 #define VERTICAL_FRONT_PORCH 40 /* 帧缓冲地址 */ #define LCD_FRAME_BUF_ADDR 0xC0000000同时预定义了丰富的 RGB565 颜色宏(WHITE、BLACK、BLUE、RED、GREEN、YELLOW、CYAN、MAGENTA、BROWN、GRAY以及 GUI 用的LIGHTBLUE、LGRAY、GRAYBLUE等),可直接用于后续绘制 API。
3.3 帧缓冲的编译器适配
由于代码格式审查原因,帧缓冲的声明针对不同编译器做了分支处理(见drv_lcd.c与drv_lcd.h):
#if defined(__CC_ARM) || defined(__ARMCC_VERSION) /* Keil MDK Compiler:将帧缓冲绝对定位到 SDRAM 地址 */ uint16_t ltdc_lcd_framebuf0[800][480] __attribute__((at(LCD_FRAME_BUF_ADDR))); #elif defined(__GNUC__) /* GCC (RT-Thread scons):仅为避免编译错误而定义的小占位数组 */ uint16_t ltdc_lcd_framebuf0[10][10]; #endif这是避免scons编译不通过的关键代码段:Keil MDK 下通过__attribute__((at(...)))把 800x480 的帧缓冲精确安放到 SDRAM 起始地址;而 GCC(RT-Thread scons 默认工具链)下由于链接脚本未预留 SDRAM 段,直接声明大数组会导致链接失败,因此仅定义一个[10][10]的占位数组保证编译通过,实际帧缓冲地址在tli_config()中通过tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)ltdc_lcd_framebuf0;交由 TLI 控制器使用(GCC 场景下实际显存位置需结合链接脚本确认,这是移植者明确标注的取舍)。
4. 显示初始化流程:TLI + IPA 源码级解析
入口函数为lcd_disp_config()(声明于 drv_lcd.h,实现在 drv_lcd.c),它按以下顺序完成显示系统初始化:
lcd_disp_en_config() -> 配置 DISP 使能引脚(GPIOD PIN13,推挽输出) lcd_disp_off() -> 先拉低 DISP(关屏) tli_gpio_config() -> 配置 TLI 全部 RGB/同步信号引脚为 AF 复用模式 lcd_disp_on() -> 拉高 DISP(开屏/背光) tli_config() -> 配置 PLLSAI 时钟、TLI 时序、Layer0 与帧缓冲 tli_layer_enable(LAYER0) -> 使能 Layer0 tli_reload_config(TLI_FRAME_BLANK_RELOAD_EN) -> 帧消隐期重载配置 tli_enable() -> 开启 TLI 控制器 ipa_config() -> 使能 IPA 时钟并注册中断4.1 TLI 显示时序配置
tli_config()中,TLI 的像素时钟由 PLLSAI 分频产生:
if (ERROR == rcu_pllsai_config(192, 2, 3)) /* 配置 PLLSAI 产生 TLI 时钟 */ while (1); rcu_tli_clock_div_config(RCU_PLLSAIR_DIV2); /* PLLSAIR 再二分频 */ rcu_osci_on(RCU_PLLSAI_CK); /* 开启 PLLSAI 时钟源 */ rcu_osci_stab_wait(RCU_PLLSAI_CK); /* 等待稳定 */随后填充tli_parameter_struct,将drv_lcd.h中的同步脉冲、前后肩、有效区域宏换算为 TLI 寄存器要求的"各段长度 - 1"形式:
| 时序参数 | 赋值 | 说明 |
|---|---|---|
synpsz_hpsz / vpsz | HORIZONTAL_SYNCHRONOUS_PULSE - 1(10-1) | HSYNC/VSYNC 同步脉冲宽度 |
backpsz_hbpsz / vbpsz | 同步脉冲 + 后肩 - 1 | 水平/垂直后肩 |
activesz_hasz / vasz | 同步脉冲 + 后肩 + 有效宽度 - 1 | 有效显示区终点 |
totalsz_htsz / vtsz | 同步脉冲 + 后肩 + 有效 + 前肩 - 1 | 整行/整帧总长 |
信号极性配置为TLI_HSYN_ACTLIVE_LOW、TLI_VSYN_ACTLIVE_LOW、TLI_DE_ACTLIVE_LOW、TLI_PIXEL_CLOCK_TLI,背景色设为白色(R/G/B 均为 0xFF)。
4.2 Layer0 层配置与帧缓冲
屏幕内容通过 Layer0 输出,关键配置如下:
layer_window_leftpos = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH; /* 窗口左边界 */ layer_window_rightpos = ACTIVE_WIDTH + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1; layer_ppf = LAYER_PPF_RGB565; /* 像素格式 RGB565 */ layer_sa = 255; /* 指定 alpha 全不透明 */ layer_acf1 / layer_acf2 = LAYER_ACF1_SA / LAYER_ACF2_SA; /* 混合因子使用 alpha */ layer_frame_bufaddr = (uint32_t)ltdc_lcd_framebuf0; /* 帧缓冲基地址 */ layer_frame_line_length = (ACTIVE_WIDTH * 2) + 3; /* 每行字节数(含对齐) */ layer_frame_buf_stride_offset = ACTIVE_WIDTH * 2; /* 行跨度 1600 字节 */ layer_frame_total_line_number = ACTIVE_HEIGHT; /* 总行数 480 */最后调用tli_dither_config(TLI_DITHER_ENABLE)开启抖动(dithering)以改善低位数色彩时的显示质量。
4.3 GPIO 与 IPA
tli_gpio_config():使能 GPIOA/B/C/D/F/G 时钟,将 HSYNC(PC6)、VSYNC(PA4)、PCLK(PG7)、DE(PF10) 以及 RGB 数据线(R7 在 PG6、R3 在 PB0、G7 在 PD3、G2 在 PA6、B7 在 PB9、B4 在 PG12 等 15 位色深线)逐一gpio_af_set为 AF14/AF9 复用,并配置为推挽、50MHz 输出。注意其中 R3 使用 AF9,其余大多数使用 AF14。ipa_config():rcu_periph_clock_enable(RCU_IPA)打开 IPA 外设时钟,nvic_irq_enable(IPA_IRQn, 0, 2)使能其中断。IPA 即 GD32F4 的图形加速单元(GPU),后续可在绘制中大显身手。
5. 软件绘制 API 一览
drv_lcd.c提供了一套直接操作帧缓冲的软件绘制函数,全部基于最底层的tli_draw_point()(向ltdc_lcd_framebuf0[0] + LCD_WIDTH * y + x写入 RGB565 颜色值):
| 函数 | 功能 | 算法/说明 |
|---|---|---|
tli_draw_point(x, y, color) | 单点绘制 | 直接写帧缓冲 |
tli_draw_line(...) | 直线 | Bresenham 画线算法 |
tli_draw_rectangle(...) | 矩形(可填充) | fill=1 填充,否则四条边线 |
tli_draw_circle(xc, yc, c, r, fill) | 圆/圆盘 | 中点圆算法,fill 时逐行填充 |
tli_draw_triangle(...) | 三角形(可填充) | 扫描线光栅化,内部用_swap排序顶点 |
tli_point_enlarge(x, y, color, magnify) | 放大点 | 用 4 个矩形画十字块,即"笔刷" |
tli_show_char(...) | 单个 ASCII 字符 | 基于asc2_160816x8 点阵,支持放大与叠加 |
tli_show_string(...) | 字符串 | 逐字符绘制并自动处理边界(仅 ' '~'~' 可见字符) |
tli_show_picture(x, y, w, h, pic) | 图片 | 输入 RGB565 双字节数组 |
tli_show_button(...) | 圆角按钮 | 四角画圆 + 四条边线 + 矩形填充组合 |
tli_show_switch(...) | 开关控件 | 圆角底座 + 圆形滑块,根据 sw 切换 on/off 颜色 |
注意:由于代码格式审查原因,本驱动未包含中文显示函数,但可直接移植官方源码中的中文显示函数(字库与tli_show_char兼容)使用。
6. 触摸驱动:FT5206 软件 I2C 全解析
6.1 引脚与寄存器
触摸部分基于FT5206 电容触摸芯片,通过 GPIO 软件模拟 I2C 与芯片通信。引脚定义见 drv_touch.h:
| 信号 | 引脚 | 说明 |
|---|---|---|
| SCL | PB6 | 时钟,上拉推挽输出 |
| SDA | PB7 | 数据,输入/输出切换,上拉 |
| RST | PD12 | 复位引脚 |
| INT | PD11 | 触摸中断输入 |
关键 I2C 命令与寄存器定义:
#define FT_CMD_WR 0x70 /* 写命令 */ #define FT_CMD_RD 0x71 /* 读命令 */ #define FT_DEVIDE_MODE 0x00 /* 模式控制 */ #define FT_REG_NUM_FINGER 0x02 /* 触摸点数状态 */ #define FT_TP1_REG ... FT_TP5_REG /* 0x03/0x09/0x0F/0x15/0x1B 五个触摸点数据 */ #define FT_ID_G_LIB_VERSION 0xA1 /* 固件版本 */ #define FT_ID_G_MODE 0xA4 /* 中断模式 */ #define FT_ID_G_THGROUP 0x80 /* 触摸灵敏度阈值 */ #define FT_ID_G_PERIODACTIVE 0x88 /* 采样激活周期 */ #define TP_PRES_DOWN 0x80 /* 按下标志 */ #define TP_CATH_PRES 0x40 /* 触点按下标志 */ #define CT_MAX_TOUCH 5 /* 最多 5 点触摸 */6.2 软件 I2C 时序
drv_touch.c用 GPIO 位操作完整实现了标准 I2C 时序:CT_IIC_Start/Stop(起始/停止条件)、CT_IIC_Send_Byte/Read_Byte(字节收发)、CT_IIC_Wait_Ack/Ack/NAck(应答管理),并通过delay_us(基于 SysTick 轮询的微秒延时)与CT_Delay控制 I2C 速率。其中:
- 每字节高位先行(MSB first);
- 等待 ACK 以 250 次为超时上限,超时自动产生 Stop 条件返回失败;
- 读字节时最后一字节发 NACK 表示读结束。
6.3 初始化与扫描
FT5206_Init()完成:配置 INT 引脚为输入 →CT_IIC_Init()初始化 I2C 引脚 → 写入设备模式、中断模式、灵敏度阈值22、激活周期12→ 读取并打印芯片固件版本(CTP ID:xxxx)。
FT5206_Scan(mode)采用轮询方式:每 10 次调用读取一次FT_REG_NUM_FINGER,若检测到 1~5 个触点(g_gt_tnum = 5),则依次读取FT_TPx_REG的 4 字节原始坐标,根据tp_dev.touchtype交换 X/Y 得到像素坐标,写入全局触摸结构体tp_dev。还包含越界保护(坐标超过 800/480 时回退到上一有效点)与松手判定(无触点时清除按下标志)。相关数据结构:
typedef struct { uint16_t x[CT_MAX_TOUCH]; /* 触点 X 坐标 */ uint16_t y[CT_MAX_TOUCH]; /* 触点 Y 坐标 */ uint8_t sta; /* 触摸状态标志 */ float xfac, yfac; /* 坐标缩放系数(预留校准用) */ short xoff, yoff; /* 坐标偏移 */ uint8_t touchtype; /* 触摸类型(坐标交换标志) */ } _m_tp_dev;该结构体全局实例为tp_dev,应用层通过tp_dev.x[0] / tp_dev.y[0]读取主触点坐标。此外还提供letgo_scan(contact, sx, sy, ex, ey)阻塞等待手指离开指定矩形区域,用于按钮的"按下-抬起"语义。
6.4 触摸自测命令
touch_test通过MSH_CMD_EXPORT注册为 MSH shell 命令。在 FinSH 终端输入touch_test即可进入循环测试:FT5206_Scan检测到触摸时打印touch。该函数内部为while(1)死循环,仅用于手动验证触摸功能,测试完成后需复位开发板退出。
7. 画板示例:触摸 + 绘制的完整应用
draw_panel.c演示了如何把上述显示与触摸能力组合成一个可交互应用。draw_panel_test通过INIT_COMPONENT_EXPORT在系统组件初始化阶段自动运行(无需在 MSH 手动执行):
界面布局(800x480 屏幕底部一排按钮,圆角半径 12):
| 按钮 | 位置 (x, y, w, h) | 功能 |
|---|---|---|
| color | (10, 400, 120, 70) | 循环切换 14 种颜色(color_buf[]) |
| pixel | (340, 400, 120, 70) | 笔刷放大倍数 1~20(PIXEL_SIZE_MAX),数字实时显示 |
| eraser | (540, 400, 120, 70) | 切换橡皮擦模式(黑底/蓝底区分状态) |
| clear | (670, 400, 120, 70) | 清屏为白色 |
交互流程:
lcd_disp_config(); /* 初始化显示 */ FT5206_Init(); /* 初始化触摸 */ tli_draw_rectangle(0, 0, 800, 480, WHITE, 1); /* 白底清屏 */ ui_init(); /* 绘制四个按钮 */ while (1) { touch_state = FT5206_Scan(0); /* 轮询触摸 */ if (touch_state == 1) { /* 命中按钮区域则执行对应操作(letgo_scan 等待松手) */ /* 否则用 tli_point_enlarge 以当前颜色+笔刷大小落笔, 橡皮擦模式下以 WHITE 覆盖实现擦除 */ } }主循环中的绘制核心是tli_point_enlarge(tp_dev.x[0], tp_dev.y[0], color_buf[color_num], button_pixel.value)—— 手指在画布上滑动时,以放大笔刷实时写帧缓冲,即可实现绘画效果。这一示例既是 LCD+触摸驱动的自检工具,也可作为自定义 UI 的基础框架。
8. 注意事项与常见问题排查
- 屏幕刷新抖动、触摸连点:原文档指出可尝试将 system_gd32f4xx.c 中的系统时钟值修改为
#define __SYSTEM_CLOCK_240M_PLL_25M_HXTAL (uint32_t)(240000000),使系统主频稳定在 240MHz(梁山派 GD32F470ZGT6 最高主频即 240MHz),随后重新编译。时序不稳会直接影响 TLI 刷新与 FT5206 采样,这是排查该类现象的首选手段。 - 中文显示:由于代码格式审查原因,本驱动未包含中文显示函数。可直接移植官方源码中的中文显示函数配合本驱动的 ASCII 点阵框架使用。
- 编译器兼容:为避免
scons编译不通过,帧缓冲采用__CC_ARM/__ARMCC_VERSION(Keil)与__GNUC__(RT-Thread scons)分支声明,详见第 3.3 节。修改该段时务必保持两个分支同时更新。 - 触摸自测:
touch_test为死循环,仅供调试;draw_panel_test由系统组件初始化自动启动,若不需要画板功能,在 ENV 中关闭Enable DRAW PANEL EXAMPLE即可。 - 触摸开关:
BSP_USING_TOUCH默认关闭,需要触摸功能时请务必在 ENV 中手动勾选,否则FT5206_Init、tp_dev等相关符号不可用。
9. 进一步阅读
- BSP 整体说明与硬件资源表:gd32470z-lckfb/README.md
- 菜单配置实现:board/Kconfig
- 板级地址定义(SDRAM 基址):board/board.h
- LCD 驱动源码:drv_lcd.c / drv_lcd.h
- 触摸驱动源码:drv_touch.c / drv_touch.h
- 画板示例:draw_panel.c
- 编译依赖控制:SConscript
- 操作系统
- 嵌入式
- 物联网
- 嵌入式OS
- RTOS
【免费下载链接】rt-thread
RT-Thread is an open source IoT Real-Time Operating System (RTOS). https://rt-thread.github.io/rt-thread/
相关推荐
RT-Thread 下 GD32F470 立创开发板 RGB LCD 触摸驱动实践:TLI 显示、SDRAM 帧缓冲与 FT5206 电容触摸全解析
RT Thread 下 GD32F470 立创开发板 RGB LCD 触摸驱动实践:TLI 显示、SDRAM 帧缓冲与 FT5206 电容触摸全解析 导读 本指
操作系统嵌入式物联网嵌入式OSRTOSRT-Thread GD32470Z-LCKFB 梁山派 BSP 开发指南:从快速上手到 RGB LCD 触摸屏扩展
RT Thread GD32470Z LCKFB 梁山派 BSP 开发指南:从快速上手到 RGB LCD 触摸屏扩展 本指南以 RT Thread 仓库中的 g
操作系统嵌入式物联网嵌入式OSRTOSMicroPython pyboard LCD 触摸屏扩展板(LCD Touch-Sensor Skin)实战指南:焊接、显示驱动与 MPR121 触摸读取
MicroPython pyboard LCD 触摸屏扩展板(LCD Touch Sensor Skin)实战指南:焊接、显示驱动与 MPR121 触摸读取 导
嵌入式语言运行时编程语言解释器编译器物联网系统编程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考