2. TouchGFX基础回顾
在进入量产部署与调试之前,有必要把 TouchGFX 的运行时骨架重新梳理一遍。很多现场问题——画面撕裂、触摸无响应、内存不足、动画卡顿——追根溯源并不是驱动或硬件故障,而是对框架的分层职责、MVP 数据流向和事件分发路径理解不到位。本节从架构、模式、控件、事件四个维度建立一张"全局地图",为后续的部署与排障提供判断依据。
一、架构组成:三层协作的运行时结构
TouchGFX 在 MCU 上运行时可以划分为三个协作层:硬件抽象层、框架核心层和应用层。硬件抽象层负责把 LCD 控制器、DMA2D/GPU2D、触摸控制器、外部 SDRAM/Flash 等外设封装成统一接口,典型实现是 TouchGFXHAL 与 TouchGFXGeneratedHAL;框架核心层包含渲染引擎、Drawable 树、Screen/Presenter/View 基类、Model 基类以及 TouchGFXEngine 主循环;应用层则是开发者用 Designer 生成的界面代码与手写的业务逻辑。
渲染路径上,框架采用"脏矩形 + 双缓冲"策略:只有发生变化的区域才被重绘,绘制结果写入帧缓冲,再由 LTDC 或 SPI/RGB 接口扫描输出。理解这条路径,就能解释为什么"局部刷新比全屏刷新省 CPU",也能解释为什么帧缓冲数量与 SDRAM 带宽直接决定能否跑满 60 FPS。
二、MVP 模式:把界面与业务解耦
TouchGFX 采用 MVP(Model-View-Presenter)而非 MVC,核心目的是让 View 只关心"怎么画",Model 只关心"数据是什么",Presenter 负责"什么时候做什么"。三者通过生成代码中的 setModel()、bind() 和回调函数连接。
典型的数据流是:用户在 View 上点击按钮 → View 调用 Presenter 的槽函数 → Presenter 调用 Model 的接口 → Model 更新数据并触发回调 → Presenter 收到回调后调用 view.updateXxx() → View 刷新控件。这条链路是单向的,任何"View 直接改 Model"或"Model 直接操作控件"的写法都会破坏可测试性,也是量产阶段最难排查的一类耦合缺陷。
// Presenter 中典型的交互转发
void Screen1Presenter::onButtonClicked()
{
model->incrementCounter(); // 交给 Model 处理业务
}
// Model 数据变化后回调 Presenter
void Screen1Presenter::counterUpdated(int value)
{
view.setCounterText(value); // 由 View 负责显示
}
三、控件体系:从基础到复合
TouchGFX 的控件以 Drawable 为根,按能力可分为四类:基础绘制类(Box、TextArea、Image)、交互类(Button、ToggleButton、Slider、FlexButton)、容器类(Container、ScrollableContainer、ModalWindow)和动态效果类(AnimatedImage、TextureMapper、MoveAnimator)。Designer 中拖拽出的每个控件最终都会生成对应的 C++ 成员变量,命名规则为 控件类型 + 序号,例如 button1、textArea2。
| 控件类别 | 代表控件 | 典型用途 | 量产关注点 |
|---|---|---|---|
| 基础绘制 | Box / TextArea / Image | 背景、文字、图标 | 位图格式与 Flash 占用 |
| 交互 | Button / Slider / FlexButton | 点击、拖动、状态切换 | 触摸采样率与去抖 |
| 容器 | Container / ScrollableContainer | 页面分区、列表滚动 | 嵌套层级与重绘范围 |
| 动态效果 | AnimatedImage / TextureMapper | 动画、3D 变换 | 帧率与 SDRAM 带宽 |
四、事件机制:从触摸采样到回调
事件机制的入口是 HAL 的触摸采样。框架在每个 tick 中读取触摸坐标,生成 ClickEvent、DragEvent、GestureEvent 等对象,然后沿 Drawable 树自顶向下做命中测试。命中后事件被投递给对应控件的 handleClickEvent(),控件再通过回调触发 Presenter 逻辑。
setTouchable(false) 被误设,就会出现"看得见却点不动"的现象,这是量产调试中最高频的触摸类问题。五、适用场景与常见误区
TouchGFX 适合中高分辨率、需要流畅动画与复杂交互的 HMI 场景,例如工业面板、家电触控屏、医疗设备界面。对于仅需显示少量文字与图标的极简界面,裸机 + 简单绘图库往往更省资源。
invalidate() 的调用时机,造成画面不刷新或过度刷新。量产前应通过代码审查逐项排除。