1. TouchGFX 基础概念:从入门到理解核心
大家好,我是老张。做嵌入式 UI 有些年头了,从最早的裸机画点,到后来用 emWin、LVGL,再到 TouchGFX,一路踩坑无数。今天咱们聊聊 TouchGFX 的基础概念,这些东西搞明白了,后面做动画刷新才不会懵。
1.1 什么是 TouchGFX
TouchGFX 是一个专门为 STM32 微控制器打造的图形用户界面框架。说白了,它就是个帮你把漂亮界面跑在单片机上的工具包。
我记得 2018 年第一次接触 TouchGFX 时,心里还犯嘀咕:单片机跑这么炫的界面,能行吗?后来试了试,发现它确实有两把刷子。它不像传统方案那样需要外挂 SDRAM 和昂贵的图形控制器,直接在 STM32 内部就能跑出流畅的动画效果。
TouchGFX 的核心特点:
- 硬件加速:利用 STM32 的 Chrom-ART 图形加速器,减少 CPU 负担
- 低内存占用:通过帧缓冲压缩和局部刷新技术,把内存需求降到最低
- 所见即所得:TouchGFX Designer 拖拽式设计,UI 布局像画图一样简单
- 丰富的控件库:按钮、滑块、图表、键盘,开箱即用
一句话总结:TouchGFX 就是让嵌入式设备拥有智能手机级别 UI 体验的利器。
1.2 TouchGFX 的架构
咱们来看看 TouchGFX 内部是怎么组织的。我习惯把它分成三层,这样理解起来比较清晰。
你看,从上到下依次是:
- 应用层:你写的业务代码都在这里。比如按钮点击后做什么、数据怎么显示。MVP 模式也在这层实现。
- 框架层:TouchGFX 的核心库。控件怎么画、动画怎么算、文字怎么渲染,都是它的事。
- 硬件抽象层:连接硬件和框架的桥梁。LCD 怎么刷、触摸怎么读、帧缓冲怎么管理,都在这里。
我的经验:刚开始做 TouchGFX 项目时,我总喜欢在应用层里直接操作硬件。后来发现这样耦合太紧,换个屏就得改一堆代码。老老实实按三层架构来,后期维护省心多了。
1.3 MVP 模式介绍
MVP 是 TouchGFX 推荐的设计模式。Model-View-Presenter,说白了就是把界面显示和业务逻辑分开。
为什么会这样?你想想看,如果界面逻辑和数据逻辑混在一起,改个按钮颜色都可能影响数据读取,那调试起来多痛苦。
| 角色 | 职责 | 我踩过的坑 |
|---|---|---|
| Model | 数据模型,负责业务数据和逻辑 | 曾经把网络请求写在 View 里,结果界面卡死 |
| View | 界面显示,只负责画 UI 和接收用户输入 | View 里不要写任何数据处理代码 |
| Presenter | 中间人,协调 Model 和 View 的交互 | Presenter 太胖了也不好,要合理拆分 |
MVP 的工作流程是这样的:
- 用户点击按钮 → View 捕获事件 → 通知 Presenter
- Presenter 调用 Model 处理数据 → Model 返回结果
- Presenter 更新 View → View 刷新显示
注意:View 和 Model 绝对不能直接通信!所有交互必须通过 Presenter。我曾经为了省事,让 View 直接调 Model 的接口,结果后面加需求时改得想哭。
1.4 帧缓冲与刷新机制
帧缓冲是 TouchGFX 最核心的机制之一。简单说,它就是一块内存区域,用来存储要显示在屏幕上的像素数据。
TouchGFX 支持两种帧缓冲模式:
| 模式 | 内存占用 | 刷新方式 | 适用场景 |
|---|---|---|---|
| 单缓冲 | 1 个帧缓冲 | 绘制完成后整帧刷新 | 静态界面、低内存设备 |
| 双缓冲 | 2 个帧缓冲 | 后台绘制,前台显示 | 动画、视频播放 |
| 局部刷新 | 1 个帧缓冲 + 脏矩形 | 只刷新变化区域 | 大部分 UI 场景 |
嗯,这里要注意。双缓冲虽然流畅,但内存翻倍。对于 STM32 这种资源受限的芯片,局部刷新才是王道。
局部刷新的原理其实不复杂:
- TouchGFX 维护一个「脏矩形」列表,记录哪些区域发生了变化
- 每次刷新时,只把这些变化区域的数据发送到 LCD
- 没变化的区域保持原样,不浪费带宽
举个例子:你界面上有个数字时钟在走,只有数字区域在变化。用局部刷新,每次只更新那几十个像素,而不是整屏 480x272 个像素。效率提升可不是一星半点。
我记得有个项目,客户要求 60fps 的动画,但用的还是低端 STM32F4。当时我第一反应是「不可能」。后来用了局部刷新 + 脏矩形优化,硬是把帧率跑到了 55fps 以上。所以说,理解刷新机制真的很重要。
帧缓冲的配置通常在 TouchGFX HAL 层里设置:
// 帧缓冲配置示例
static_cast<STM32F4DMA::DMA_TypeDef*>(hal->getDMA())
->setFrameBufferFormat(Bitmap::RGB565);
// 启用局部刷新
hal->setFrameBufferRefreshStrategy(
FrameBufferRefreshStrategy::PARTIAL_REFRESH
);
避坑指南:配置帧缓冲格式时,一定要和 LCD 驱动匹配。RGB565 和 RGB888 混用,显示出来的颜色会完全不对。我曾经因为这个排查了整整两天,最后发现是格式没对齐。
好了,这一章的基础概念就聊到这里。TouchGFX 是什么、三层架构怎么搭、MVP 怎么用、帧缓冲怎么刷,这些搞清楚了,后面做动画刷新就有底气了。