1. 课程导入

大家好,我是老张。做嵌入式 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 内部是怎么组织的。我习惯把它分成三层,这样理解起来比较清晰。

TouchGFX 三层架构 应用层(Application Layer) 用户界面、业务逻辑、屏幕管理 Model / View / Presenter 框架层(Framework Layer) 控件库、事件处理、动画引擎、字体渲染 Drawable / Container / Widget 硬件抽象层(HAL Layer) LCD 驱动、触摸驱动、帧缓冲管理 OSAL / DMA2D / LTDC

你看,从上到下依次是:

  1. 应用层:你写的业务代码都在这里。比如按钮点击后做什么、数据怎么显示。MVP 模式也在这层实现。
  2. 框架层:TouchGFX 的核心库。控件怎么画、动画怎么算、文字怎么渲染,都是它的事。
  3. 硬件抽象层:连接硬件和框架的桥梁。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 这种资源受限的芯片,局部刷新才是王道。

局部刷新的原理其实不复杂:

  1. TouchGFX 维护一个「脏矩形」列表,记录哪些区域发生了变化
  2. 每次刷新时,只把这些变化区域的数据发送到 LCD
  3. 没变化的区域保持原样,不浪费带宽

举个例子:你界面上有个数字时钟在走,只有数字区域在变化。用局部刷新,每次只更新那几十个像素,而不是整屏 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 怎么用、帧缓冲怎么刷,这些搞清楚了,后面做动画刷新就有底气了。