资讯动态

STM32F746移植TouchGFX实战:从LTDC配置到RGB屏界面流畅运行

发布时间:2026/10/19 6:42:22 来源:尧图企业网站定制
做嵌入式的人大概都有一段时间特别“怕做界面”。裸机点灯、串口打印这些还好说一接到“给设备加个显示”的需求经常连续熬夜调参数画一条直线要想抗锯齿显示中文得先找字库换几页菜单就得重新设计刷新逻辑。我是在给微雪Open746开发板移植TouchGFX之后才真正觉得STM32上做GUI这件事可以变得很轻松。这块板子用的主控是STM32F746IGT6CM7内核跑到216MHz再加上板载SDRAM和RGB接口电容屏可以说是为TouchGFX量身准备的硬件。这篇文章就把我从CubeMX配置、LTDC时序、SDRAM帧缓冲、触摸芯片接入到TouchGFX Designer出页面、最后在板上跑通的完整过程写出来目的很明确让手里有Open746或者类似F746板子的朋友少走几个我踩过的坑。1. 先看清这块板子Open746凭什么适合跑TouchGFX1.1 Open746的硬件底子微雪Open746的核心是STM32F746IGT6这颗料天生就是干显示这活的。Cortex-M7内核主频最高216MHz片上带1MB Flash和320KB的SRAM。320KB的RAM听起来不算小但如果在800x480的屏上开一个ARGB8888的帧缓冲一次就要吃掉大概1.5MB单靠片上RAM肯定不够。所以Open746板载了一颗外部SDRAM常见型号是华邦的W9825G6KH容量为32MB正好解决帧缓冲的内存问题。板上还引出了RGB接口的LCD排座配套使用的是4.3寸、800x480的电容触摸屏触摸控制器走I2C接口。F746这颗芯片最值得关注的是内部集成了LTDC控制器和DMA2D图形加速器。LTDC的作用是不断从指定的显存地址读取像素数据按照面板的时序信号把数据推到LCD排线上整个过程由硬件DMA完成CPU只需要保证显存里面的内容正确。对比老式的8080并口屏MCU省下的时间相当可观。所以只要在SDRAM里放好几张帧缓冲再告诉LTDC这些缓冲的基地址屏幕就能自己刷新起来CPU就可以腾出手去跑业务逻辑。1.2 为什么选TouchGFX而不是继续用老办法很多朋友会问STM32上做界面的方案不是挺多吗为什么偏偏要折腾TouchGFX我之前也用过一些轻量级GUI库说实话简单的菜单页面它们完全能搞定但要做到漂亮的动效、平滑的滑动切换、复杂的自定义控件写起来就很吃力。TouchGFX的优势在于它跟F746的硬件配合得很紧底层直接利用了LTDC和DMA2D做透明叠加、混合效果都不需要CPU去算像素。而且它的PC工具TouchGFX Designer是可视化拖拽界面写完界面代码由工具生成你只需要关心页面逻辑不用维护一堆坐标计算。另外要提一个很多人在意的事ST整合TouchGFX之后这个框架已经对STM32用户免费开放不需要担心版权费用问题。对我这种习惯先跑通再深入的人来说把TouchGFX跑在Open746上还有一个大好处——它生成的项目结构很清晰UI代码和应用代码分层后面做工程维护比全手写绘图逻辑要舒服得多。我的结论很直接如果你手里有一块带SDRAM和RGB屏的F7系列板子第一选择就应该是TouchGFX。2. 移植前的准备工作工具链和基础工程2.1 三个软件怎么配才不打架工欲善其事必先利其器。做TouchGFX移植我前后会用到三个工具STM32CubeMX负责生成底层工程和外设初始化TouchGFX Designer负责设计界面并生成UI代码编译环境我习惯用STM32CubeIDE。如果偏好其他IDE也没关系IAR和Keil同样能编译TouchGFX工程只是工程文件结构略有不同。工具版本需要注意一个点TouchGFX Designer和CubeMX的集成度是慢慢变高的新版CubeMX可以直接在中间件列表里找到TouchGFX Generator。我建议装新一点的版本比如TouchGFX Designer活动维护版本配合对应的CubeMX版本能省去很多手动搬文件的麻烦。装好之后CubeMX界的New Project向导里会多出TouchGFX相关选项这就是两者打通了。我见过有人卡在“CubeMX生成不了TouchGFX代码”上多半原因是两个软件的版本对不上。最省事的做法是打开CubeMX时先别急着建工程检查一下它识别到的TouchGFX路径是否正确也就是TouchGFX Designer的安装目录。路径里尽量不要带中文或空格老话常谈但真的有人因为这个编译不过。2.2 CubeMX把外设和时钟搭好新建工程时需要选择正确的芯片型号也就是STM32F746IGT6软件会自动匹配引脚定义。一个比较关键的地方是时钟树Open746板载晶振的值需要跟硬件对应F746最高主频216MHzCubeMX里配置成最高频率即可TouchGFX对性能的要求不低建议把主频拉满。接下来要开启的外设主要是这几个LTDC用于控制显示接口FMC用于访问外部SDRAMI2C用于读触摸屏另外还要配置一个串口后面调试打印信息会用到。从CubeMX的角度讲外设的初始化代码生成非常自动化你只需要在图形界面上把参数填对点击生成代码它就帮你把这些寄存器的初始化全部写好。这一步骤做到底就为正式移植打好了底子后面出错的可能性会小很多。这里有一个细节建议在CubeMX的引脚分配界面里先把LCD和触摸相关的引脚都翻开看一下确认它们没有被复用成其他功能。比如RGB接口的很多引脚的默认复用功能可能就是GPIO你需要手动改成LTDC的复用设置。微雪Open746的引脚布局在板子手册里会给一个清晰的对应关系照着改就行。不要嫌这一步啰嗦引脚冲突是后面白屏和触摸无响应最常见的根源之一。3. 关键配置逐个过LTDC、SDRAM、触摸和系统任务3.1 LTDC时序屏幕白屏还是花屏全看它LTDC的配置是我觉得整个移植过程中最需要耐心的部分。你要理解它本质上是一套“时钟产生器”它负责产生LCD面板需要的HSYNC、VSYNC、DE和像素时钟信号。每个屏都有自己的时序参数而且这些参数通常写在屏幕的数据手册里大多数4.3寸800x480的RGB屏参数是比较接近的但千万不能拍脑袋乱填。纯手工移植的老玩家肯定看过很多教程都贴过这么一组经典参数水平同步脉冲宽度1、水平后肩46、水平前肩210、垂直同步脉冲宽度1、垂直后肩23、垂直前肩22像素时钟大约33.3MHz。这个参数在很多4.3寸屏幕上是通用的可以直接作为起点。如果把前肩和后肩填错屏幕上通常会出现明显的偏移或者显示花屏如果像素时钟差得太远屏幕亮度会异常或者干脆白屏。在CubeMX的LTDC配置界面里把这几个值填进去之后还需要启用Layer1图层。注意图层要设置正确的窗口大小也就是800x480并且要把像素格式跟后面TouchGFX里选择的格式对应起来。F746的LTDC支持很多种像素格式比如RGB565、RGB888、ARGB8888格式选错会在屏幕上出现颜色严重失真、每像素错位的现象这类问题定位起来比花屏还要恼火。3.2 SDRAM分配帧缓冲放哪、放几份TouchGFX的帧缓冲如果放在内部SRAM里800x480的分辨率根本放不下。正常做法是把帧缓冲放到外部的SDRAM中SDRAM的基地址通常从0xC0000000开始。在CubeMX里把FMC配置成连接SDRAM的方式然后确认访问时序能让存储器稳定工作这一步一般要做个简单的写读测试确保SDRAM能正确读写才往下继续。帧缓冲数量的选择很有讲究。最保守的方案是用单帧缓冲占内存最少但画面刷新过程中如果LTDC正在读上半屏CPU或DMA2D已经开始写下半屏就可能看到撕裂效果。我的建议是至少开双缓冲也就是准备两份同样大小的帧缓冲TouchGFX在其中一块上绘制另一块正在被LTDC扫描显示当前者绘制完毕后再进行交换这样画面会稳定很多。算一下内存需求其实很简单800x480的屏幕用ARGB8888格式时每个像素占4字节单帧缓冲约1.54MB双缓冲约3MB用RGB565时每像素占2字节双缓冲也就约1.5MB。Open746上的32MB SDRAM完全扛得住。我在工程里是这样安排的SDRAM前几个MB留给帧缓冲后面部分留给其他用途比如缓存图片资源或者做堆。这样布局清晰后面排查内存覆盖问题会方便很多。3.3 触摸芯片接入把触摸数据送进TouchGFXOpen746配套的电容触摸屏常见的触摸控制器有汇顶的GT9xx系列也有FT5x06系列具体可以看板子上丝印。以GT9xx为例它通过I2C跟主控通信地址通常由复位引脚的电平决定常见的有0x5D和0x29两个地址。读触摸数据的大致过程是先读控制寄存器判断有没有触摸事件然后读出触摸点的坐标值。GT9xx内部有一块映射寄存器区坐标数据就存在特定的偏移位置顺着规格书查就行。TouchGFX对触摸层的接口定义得很简单在工程里会有一个STM32TouchController.cpp文件里面有个sampleTouch函数TouchGFX的框架会在需要时反复调用它。你只需要在这个函数里把触摸坐标读出来写入x和y两个引用参数返回true表示有触点。也就是说从硬件的I2C数据到TouchGFX的触摸事件中间就差这么一小段驱动代码。很多第一次接触这个接口的人会疑惑坐标方向的问题。触摸芯片输出的坐标通常是原始坐标而触屏在板子上的安装方向可能跟屏的扫描方向不一致。遇到这种情况最简单的办法就是在sampleTouch里对坐标做一次坐标变换比如交换X和Y或者做x 800 - x这样的反转。先用一段串口打印代码把原始坐标打印出来判断方向后改变换公式是最快的调试思路。3.4 把TouchGFX挂进FreeRTOS任务如果CubeMX工程里用了FreeRTOSTouchGFX推荐跑在一个独立的任务里而不是放在主循环裸跑。原因很简单TouchGFX内部有一套事件循环机制它负责处理触摸事件、定时器、动画刷新等如果跟业务逻辑挤在同一个主循环里很容易互相卡顿。把它放进独立的FreeRTOS任务UI线程和其它业务线程就能各跑各的。CubeMX的TouchGFX Generator可以帮你自动生成这个任务你只需要在中间件配置里打开TouchGFX再设置好显示分辨率和像素格式生成代码后它会自动创建一个名叫TouchGFX_Task的线程。任务函数内部调用核心的touchgfxRun()函数这个函数正常情况下不会返回而是不断地处理触摸事件和渲染请求。单独把UI放一个任务还不够还要注意优先级和栈大小。TouchGFX的绘制过程涉及大量函数调用和浮点运算任务栈要给足给太少会直接进HardFault。我在调试的时候遇到过几次非常隐蔽的进硬件错误异常问题检查完内存访问、时钟配置都没问题最后发现是任务栈爆了这个教训很深刻。4. 正式移植流程从Designer到板上跑通4.1 用TouchGFX Designer搭第一个页面硬件底层配置基本就绪后重心转移到TouchGFX Designer这边。启动后可以新建一个空项目选择对应的芯片型号和显示参数设计器会根据配置生成一个包含基础工程结构的.touchgfx文件。设计器的界面是非常友好的左边是控件库中间是画布右边是属性和交互面板。我会建议先从最简单的文本和按钮开始不要一上来就堆复杂的图表和动画先把跑通流程走完。在设计器里拖一个背景图片和按钮再给按钮添加一个跳转页面的交互动作这些操作完全是图形化的。完成后点击生成代码设计器会把GUI相关的源码输出到工程指定目录下。如果你是把设计器工程跟CubeMX工程放在同一个文件夹管理生成的代码会被整合到CubeMX工程里。注意TouchGFX Designer生成的是C代码底层驱动继续使用C代码这种混合架构对嵌入式工程来说是很常见的。4.2 工程合并和链接器配置使用TouchGFX Generator时CubeMX工程会自动引用TouchGFX目录下的代码而手动移植方式则需要自己处理文件拷贝。我建议能自动集成的话尽量用自动方式能把工作量减少一大部分。但无论自动还是手动有一个地方必须亲自动手那就是链接脚本。TouchGFX生成的帧缓冲通常定义在SDRAM地址段你要在链接脚本里声明一个SDRAM区域并且给帧缓冲分配一个合适的起始地址。链接器的写法取决于你用的IDE我用的STM32CubeIDE是GCC链接脚本里面需要增加类似这样一段/* 声明外部SDRAM区域 */ SDRAM (xrw) : ORIGIN 0xC0000000, LENGTH 32M然后确保工程链接的符号把帧缓冲数组放到这个区域里。TouchGFX通常在TouchGFXHAL里配置帧缓冲地址你可以直接在配置头文件里指定一个具体的SDRAM地址比如0xC0000000也可以让链接器把一个大数组分配到.sdram段再传入地址。两种方式都行第二种对内存布局管理更清晰推荐用它。如果链接脚本没有正确include SDRAM区域编译出来的程序运行时即使能启动也会在初始化SDRAM帧缓冲期间访问非法地址表现就是死机。另外链接脚本中SDRAM区域的起始地址一定不能跟其它用途的内存段冲突这点在你手动规划内存时要有全局意识。4.3 编译烧录后第一次点亮一切配置完成后就可以尝试第一次编译了。第一次编译大概率会有报错常见的有函数未定义、头文件找不到、C链接不兼容提示等。不要慌先把报错信息逐条看一遍。绝大多数“未定义引用”都指向触摸驱动或者显示驱动的某个函数没实现你可以先写一个返回空的实现来占位确认编译链接通过后再填充功能。烧录之后第一次上电如果一切正常屏幕会先显示TouchGFX的默认启动界面。如果屏幕没有显示任何东西先把LTDC相关初始化代码打印日志确认它有没有执行再检查LCD排线是否接好排除硬件问题。在这个过程中我强烈建议串口打印要提前做好因为屏幕本身不亮的时候你唯一的排查窗口就是串口。当屏幕上出现默认页面后第一件事是确认触摸是否可用。用手指点在屏幕上如果UI响应了按钮按下效果说明触摸链路已经打通。如果触摸没反应回到触摸驱动上排查先确认I2C通信正常再确认中断引脚和复位引脚的配置。第一次触摸能跑通整个移植工程的骨架就算是立住了。5. 翻车现场与排查速查表5.1 白屏、花屏和条纹我在调试过程中被LTDC坑的次数最多白屏问题基本可以按这个优先级排查。第一确认LTDC时钟是否使能像素时钟是否产生。用示波器量LCD接口上的像素时钟是最直接的办法没有示波器也可以在代码里打印相关寄存器的值来确认。第二确认时序参数尤其要核对同步脉冲、前肩和后肩。第三个常见原因是图层没有使能或者图层默认透明色被设成了全透明导致LTDC反复扫描但整层都没有有效像素输出。花屏通常跟像素格式不匹配有关。你在一帧像素数据里按照RGB565写入但LTDC却按照ARGB8888去解释那么每个点的颜色必然错乱。还有一个原因是屏幕数据线和F746的引脚顺序接得不对这种纯硬件问题在整板底板上一般不会出现但如果你自己做的底板就要拿起放大镜检查PCB走线对照。屏幕上出现横向条纹很多情况下是SDRAM带宽不够或者是刷新过程中帧缓冲被同时访问。把像素时钟稍微降低一点测试如果条纹减轻就基本确定是带宽问题。另外开启双缓冲也能改善这种撕裂感。实在不行就上RGB565内存带宽压力小很多肉眼对这种格式下的颜色损失是不敏感的。5.2 触摸漂移、方向不对触摸能用但点击位置跟手指的位置偏了这种问题通常不是硬件坏了而是坐标映射没做好。触摸芯片直接读到的坐标是它在触摸面板物理坐标系下的值屏幕显示有它自己的坐标方向二者如果不一致就会出现点击A点响应在B点的现象。我调试的时候会专门做一个测试页面在四个角和中心各放一个按钮点击时观察实际响应按钮在哪个位置这样判断方向偏差非常直观。方向修正完成后如果还存在整体偏移比如总是偏左上通常是坐标范围没有做线性映射。把读出的X和Y按照触摸面板的最大值和屏幕分辨率做一次线性变换基本上就能解决。这个过程中最好把原始坐标打印出来总结规律后再写映射代码。触摸的灵敏度如果偏弱可以检查触摸控制器初始化时是否配置了合适的增益和阈值这些寄存器参数一般在触摸芯片的初始化序列里可以调整。还有一种更隐蔽的情况触摸能上报但是点击后界面卡死。原因往往是触摸中断引脚没有正确接入或者驱动在等待触摸状态时陷入死循环。建议把触摸流程做成非阻塞的读取方式始终给底层的触摸检测留有超时退出避免硬件异常时把整个UI任务挂死。5.3 帧率拖沓怎么办如果点击按钮后动画的过渡不够流畅第一件事是确认芯片的I-Cache和D-Cache是否开启了。Cortex-M7有很强的Cache能力我见过很多工程因为没开CacheTouchGFX运行性能至少损失三成。打开Cache的代码很简单CubeMX甚至可以在系统初始化阶段自动生成务必确认它已经执行。第二个方向是看CPU主频Open746是能到216MHz的如果你把系统时钟配置成180MHz甚至更低都会影响渲染速度。在主频和Cache都正常的前提下帧率依然不理想就要考虑像素格式了。ARGB8888确实漂亮但渲染和搬运的开销大如果不是特别需要透明混合效果换成RGB565能让流畅度上一个台阶。还有一个容易忽略的点就是DMA2D的使用。TouchGFX在内部会尽量把图片混合、拷贝这类操作交给DMA2D去处理但前提是你要在TouchGFX的配置里使能DMA通道。配置正确后你可以从日志里看到大量绘制任务被承接给了DMA2DCPU负载明显降低刷新效果也会更平滑。写在最后的经验整套移植流程走下来我最想跟大家分享的是TouchGFX移植这件事真正难的不是框架本身而是对目标板硬件细节的把握。LTDC时序、SDRAM初始化、触摸坐标映射每一个都是独立的“坑点”但它们组合在一起时就变成了整个GUI能否跑起来的关键链路。我个人的习惯是每完成一个环节就在串口打一条明确日志从时钟配置、SDRAM自检到触摸事件上报层层递进地确认而不是等屏幕上出现结果了再去猜。这样就算出问题也能快速定位到具体是哪一环断了。如果你也在Open746上移植TouchGFX大可不必被那些参数吓住按顺序一步步搭下来最后看到自己拖出来的界面在屏幕上一帧一帧流畅运行那种成就感是值得的。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑