一、TouchGFX 概述:从入门到精通的第一块基石
大家好,我是你们这门课的老朋友。做嵌入式 GUI 有些年头了,踩过的坑不少,攒下的经验也还行。今天咱们正式开始《TouchGFX 动画事件》的第一章——先把这个工具的身世、地位和本事聊透。
你可能会问:市面上做嵌入式界面的方案那么多,为什么偏偏要学 TouchGFX?嗯,这个问题我当年也问过自己。等我把它的来龙去脉讲清楚,你自然就明白了。
1.1 什么是 TouchGFX?
TouchGFX,说白了,是一个专门给嵌入式设备做图形用户界面的软件框架。它跑在微控制器上,帮你在小屏幕、低资源的环境里,做出媲美智能手机的流畅动画和触控交互。
我习惯把它理解成「嵌入式界的 Qt」。但跟 Qt 不一样的是,TouchGFX 是为资源受限的硬件量身定做的——你的 MCU 可能只有几百 KB 的 RAM,几 MB 的 Flash,它照样能跑出 60 帧的动画。
核心定义:TouchGFX 是一个基于 C++ 的、硬件加速的嵌入式 GUI 框架,由瑞典公司 TouchGFX 开发,2018 年被 STMicroelectronics 收购。它深度适配 STM32 系列 MCU,但也支持其他厂商的硬件。
我记得第一次接触 TouchGFX 是在一个智能家居项目上。客户要求界面必须「跟手机一样顺滑」,但手里的芯片只是 STM32F4,主频 168MHz,RAM 才 192KB。当时我试过 uGUI、emWin,效果都不理想。直到同事推荐了 TouchGFX——说实话,第一次看到它的演示 demo,我愣了半天:这真的是跑在 MCU 上的?
1.2 TouchGFX 在嵌入式 GUI 中的地位
咱们先看看嵌入式 GUI 的江湖格局。我按自己的经验,把主流方案分成了三类:
| 方案类型 | 代表产品 | 特点 | 适合场景 |
|---|---|---|---|
| 轻量级裸奔 | LVGL、uGUI | 代码量小、无硬件加速、动画能力弱 | 低端 MCU、简单界面 |
| 商业级框架 | TouchGFX、emWin、Embedded Wizard | 硬件加速、丰富控件、动画引擎 | 中高端 MCU、复杂交互 |
| 高端 SoC 方案 | Qt for MCU、Android Things | 功能强大、资源需求高 | 高性能 SoC、Linux 环境 |
TouchGFX 的位置,恰好卡在「商业级框架」这个档位里。但它有一个其他对手很难追的优势——与 STM32 的深度绑定。
为什么会这样?因为 TouchGFX 被 ST 收购后,直接打通了 STM32 的硬件加速单元(LTDC、DMA2D、Chrom-ART)。别的框架要自己写驱动去调这些外设,TouchGFX 是原生支持,开箱即用。你想想看,这省了多少底层调试的功夫。
我在一个医疗设备项目里做过对比:同样的 STM32H743 芯片,跑同样的动画效果,TouchGFX 的帧率比某竞品高了将近 40%。原因很简单——它把 DMA2D 用到了极致,像素搬运和混合几乎不占 CPU 时间。
个人建议:如果你的项目用的是 STM32 系列,尤其是带 TFT 控制器或 DMA2D 的型号,TouchGFX 基本是首选。不是因为它完美,而是因为它最省心。
1.3 TouchGFX 的核心特性与优势
下面我挑几个最实在的特性,结合项目经验跟你聊聊。
1.3.1 硬件加速渲染
TouchGFX 的渲染管线是分层的。它把界面拆成多个「画布层」,每一层独立更新,最后通过硬件混合器合成。这样做的好处是:你只需要重绘变化的那一层,其他层不动。
举个例子:一个仪表盘界面,指针在转,背景和刻度不变。传统做法是整个屏幕重绘,TouchGFX 只重绘指针那一层。配合 DMA2D 的 2.5D 加速,性能差距非常明显。
// TouchGFX 中典型的层配置示例
// 在 HAL 初始化时设置
hal->setFrameBufferStartAddress(frameBuffer, 0);
hal->setFrameBufferStartAddress(frameBuffer1, 1);
hal->setFrameBufferStartAddress(frameBuffer2, 2);
// 启用 DMA2D 加速
hal->setDMAAutoReload(true);
hal->setDMABurstLength(DMA2D_BURST_LENGTH_16);
1.3.2 强大的动画引擎
这是咱们这门课的核心。TouchGFX 内置了一套完整的动画系统,支持缓动函数、关键帧、并行动画、串行动画链。你不需要自己写定时器中断,也不需要手动计算插值。
我记得在做一个智能门锁项目时,需要实现「指纹验证成功 → 图标放大 → 绿色对勾弹出 → 门锁旋转」这一串动画。用 TouchGFX 的 AnimationManager,大概 50 行代码就搞定了。如果用裸机自己写,光状态机就得折腾好几天。
动画引擎核心能力:
- 支持 30+ 种缓动曲线(EaseIn、EaseOut、Bounce、Elastic 等)
- 可对任意属性做动画(位置、大小、颜色、透明度、旋转角度)
- 动画回调机制:开始、更新、结束三个阶段都有回调
- 支持动画组:多个动画可以并行或串行执行
1.3.3 所见即所得的 UI 设计器
TouchGFX Designer 是一个桌面工具,你可以在上面拖拽控件、设置属性、预览动画效果。生成的代码直接导入到你的 IDE 里编译。
我个人的习惯是:先在 Designer 里把界面布局和动画逻辑搭好,然后导出代码,再在 IDE 里做业务逻辑的对接。这样分工明确,调试效率高很多。
避坑指南:我曾经犯过一个错误——在 Designer 里把动画参数调得特别花哨,结果导出后发现 MCU 跑不动。后来学乖了:先在目标硬件上跑一下性能测试,再决定动画的复杂程度。TouchGFX 自带的帧率监控工具很好用,记得打开。
1.3.4 低内存占用
TouchGFX 的内存管理很讲究。它支持多种帧缓冲策略:单缓冲、双缓冲、局部缓冲。对于 RAM 紧张的芯片,可以用局部缓冲 + DMA2D 的方式,只缓存变化区域,大幅降低内存需求。
| 缓冲策略 | 内存占用(以 480x272 16位色为例) | 适用场景 |
|---|---|---|
| 单缓冲 | 约 260 KB | RAM 充足,简单界面 |
| 双缓冲 | 约 520 KB | 需要流畅动画,RAM 够用 |
| 局部缓冲 | 可低至 32 KB | RAM 紧张,静态界面为主 |
我在一个电池供电的便携设备上,用局部缓冲策略,把帧缓冲从 260KB 压到了 48KB,动画效果依然能保持在 30 帧以上。这个优化空间,是其他框架很难给的。
1.3.5 丰富的控件库与自定义能力
TouchGFX 内置了按钮、滑块、进度条、图表、键盘、容器等 40 多种控件。更关键的是,你可以通过继承和组合,做出完全自定义的控件。
举个例子:我需要一个「圆形进度环」,标准控件库里没有。我直接继承了 Circle 类,重写了 draw() 方法,加上动画属性绑定,两天就搞定了。如果从零开始写,光底层绘制就得一周。
// 自定义圆形进度环的简化示例
class CircularProgress : public Circle {
public:
CircularProgress() {
setRadius(50);
setLineWidth(8);
setArc(0, 360); // 默认整圆
}
void setProgress(uint8_t progress) {
// progress: 0-100
uint16_t endAngle = (uint16_t)(progress * 360 / 100);
setArc(0, endAngle);
invalidate(); // 触发重绘
}
};
1.4 TouchGFX 的知识体系全景
为了让你对这门课有个整体印象,我画了一张结构图。它把 TouchGFX 的核心模块和咱们 30 章的内容串联起来了。
从这张图你能看到,咱们这门课会从最底层的硬件抽象层讲起,一路往上走到应用层。动画和事件引擎是中间最核心的一层——它连接了 UI 控件和底层渲染,也是你做出流畅交互的关键。
1.5 为什么选择 TouchGFX 做动画?
最后我想说点实在的。嵌入式 GUI 的动画,跟 Web 或移动端不一样。你的 CPU 主频可能只有几百 MHz,RAM 按 KB 算,Flash 按 MB 算。在这种环境下做动画,每一帧都要精打细算。
TouchGFX 的优势在于:它把「性能优化」这件事,从开发者手里接过去了一大半。你只需要关注动画的逻辑和效果,底层怎么搬运像素、怎么混合图层、怎么利用硬件加速,框架帮你搞定了。
我见过不少团队,自己写动画引擎,最后要么帧率上不去,要么内存爆了,要么动画卡顿。换到 TouchGFX 之后,这些问题基本没再出现过。当然,它也不是万能的——后面我会专门讲它的局限性和应对方案。
给新手的建议:如果你刚开始学 TouchGFX,别急着写代码。先把 Designer 玩熟,拖几个控件,加几个动画,看看生成的代码长什么样。等你对「框架能做什么」有了感觉,再深入底层细节。这样学起来事半功倍。