1、TouchGFX动画基础:帧率(FPS)概念、刷新机制、VSync同步原理
各位做嵌入式UI的同行,咱们今天聊聊动画性能最底层的那些事。说实话,我见过太多项目,UI效果图做得漂漂亮亮,一上真机就卡成PPT。问题出在哪?多半是对帧率、刷新机制这些基础概念没吃透。
我自己刚接触TouchGFX那会儿,也踩过类似的坑。总觉得不就是让画面动起来嘛,结果一深入才发现,这里面的门道比想象中多得多。好,咱们正式开始。
1.1 帧率(FPS)到底是什么?
帧率,全称Frames Per Second,每秒传输的帧数。说白了,就是一秒钟内屏幕能刷新多少张画面。
你想想看,电影是24FPS,电视是30FPS,咱们做嵌入式UI,目标通常是60FPS。为什么是60?因为人眼的视觉暂留效应,60FPS已经能提供非常流畅的视觉体验了。
关键认知:帧率不是越高越好。60FPS和120FPS在人眼感知上差异极小,但CPU/GPU的负载却翻倍。我个人的习惯是,先稳定60FPS,再考虑优化功耗。
在TouchGFX里,帧率计算其实很简单:
// 伪代码:帧率计算逻辑
uint32_t fps = 0;
uint32_t lastTick = HAL_GetTick();
uint32_t frameCount = 0;
void onFrame() {
frameCount++;
uint32_t now = HAL_GetTick();
if (now - lastTick >= 1000) {
fps = frameCount;
frameCount = 0;
lastTick = now;
// 此时fps就是当前帧率
}
}
嗯,这里要注意:TouchGFX自带的性能监测工具可以直接看到实时FPS,但我建议你在开发阶段自己加一个这样的计数器,方便定位问题。
1.2 刷新机制:TouchGFX怎么把画面画上去?
TouchGFX的刷新机制,我总结为三个字:增量刷新。
什么意思?它不是每一帧都把整个屏幕重画一遍,而是只画变化的部分。这跟PC上的游戏引擎完全不同——游戏引擎恨不得每帧都渲染整个场景,但嵌入式MCU的资源有限,全屏重绘太奢侈了。
具体流程是这样的:
- 脏矩形检测:TouchGFX会标记哪些区域发生了变化(比如按钮按下、文字更新)
- 局部渲染:只渲染这些脏矩形区域
- DMA传输:通过DMA把渲染好的数据送到显存
- 屏幕刷新:LCD控制器从显存读取数据,显示到屏幕上
我的经验:曾经有个项目,动画卡顿严重。我打开TouchGFX的调试工具一看,发现脏矩形几乎覆盖了整个屏幕——等于每次都在全屏重绘。后来优化了动画逻辑,把脏矩形缩小到原来的1/5,帧率直接从25FPS飙到55FPS。
所以,理解脏矩形机制,是优化动画性能的第一步。
1.3 VSync同步原理:为什么画面会撕裂?
VSync,垂直同步。这个名字听起来高大上,其实原理很简单。
咱们的LCD屏幕,是从上到下逐行扫描的。如果CPU在屏幕扫描到一半的时候,突然把显存里的数据换了,就会出现上半张是旧画面、下半张是新画面的情况——这就是画面撕裂。
VSync的作用,就是让CPU/GPU等到屏幕扫描完一整个画面(垂直消隐期)之后,再更新显存数据。
避坑指南:我曾经在一个项目里关闭了VSync,想着能提高帧率。结果帧率确实上去了,但画面撕裂严重,用户体验极差。后来老老实实把VSync打开,虽然帧率降了一点,但画面流畅度反而提升了。
在TouchGFX里,VSync的配置通常在HAL层:
// TouchGFX HAL配置示例
static TouchGFXHAL hal;
hal.setFrameBufferStartAddress((uint16_t*)FRAME_BUFFER_ADDR);
hal.setVsyncInterval(16); // 60FPS对应的VSync间隔,单位ms
hal.setDisplayRefreshMode(touchgfx::HAL::DISPLAY_REFRESH_MODE_VSYNC);
这里有个细节:setVsyncInterval(16) 对应的是60FPS。如果你的屏幕是30FPS,那就设成33。这个值必须和屏幕的刷新率匹配,否则动画时序会乱。
1.4 三者之间的关系
帧率、刷新机制、VSync,这三者不是孤立的。我画了一张图,帮你理清它们的关系:
从这张图你能看出来,三个环节是环环相扣的。帧率上不去,可能是刷新机制没用好;画面撕裂,多半是VSync没配好。我建议你在做性能优化时,按这个顺序排查:先看VSync配置对不对,再看脏矩形是否合理,最后才去调帧率目标。
1.5 实际项目中的常见问题
我把这些年遇到的高频问题整理了一下,列个表方便你对照:
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 帧率忽高忽低 | VSync间隔不匹配 | 检查 setVsyncInterval 是否与屏幕刷新率一致 |
| 画面撕裂 | VSync未开启或配置错误 | 确认 DISPLAY_REFRESH_MODE_VSYNC 已启用 |
| 动画卡顿 | 脏矩形过大或过多 | 使用TouchGFX Designer的Profiler查看脏矩形分布 |
| 帧率低于目标 | 渲染耗时超过VSync间隔 | 优化渲染逻辑,或降低目标帧率 |
一个小技巧:如果你不确定当前帧率是否稳定,可以在屏幕上放一个FPS显示控件。TouchGFX Designer里自带这个组件,拖出来就能用。我习惯在开发阶段一直开着它,就像开车看仪表盘一样。
好了,这一章的内容就到这里。帧率、刷新机制、VSync,这三个概念是TouchGFX动画性能优化的基石。后面的章节,我们会基于这些基础,一步步深入具体的优化技巧。