
在自制板卡上跑 TouchGFX 这件事我前后折腾了将近三周。中间一度怀疑是硬件画错了、屏幕买错了、甚至是芯片本身有问题最后才发现大部分时间都耗在了几个非常隐蔽的软件配置和内存细节上。这篇东西就是把这段经历里最有价值的排查思路、参数计算和避坑点整理出来给正在和 TouchGFX 死磕自定义板卡的朋友一个参考。先说结论TouchGFX 本身并不难难的是“把它放到一块不是官方评估板的硬件上”。官方板卡的工程一生成就能跑那是因为 ST 已经把引脚映射、SDRAM 时序、触摸芯片型号、屏幕参数全部匹配好了。换到自定义板卡这些隐含的“正确答案”全部失效每一个环节都需要你自己重新确认。这篇内容适合手里已经有了一块能跑裸机程序的板子、准备或正在把 TouchGFX 集成进来的人阅读我会按照实际踩坑的顺序把从显示链路到触摸适配再到性能调优的完整路径讲清楚。1. 自定义板卡和官方评估板之间的“隐形差距”很多人会有一个误解TouchGFX 就是一套软件库放到哪块 MCU 上都应该一样跑。但实际上TouchGFX 的设计前提是“GPU 辅助渲染”和“帧缓冲直接输出到显示控制器”这两点让它对底层硬件接口的依赖远高于一般 GUI。这也是为什么在自定义板卡上它表现得格外“娇气”。1.1 先分清 TouchGFX 和普通 GUI 的定位差异普通的嵌入式 GUI比如 LittlevGL 或者 emWin本质上是软件把像素画进一块内存区域然后再通过某种方式搬运到屏幕上。这个过程里MCU 的算力决定了绘图速度显示接口只负责“搬运”两者相对独立。TouchGFX 则不同。它针对 STM32 的 LTDCLCD-TFT Display Controller和 DMA2D内存到内存的图形加速器做了深度优化渲染管线的理念是“尽可能在写入显存的同时就让数据流到屏幕上”并通过双缓冲、局部刷新、帧缓冲在 SDRAM 和内部 SRAM 之间的分配来换取性能。这意味着如果没有配置好 LTDC、没有分配好帧缓冲、没有让 DMA2D 按预期工作TouchGFX 的表现会变得非常奇怪——有时候是画面撕裂有时候是颜色错乱有时候干脆黑屏。另一个容易忽略的点是TouchGFX Designer 生成的代码默认是为 CubeMX 生成的工程服务的它会假设你已经通过 CubeMX 配置好了时钟树、FMCFlexible Memory Controller和 LTDC。如果这些底层配置和你的板子不一致生成的代码几乎不可能直接跑通。1.2 硬件差异带来的第一个坑显示接口类型官方评估板上常见的屏幕接口有两种并行 RGB 接口通过 LTDC 外设直接驱动数据线数量从 16 位到 24 位不等。MIPI DSI 接口通过 DSI 主机外设驱动数据走差分串行链路。你的自定义板卡是哪一种直接决定了 TouchGFX 工程里需要启用的外设和引脚分配。很多人在这一步就卡住了用了一块 RGB 接口的屏幕却在 CubeMX 里参考了 MIPI DSI 的评估板工程或者反过来。我在排查时最先做的就是“接口三确认”屏幕数据手册上标明的接口类型是什么并行 RGB 还是 MIPI DSI 或 SPIMCU 上对应外设是否支持这种接口例如 STM32F429 系列只有 LTDC而 STM32F769 系列同时有 LTDC 和 DSI。CubeMX 的引脚分配是否与硬件原理图完全一致特别是像素时钟、HSYNC、VSYNC、DE、数据引脚的位置。这三项只要有一项不对后续不管怎么调软件都是白费功夫。2. LTDC 显示链路排查接线、时序与花屏的真相LTDC 是 TouchGFX 在大部分 STM32 平台上最关键的显示外设。它的作用是把内存中的帧缓冲数据按照你设置的时序参数源源不断地输出到屏幕。如果把整条链路比作一条水管LTDC 就是那个水龙头帧缓冲是水箱屏幕是出水口。任何一个环节堵塞最终看到的结果就是花屏或者黑屏。2.1 引脚映射核对按键级别的最佳实践我在这次项目中踩的第一个具体问题是屏幕颜色看起来整体偏绿而且画面严重错位。排查到最后发现原因简直让人哭笑不得——RGB 引脚映射时把红色和绿色的两组数据线接反了。LTDC 的数据引脚是这样的RGB888 模式下LTDC_R2到LTDC_R7对应红色的 6 位数据LTDC_G2到LTDC_G7对应绿色 6 位数据LTDC_B2到LTDC_B7对应蓝色 6 位数据。如果你在自定义板卡的原理图上将 MCU 的某个引脚分配给了 LTDC 的某个信号但 PCB 布线上这个信号实际连到了屏幕的另一组数据线那么屏幕显示的图像就会是通道互换后的结果。排查这个问题最快的方式不是用 TouchGFX 去调而是先写一个裸机测试程序直接往 LTDC 的帧缓冲地址里填几个纯色像素红色 0x00FF0000、绿色 0x0000FF00、蓝色 0x000000FF然后用示波器或者逻辑分析仪检查对应数据线上的电平。如果硬件连线本身有问题那么无论怎么在软件里折腾都不可能得到正确的颜色。另外一个经常被忽略的是 LTDC 的 DEData Enable信号极性。很多屏幕要求 DE 为高电平有效但某些屏的驱动 IC 对极性的要求比较特殊。在 CubeMX 的 LTDC 配置里Polarity有 Active High 和 Active Low 两个选项大部分情况下选 Active High但也有例外。遇到整屏有条纹、或者画面左右颠倒、上下颠倒时除了检查 HSYNC/VSYNC 极性也要顺手确认 DE 的极性。2.2 LTDC 时序参数的确定过程LTDC 的时序参数包括参数含义典型来源Hsync 宽度水平同步信号脉冲宽度像素时钟数屏幕数据手册Hsync 前肩有效数据开始前的同步信号后延时屏幕数据手册Hsync 后肩有效数据结束到下一同步信号的间隔屏幕数据手册Vsync 宽度垂直同步信号脉冲宽度行数屏幕数据手册Vsync 前肩有效帧开始前的同步行数屏幕数据手册Vsync 后肩有效帧结束后的同步行数屏幕数据手册很多人直接用 CubeMX 里的默认值然后发现屏幕显示位置偏移或者出现扫描线。正确做法是严格对照屏幕数据手册中的“Timing Characteristics”表格填写。以常见的 4.3 寸 480x272 RGB 屏为例数据手册里通常会给出类似这样的参数HsyncWidth: 41 HsyncFrontPorch: 2 HsyncBackPorch: 2 VsyncWidth: 10 VsyncFrontPorch: 2 VsyncBackPorch: 2把这些数值填入 CubeMX 后还差一个像素时钟的计算。LTDC 的像素时钟PixelClock决定了数据的输出速率计算公式是PixelClock (屏幕宽度 HsyncWidth HsyncFrontPorch HsyncBackPorch) × (屏幕高度 VsyncWidth VsyncFrontPorch VsyncBackPorch) × 刷新率以 480x272、60Hz 刷新率为例代入上面给的时序参数水平总像素 480 41 2 2 525 垂直总行数 272 10 2 2 286 PixelClock 525 × 286 × 60 ≈ 9.01 MHz所以PixelClock大约设为 9 MHz 即可。如果设得太高屏幕可能超出带宽导致闪屏设得太低刷新率下降肉眼能感觉到卡顿。这里有一个很重要的实操建议在你把 TouchGFX 工程烧进去之前先用裸机程序把 LTDC 调好确认屏幕能正常显示纯色和颜色渐变。这一步如果花半天时间换来的是之后整整少掉几天排查黑屏的时间非常划算。3. 帧缓冲落进 SDRAM带宽、对齐和 Cache 三个拦路虎显示链路通了之后下一个大坑就是帧缓冲。TouchGFX 在自定义板卡上“跑不动”的原因十有八九出在 SDRAM 的配置上。3.1 为什么必须用到 SDRAM先算一笔账。假设屏幕分辨率是 480x272采用 RGB888 颜色格式每个像素 4 字节32 位单帧缓冲大小480 × 272 × 4 522,240 字节 ≈ 510 KB如果按照 TouchGFX 默认的双缓冲策略就需要约 1 MB 的内存。再算上图形资源、字库、图片缓存至少需要 1.5~2 MB 的连续内存。STM32 内部 SRAM 通常只有 192 KB 到 512 KB完全不够用。所以SDRAM 基本是必须的。有些人试图用单缓冲 小分辨率来绕过 SDRAM但这会牺牲 TouchGFX 的核心优势——平滑的动画效果和局部刷新能力相当于买了个跑车只用来在小区里买菜意义不大。3.2 FMC 配置的坑时序、位宽和 Bank 地址SDRAM 挂在 STM32 的 FMCFlexible Memory Controller上CubeMX 中有一个完整的 SDRAM 配置界面。常见的 SDRAM 是 16 位数据宽度挂在 Bank 1 或 Bank 2 上地址范围根据 Bank 和行/列地址数而定。配置 SDRAM 时有几个关键参数列地址位数Column Bits常见 8、9、11 位取决于 SDRAM 芯片型号。行地址位数Row Bits常见 11、12、13 位。CAS 延迟CAS Latency常见 2 或 3需要和 SDRAM 芯片规格匹配。刷新周期Refresh Period通常 64 ms但具体在 FMC 里填的是刷新计数需要根据 SDRAM 数据手册计算。一个非常容易犯的错误是行地址和列地址数填错导致访问 SDRAM 时地址错乱。表现是TouchGFX 跑起来时画面某些区域出现规律的乱码或花屏且每次运行位置固定。这是因为帧缓冲的地址映射与 SDRAM 实际物理地址不对应数据写入了错误的行列。正确做法先查你的 SDRAM 芯片数据手册确认行列地址位数和刷新周期。例如 W9825G6KH 是 256Mb SDRAM行地址 13 位列地址 9 位Bank 数 4数据宽度 16 位。那么在 CubeMX 中就应该把 Row Bits 设为 13Column Bits 设为 9。不要想当然地照搬其他工程。3.3 内存对齐和 D-Cache 导致的花屏TouchGFX 的帧缓冲地址有对齐要求通常是 32 字节对齐。如果帧缓冲变量定义时没有指定对齐属性编译器可能会把它放在一个未对齐的地址上导致图形渲染时出现奇怪的偏移或者是边缘出现噪点。在 TouchGFX 生成的代码中帧缓冲通常通过 CubeMX 分配在 SDRAM 的起始位置。你可以通过链接脚本Linker Script来保证这一点。例如在 STM32CubeIDE 的.ld文件中可以为 SDRAM 单独定义一个内存区域然后在代码中显式声明__attribute__((section(.sdram))) uint32_t framebuffer[480*272];这样帧缓冲就会被放置到你指定的 SDRAM 地址段对齐问题也能通过区域起始地址对齐来解决。更稳妥的做法是检查生成的链接脚本中.sdram段的ALIGN(32)设置。D-Cache 是另一个隐性杀手。当你开启了 STM32 的 D-Cache 后CPU 会先把数据缓存在 Cache 里而不是立刻写入 SDRAM。如果 TouchGFX 的 DMA2D 直接读取 SDRAM 中的帧缓冲进行图形操作而 CPU 已经写入的数据还在 Cache 中就会产生数据不一致。表现为画面要么出现“残留”“拖影”要么某个区域一直保持旧内容。解决办法是在 TouchGFX 的帧缓冲切换或刷新之后做一次 Cache 的 Clean 和 InvalidateSCB_CleanDCache_by_Addr((uint32_t*)framebuffer, sizeof(framebuffer)); SCB_InvalidateDCache_by_Addr((uint32_t*)framebuffer, sizeof(framebuffer));这两个函数的调用时机需要仔细斟酌。一般做法是在写入帧缓冲之后调用 Clean确保脏数据写回内存在 DMA2D 读操作之前调用 Invalidate确保 Cache 中的数据是最新的。如果时机不对效果甚至会更差。3.4 带宽计算的必要性SDRAM 带宽是很多人忽视的瓶颈。计算方式为屏幕总像素 × 每像素字节数 × 刷新率 最低带宽需求继续用 480x272 的屏幕和 32 位色彩来算480 × 272 × 4 × 60 31,334,400 字节/秒 ≈ 31.3 MB/s这只是显示所需的数据量还没算 TouchGFX 在动画、局部刷新时需要额外从 SDRAM 读取图像资源、字库的开销。如果 SDRAM 的配置时序过于保守实际可用带宽不够就会出现掉帧、卡顿。从实测来看把 SDRAM 时钟和刷新参数调到符合芯片规格的安全上限范围内是提升整体流畅度最直接的硬件手段。4. 触摸驱动适配从 I2C 地址到坐标映射的完整打通显示链路通了之后屏幕上能看到 TouchGFX 的界面了但点击完全没反应。这个问题卡了我两天。TouchGFX 的“触摸”并不是自己知悉触摸芯片的存在而是通过一个TouchController抽象层来获取坐标信息的。这个抽象层必须由你根据实际的触摸芯片驱动来实现。4.1 触摸芯片的 I2C 探测与地址确认市面上常见的触摸芯片包括 GT911、FT5x06、GT811、CST816 等。每种芯片的 I2C 地址可能不同甚至同一型号可能有多个地址位可选取决于芯片引脚电平。首先确认你的触摸芯片型号然后从数据手册中找到其 I2C 地址。以 FT5x06 为例其 7 位 I2C 地址常见为 0x38但某些版本的地址可能通过引脚配置为 0x28。如果你直接用 0x38 去读读不到任何数据触摸自然就不工作。一个非常实用的探测方法写一个简单的 I2C 扫描程序遍历地址 0x00 到 0x7F看哪个地址有 ACK 响应。我之前就是这样找出了板子上触摸芯片的真实地址节省了大量时间。4.2 TouchGFX 中的 TouchController 接口在 TouchGFX 生成的工程中有一个名为TouchController的抽象类需要实现它的init()和sampleTouch()方法。sampleTouch(int32_t x, int32_t y)的返回值代表是否有触摸事件x和y则是触摸坐标。这里有一个非常容易踩的坑TouchGFX 期望x和y的范围与屏幕分辨率一致且坐标原点在屏幕左上角。而很多触摸芯片报告的坐标是“原始坐标”范围可能是 0~4095 之间甚至坐标系也可能相反。举个例子GT911 在 480x272 屏幕上常常会报告 0~1023 或 0~2047 范围内的值且 X 轴和 Y 轴正向可能与屏幕相反。这时就需要在sampleTouch()里做缩放和映射x (raw_x * 480) / 1024; y (raw_y * 272) / 1024;如果发现触摸位置和点击位置不对应是镜像或者旋转的关系还需要做坐标翻转。例如x 480 - x; y 272 - y;确定坐标映射是否正确的办法是在屏幕上画一个十字准星然后依次点击左上、右上、左下、右下四个角用串口打印出 TouchGFX 收到的坐标值。通过这四个点的实际值和期望值就可以反推映射关系。4.3 中断模式和轮询模式的取舍触摸芯片一般会有中断引脚INT在有触摸事件时拉低或拉高通知 MCU 读取数据。你可以选择用 MCU 的外部中断来触发读操作也可以选择让 TouchController 在sampleTouch()里面直接轮询 I2C 读取。在实际项目里推荐使用 GPIO 外部中断 标志位的方式。理由是轮询模式下TouchController 每次被 TouchGFX 调用时都会去读一次 I2C即使没有任何触摸事件。这会白白占用 CPU 和 I2C 总线时间拖慢 GUI 本身的渲染效率。而中断模式只在有触摸事件时才触发读取效率高得多。但中断模式也有个坑触摸芯片的 INT 引脚通常是开漏输出需要外部上拉或者 MCU 配置内部上拉。如果你的原理图上没有这个上拉电阻中断可能会一直拉低或者一直拉高导致检测不到正确的边沿。排查时需要先用万用表测一下 INT 引脚的静态电平。关于这点我是吃了亏的原理图上漏画了一个上拉电阻导致中断信号一直无效白白查了两天。4.4 TouchGFX 与触摸 IC 驱动之间的数据流TouchGFX 的主循环会定期调用sampleTouch()把返回值交给 GUI 的事件处理器。如果你发现点击之后有反应但反应有几百毫秒的延迟可能的原因之一是 I2C 时钟频率太低读一次完整的数据需要太长时间。很多触摸芯片支持 400 kHz 的快速模式而 CubeMX 默认可能在 100 kHz。把 I2C 时钟频率调到芯片允许的上限可以明显降低触摸延迟。5. 构建链路与调试方法从编译报错到画面渲染当你把显示和触摸都调通之后下一个阶段的问题集中在“工程集成”和“构建配置”上。TouchGFX 生成的代码不像普通 HAL 工程那么简单它依赖多个外部库和特定构建选项。以下是我实际遇到并解决过的几类典型问题。5.1 CubeMX 工程与 TouchGFX 工程的联动步骤TouchGFX 的工作方式是这样的在 TouchGFX Designer 中创建 UI 工程指定 STM32 型号和分辨率它会生成一份 UI 代码和一个.ioc文件引用。然后你在 CubeMX 中打开这个.ioc进行外设配置生成初始化代码。最后把两部分代码合并到一个 IDE 工程中编译。一个很常见的错误是在 CubeMX 中打开了 TouchGFX 生成的.ioc之后重新生成了代码结果 TouchGFX 的库文件或中间层代码没有被正确包含进来。解决办法是确认工程里的 Middleware 选项中已经把 TouchGFX 勾选上并且设置里指定了正确的 TouchGFX 安装路径。我用的版本是 TouchGFX Designer 4.24 和 STM32CubeMX 6.10两者配合时有一个细节CubeMX 生成代码后会在工程目录下创建一个TouchGFX文件夹里面有target、generated、gui、App等子目录。这些目录里的文件不要随意改动尤其是generated目录里面是由 Designer 生成的代码和 UI 文件一一对应。如果手动改了它下次 Designer 重新生成时可能会覆盖掉你的修改。5.2 链接脚本中的 SDRAM 段和帧缓冲分配我之前提到过帧缓冲最好放在 SDRAM 中。这就需要在链接脚本中为 SDRAM 增加一个段。以 STM32F429 为例默认的链接脚本只定义了内部 FLASH 和 SRAM并没有 SDRAM 段。一个常见的做法是在.ld文件中添加MEMORY { FLASH (rx) : ORIGIN 0x08000000, LENGTH 2048K RAM (xrw) : ORIGIN 0x20000000, LENGTH 192K SDRAM (xrw) : ORIGIN 0xC0000000, LENGTH 8192K }然后在代码段定义中增加一个.sdram段. ALIGN(4); .sdram : { . ALIGN(32); *(.sdram) . ALIGN(32); } SDRAM之所以要对齐 32 字节是因为 DMA2D 和 LTDC 对帧缓冲地址有对齐要求未对齐会导致性能下降甚至硬件错误。这个细节我在最初做实验时没有留意结果折腾了一天才发现问题是地址没有 32 字节对齐。5.3 HardFault 的常见诱因和定位手段自定义板卡上跑 TouchGFXHardFault 可以说是“必修课”。最常见的诱因有三个帧缓冲未初始化TouchGFX 启动时会直接向帧缓冲地址写入数据。如果这个地址对应的内存还没有被启用比如 SDRAM 的 FMC 控制器还没初始化就尝试访问立即 HardFault。堆栈溢出TouchGFX 的 GUI 线程和渲染线程需要较大的栈空间。默认的启动文件可能只分配了 8 KB实际需要更大。如果动画复杂很容易溢出。外设时钟未使能LTDC、DMA2D、FMC 这些外设的时钟在 CubeMX 里默认会生成但如果你手动合并代码时漏掉了某一段初始化代码访问外设时也会 HardFault。定位 HardFault 最有效的方式是用调试器停在异常处理函数里查看栈回溯Call Stack找到触发异常的函数名。如果栈回溯信息不完整可以在HardFault_Handler里加上一段代码把程序计数器PC和链接寄存器LR的值打印出来然后对照汇编代码找到具体的函数。这部分比较烧脑但一旦找到位置修复通常很快。5.4 关于调试输出的建议TouchGFX 本身运行效率很高但它的渲染是没有“printf”的。也就是说你不能直接在屏幕上看到每个像素是怎么画出来的。想要确认系统在跑最好的方式是串口输出日志。我自己的习惯是在外设初始化完成、TouchGFX 启动之前用串口打印 “Start”在 TouchGFX 的主循环里使用一个强撸计数器每秒打印一次帧率或者 CPU 占用在触摸事件发生时打印触摸坐标。这套日志体系帮我快速定位了很多问题。比如如果“Start”能打印但画面始终黑屏说明问题出在 LTDC 配置如果画面能显示但 TouchGFX 的帧率极低说明问题出在帧缓冲或 SDRAM 带宽如果触摸事件完全没有说明问题出在 I2C 初始化或中断配置。6. 性能调优从掉帧到流畅的实测路径画面能显示、触摸能点击但这只是“能跑”。如果你想让界面像产品而不是演示板性能调优逃不掉。这一节讲的是我从掉帧明显到基本流畅的实测路径。6.1 帧时间分析瓶颈在哪里我先说一个概念TouchGFX 的渲染过程中CPU 负责绘制图形LTDC 负责把帧缓冲推送到屏幕DMA2D 负责图形加速。三者并行工作时帧率取决于最慢的那一个。从实际操作上看掉帧最常发生在动画切换和复杂图片填充的场景。这时候你需要判断瓶颈是 CPU 还是总线带宽。一个比较简单的判断方法在动画过程中用调试器观察 CPU 占用率。如果 CPU 占用率接近 100%且 DMA2D 的工作量并不大那瓶颈大概率在 CPU 的图形绘制逻辑可以通过将部分绘制任务交给 DMA2D 来缓解。如果 CPU 占用率并不高但帧率还是上不去瓶颈就更可能在内存带宽或 LTDC 的像素时钟。6.2 降低颜色深度是性价比最高的优化TouchGFX 支持 RGB88824 位/像素和 RGB56516 位/像素。从视觉效果上说RGB565 在某些渐变色场景会有轻微色带但换取的是帧缓冲带宽直接减半。在之前 480x272 的例子里RGB888 的带宽需求是 31.3 MB/s降到 RGB565 就是约 15.7 MB/sSDRAM 压力小了很多。如果你想追求流畅度且对颜色精度要求不是极高直接改成 RGB565 是立竿见影的做法。具体的修改位置在 TouchGFX Designer 的“Screen”属性或 CubeMX 的 LTDC 配置中需要把像素格式改为LTDC_PIXEL_FORMAT_RGB565同时在 TouchGFX 生成代码时的颜色深度也要对齐。如果这两处不一致会出现颜色完全错乱的情况。6.3 局部刷新与 DMA2D 加速的取舍TouchGFX 的局部刷新Partial Rendering是它相对传统 GUI 的一大优势。它只在画面变化的部分重新绘制而不是整帧刷新。这个特性在常用界面下可以大幅降低 SDRAM 带宽需求。但局部刷新也有一个代价它需要额外的一块“脏矩形”管理区域并且在某些操作中比全帧刷新更复杂。如果你的动画是全屏切换局部刷新的优势反而不明显。实际使用中我是这样取舍的静态界面、按钮点击、数字更新开启局部刷新效果明显。全屏动画、视频播放、地图平移关闭局部刷新直接用全帧双缓冲反而更稳。DMA2D 加速则建议全程开启。它可以在后台搬运数据减轻 CPU 负担。不过如果你发现 DMA2D 的缓冲区和 SDRAM 时序有冲突出现花屏可以先关闭 DMA2D验证是否为配置问题。6.4 关于内存分配的最终建议最后想提一个关于内存分配的思路这也是我在多个项目中验证过有效的做法在 SDRAM 中预留三个主要区域帧缓冲区双缓冲大小 屏幕分辨率 × 每像素字节数 × 2图形资源区图片、字库、缓存大小根据资源大小而定动态分配区用于 TouchGFX 运行时创建的动态对象把这三个区域在链接脚本或启动代码中明确划分然后用宏定义引用地址而不是让编译器随意放置。这样做的好处是你可以通过查看内存占用报告快速判断是否需要裁掉某些图片资源或者在帧缓冲区和动态区之间做出权衡。我见过不少人把所有的内存都放在一起用默认的堆分配来管理结果帧缓冲和数据资源相互干扰出现各种莫名其妙的 bug。划分区域虽然看似死板但能让系统行为更可预测排除问题时也更有针对性。6.5 实测数据和最终调优效果总结一下我在这块板子上的实测数据方便你做参考项目调优前调优后颜色深度RGB888RGB565刷新模式全帧刷新局部刷新帧率静态界面约 55 fps约 60 fps帧率日历翻页动画约 28 fps约 58 fpsSDRAM 带宽占用约 31.3 MB/s约 15.7 MB/s触摸响应延迟约 60 ms约 15 ms帧率提升最明显的是动画场景从 28 帧提升到接近满帧观感完全是两回事。触摸延迟的改善则主要归功于 I2C 时钟从 100 kHz 提到 400 kHz以及中断模式的正确配置。回到开头那句话TouchGFX 本身不复杂复杂的是自定义板卡带来的各种“隐含变量”。但只要能把显示、内存、触摸、构建这四件事逐个确定下来剩下的工作就和官方评估板没太大区别了。希望这篇记录能帮正在同样挣扎的人少走我走过的弯路。