资讯动态

STM32H743IIT6 CubeMX+TouchGFX工程搭建与避坑指南

发布时间:2026/10/17 16:21:45 来源:尧图企业网站定制
简介这是一份面向嵌入式GUI开发者的STM32H743IIT6完整工程基于正点原子平台将Cubemx配置、HAL库与Touchgfx图形框架整合适配4.3英寸800×480液晶屏及触摸驱动可用于工业控制、消费电子与物联网设备的界面开发。压缩包共1172个文件约71.44MB以hpp、h、cpp、c等源码文件为主配合d、o、crf等编译中间产物以及a、lib静态库、png图片资源、uvprojx与uvoptx工程文件、ioc配置文件和hex烧录文件完整保留了从CubeMX初始化到TouchGFX界面渲染的工程结构。已有2220人学习下载。通过该工程读者可参考时钟与外设配置、HAL层驱动、触摸移植及TouchGFX界面布局与事件处理的实现方式快速搭建可运行的GUI原型并在此基础上继续调试与优化自己的项目。1. 拿到一块 H743 板子怎么把 TouchGFX 跑出丝滑感手里有块 STM32H743IIT6 的板子屏幕也点得亮但一到 TouchGFX 就卡在“怎么把 CubeMX 生成的工程和 TouchGFX Designer 接起来”这一步——这大概是很多做嵌入式 UI 的开发者都遇到过的场景。这份正点原子 STM32H743IIT6 的 CubeMX TouchGFX 工程解决的就是这件事它把时钟树、SDRAM、LTDC、DMA2D、FMC 这些和显示相关的底层配置全部在 CubeMX 里配好再挂上 TouchGFX 的中间件让你打开就能编译、烧录就能看到界面动起来。适合两类人一是刚拿到 H743 开发板、想快速验证屏幕和触摸的初学者二是已经在用 F4/F7 跑 TouchGFX、想迁移到 H7 平台看看性能提升的老手。H743 的 480MHz 主频加 Chrom-ART 加速器跑 800×480 的界面基本是降维打击但前提是底层得配对。2. 工程架构拆解从 CubeMX 配置到 TouchGFX 中间件2.1 整体分层与数据流向这个工程的结构可以按“硬件抽象层 → 中间件层 → 应用层”来理解。最底下是 CubeMX 生成的 HAL 初始化代码负责把 FMC、LTDC、DMA2D、I2C触摸芯片这些外设配起来中间是 TouchGFX 的中间件它通过TouchGFXHAL类接管了 LTDC 的图层刷新和 DMA2D 的加速填充最上面是 TouchGFX Designer 生成的界面代码包括 Screen、Presenter、View 三层。数据流向是这样的触摸中断触发后I2C 读取坐标通过OSWrappers把事件塞进 TouchGFX 的消息队列TouchGFX 引擎在后台任务里处理事件、更新模型然后调用TouchGFXHAL::flushFrameBuffer()把脏矩形区域通过 DMA2D 搬到 LTDC 的显存地址。整个过程 CPU 只负责逻辑像素搬运全交给 DMA2D这就是 H7 跑 TouchGFX 比 F4 流畅的根本原因。2.2 CubeMX 里必须配对的几个关键项打开.ioc文件重点看这几处配置少一个 TouchGFX 都跑不起来时钟树H743 的 LTDC 时钟来自 PLL3通常配到 25~33MHz 左右具体看屏幕手册的像素时钟要求。SDRAM 时钟来自 FMCH743 的 FMC 时钟可以跑到 100MHz 以上但 SDRAM 芯片如果速度不够就得降频。FMC 配置正点原子的板子一般挂的是 W9825G6KH 或类似型号的 SDRAM32 位带宽地址映射要按芯片手册填。这里最容易翻车的是时序参数CAS latency、tRCD、tWR 这些填错屏幕会花屏或者干脆不亮。LTDC 配置图层数量、像素格式RGB565 还是 ARGB8888、显存起始地址指向 SDRAM 里的缓冲区、行中断和寄存器重载中断要打开。DMA2D模式选“Memory-to-Memory with PFC”或者直接用 TouchGFX 的默认配置它会在初始化时自己接管。FreeRTOSTouchGFX 需要一个任务来跑引擎主循环CubeMX 里把 FreeRTOS 使能给 TouchGFX 任务分配足够的栈建议 4096 字以上优先级设成普通即可。2.3 TouchGFX 中间件的接入点CubeMX 里勾选 TouchGFX 中间件后它会生成几个关键文件TouchGFXHAL.cpp、TouchGFXGeneratedHAL.cpp、OSWrappers.cpp。其中TouchGFXHAL是你需要改的地方比如屏幕分辨率、显存地址、触摸驱动对接。// TouchGFXHAL.cpp 中初始化显存和图层 void TouchGFXHAL::initialize() { // 调用父类初始化设置分辨率 TouchGFXGeneratedHAL::initialize(); // 设置显存地址指向 SDRAM 中分配的缓冲区 // 注意这个地址要和 LTDC 图层配置里的地址一致 setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC00BB800, (void*)0); // 使能 DMA2D 加速H7 上必须开否则刷新率上不去 setDMAToDMATransferFunction(...); }这段代码里setFrameBufferStartAddresses的三个参数分别是前景层、背景层和第三层的显存地址。如果你的界面只用了一个图层后两个可以传 0。地址0xC0000000是 SDRAM 映射到 FMC 后的基地址具体值取决于 CubeMX 里 FMC 的 Bank 配置。2.4 触摸驱动的对接方式正点原子的屏幕一般配 GT9147 或 FT5206 触摸芯片走 I2C 接口。TouchGFX 不直接读 I2C而是通过一个“触摸事件队列”来接收坐标。你需要在 I2C 中断或轮询任务里读取坐标然后调用OSWrappers::signalTouchEvent()把事件推给 TouchGFX。// 在触摸扫描任务中调用 void TouchTask(void *argument) { TouchPoint tp; for(;;) { if (GT9147_Scan(tp)) // 自定义的触摸扫描函数 { // 把坐标写入 TouchGFX 的全局变量 // 注意坐标原点在左上角和屏幕像素坐标一致 OSWrappers::setTouchCoordinates(tp.x, tp.y); OSWrappers::signalTouchEvent(); } osDelay(10); // 10ms 扫描一次够用了 } }这里的关键是setTouchCoordinates和signalTouchEvent必须成对调用只设坐标不发信号TouchGFX 不会处理只发信号不设坐标它会用上一次的旧坐标。另外扫描周期别设太短10ms 对应 100Hz 采样率已经超过大多数触摸芯片的上报率了再快也是浪费 CPU。3. 从零跑通编译、烧录、调试的完整链路3.1 工具链准备与工程导入这个工程默认是 STM32CubeIDE 的工程结构但也可以用 Keil MDK 或 IAR 打开。如果你用 CubeIDE直接File → Open Projects from File System选工程根目录即可如果用 Keil需要先安装 STM32H7 的 Device Family Pack然后打开MDK-ARM目录下的.uvprojx文件。工具链版本建议CubeIDE 1.9 以上CubeMX 6.5 以上TouchGFX Designer 4.20 以上。版本不匹配时TouchGFX 生成的代码可能和中间件对不上编译会报一堆undefined reference。我一般会先看工程根目录下的.mxproject文件里面记录了生成时用的 CubeMX 版本照着装同版本最稳。3.2 编译顺序与常见报错处理TouchGFX 工程的编译顺序有讲究先编译 TouchGFX 的静态库Middlewares/ST/TouchGFX/touchgfx_core再编译应用层代码。CubeIDE 里一般已经配好了依赖关系但如果你手动改过目录结构可能会遇到链接错误。常见的编译报错及处理region RAM overflowedTouchGFX 的显存和堆栈都放在内部 RAM 里了但 H743 的内部 RAM 不够放两块 800×480 的 RGB565 缓冲区。解决办法是把显存地址改到 SDRAM在链接脚本里把TouchGFX_Framebuffer段定位到0xC0000000。undefined reference to osMessageQueueNewFreeRTOS 的 CMSIS-RTOS v2 封装没使能在 CubeMX 里把 FreeRTOS 的接口版本改成 CMSIS_V2。TouchGFXHAL.cpp: No such fileTouchGFX 中间件没勾选回 CubeMX 里补上再重新生成。3.3 烧录与首次上电检查烧录用 ST-Link 或 J-Link 都行H743 的 SWD 接口在正点原子板子上是标准 20 针。烧录前确认 BOOT0 跳线在 0 位置从 Flash 启动否则程序跑不起来。上电后如果屏幕不亮按这个顺序排查先量背光电压一般是 3.3V 或 5V再看 LTDC 的像素时钟有没有输出用示波器量 LTDC_CLK 引脚最后检查 SDRAM 是否初始化成功。SDRAM 初始化失败的话LTDC 读不到显存数据屏幕会一直白屏或花屏。可以在main()里加一句 SDRAM 读写测试写一个值再读回来对不上就是 FMC 时序配错了。3.4 用 TouchGFX Designer 验证界面刷新工程跑起来后用 TouchGFX Designer 打开TouchGFX/MyApplication.touchgfx文件随便拖一个 Box 控件上去设成红色然后点“Generate Code”再编译烧录。如果屏幕上出现红色方块说明整条链路通了。这时候可以测一下刷新率在 Designer 里加一个Performance计数器或者自己在flushFrameBuffer里翻转一个 GPIO用示波器量频率。800×480 的屏幕DMA2D 全屏填充大概在 2~3ms加上 LTDC 的扫描时间整体刷新率能到 30fps 以上。如果只有几帧检查 DMA2D 是否真的使能了以及 SDRAM 的带宽是否够。4. 避坑与排查H743 跑 TouchGFX 最容易翻车的几个点4.1 SDRAM 时序配错导致花屏现象屏幕能亮但显示内容有雪花、条纹或者颜色错位。原因FMC 的 SDRAM 时序参数和实际芯片不匹配最常见的是 CAS latency 设成了 3 但芯片只支持 2或者 tRCD/tWR 设得太小。解决查 SDRAM 芯片手册的时序表把FMC_SDRAM_TIMING里的TMRD、TXSR、TRAS、TRC、TWR、TRP、TRCD全部按手册最小值再放宽 10% 填。正点原子的 W9825G6KH 在 100MHz 下CAS2、TRCD2、TRP2 是稳的。4.2 显存地址和 LTDC 图层地址不一致现象TouchGFX 初始化后屏幕全黑但背光亮。原因TouchGFXHAL::initialize()里设置的显存地址和 CubeMX 里 LTDC 图层配置的地址不是同一个LTDC 从错误的地址读数据读到的全是 0。解决在 CubeMX 的 LTDC 配置里看Layer 0 Address把这个值抄到setFrameBufferStartAddresses的第一个参数里。两个地址必须一模一样差一个字节都不行。4.3 FreeRTOS 任务栈溢出现象界面跑几秒后死机或者触摸没反应调试器里看到 HardFault。原因TouchGFX 引擎任务栈给太小了默认可能是 1024 字跑复杂界面时不够用。解决在 CubeMX 的 FreeRTOS 配置里把 TouchGFX 任务的栈改成 4096 字16KB如果界面控件特别多给到 8192 字。另外把configCHECK_FOR_STACK_OVERFLOW设成 2溢出时能触发钩子函数方便定位。4.4 DMA2D 和 LTDC 抢 SDRAM 带宽现象界面刷新时偶尔撕裂或者触摸响应变慢。原因DMA2D 在往显存写数据的同时LTDC 在从显存读数据两者都走 FMC 总线SDRAM 带宽被占满。解决把 LTDC 的图层像素格式从 ARGB8888 改成 RGB565带宽直接减半。如果还不够降低 LTDC 的像素时钟或者把 DMA2D 的传输拆成小块让出总线给 LTDC。4.5 TouchGFX Designer 生成代码覆盖手写代码现象在TouchGFXHAL.cpp里改的代码重新生成后没了。原因TouchGFX Designer 只保护TouchGFXGeneratedHAL.cpp和TouchGFXHAL.cpp里的特定区域如果你改到了生成区域下次生成就被覆盖。解决所有自定义代码都写在TouchGFXHAL.cpp的// USER CODE BEGIN和// USER CODE END之间Designer 不会动这两个标记之间的内容。触摸驱动、显存地址设置都放这里。5. 二次开发从能跑到好用的改造思路5.1 把触摸从轮询改成中断默认工程里触摸是 10ms 轮询一次CPU 占用虽然不高但响应有最多 10ms 的延迟。改成中断方式后触摸芯片一有数据就触发 EXTI在中断里读 I2C 再推事件响应能压到 2ms 以内。// 在 EXTI 中断回调里处理触摸 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin TOUCH_INT_Pin) { // 在中断里只发信号实际读取放到任务里做 // 因为 I2C 读取可能阻塞中断里不能等 BaseType_t xHigherPriorityTaskWoken pdFALSE; vTaskNotifyGiveFromISR(TouchTaskHandle, xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } }这里用vTaskNotifyGiveFromISR而不是直接读 I2C是因为 I2C 传输在中断上下文里可能死锁。触摸任务收到通知后再去读坐标读完推给 TouchGFX。这样既保证了响应速度又不会在中断里做耗时操作。5.2 用双缓冲加脏矩形降低刷新开销TouchGFX 默认是单缓冲加脏矩形如果界面有动画单缓冲会撕裂。改成双缓冲后TouchGFX 在后台缓冲画完再切换撕裂消失但显存占用翻倍。H743 的 SDRAM 一般有 32MB放两块 800×480 的 RGB565 缓冲每块 768KB绰绰有余。// 在 TouchGFXHAL::initialize() 里设置双缓冲 setFrameBufferStartAddresses((void*)0xC0000000, // 缓冲0 (void*)0xC00C0000, // 缓冲1 (void*)0); // 第三层不用 // 使能双缓冲 setDoubleBuffering(true);双缓冲的代价是每次刷新要切换 LTDC 的图层地址这个操作在flushFrameBuffer里由 TouchGFX 自动完成你只需要把两个缓冲地址传对就行。注意两个地址之间要留够空间800×480×2 字节 768KB所以第二个地址至少是第一个加 0xC0000。5.3 把界面资源放到外部 FlashTouchGFX 的图片和字体默认编译进内部 FlashH743 的 2MB Flash 看着不小但界面一复杂就不够用了。正点原子的板子一般带 W25Q256 之类的 SPI Flash可以把资源外置。改造步骤在 TouchGFX Designer 里把资源存储位置改成“External”生成代码后在TouchGFXHAL::initialize()里实现TouchGFXGeneratedHAL::getExternalFlashAddress()的读取函数通过 QSPI 或 SPI 读 Flash 数据。这样内部 Flash 只放代码资源全放外部2MB 能省出一大半。5.4 验证改造效果的方法每次改完底层配置别急着写复杂界面先用一个最简单的测试界面验证一个全屏红色 Box 一个计数器文本。红色 Box 用来确认 LTDC 和 DMA2D 正常计数器用来确认 TouchGFX 引擎在跑。如果红色能显示、计数器在动说明底层没问题可以往上加控件了。我自己的习惯是每次改完 CubeMX 配置重新生成代码后先编译烧录这个最小测试界面通过了再合并到正式工程里。这样出问题时能快速定位是底层配置的锅还是应用代码的锅。从那以后我每次动 FMC 或 LTDC 配置都强制走一遍这个最小验证流程省了很多来回折腾的时间。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑