Qt for MCUs 是轻量级裸机UI引擎,不依赖QObject、STL或OS,需栈/静态内存管理、预编译资源、禁用异常/RTTI,并用专用CMake函数和工具链构建。

Qt for MCUs 本质不是“在 MCU 上跑 Qt”
Qt for MCUs 不是把桌面版 Qt 移植到裸机上,它压根没用 QObject、信号槽、事件循环或 QApplication。它是个轻量级 UI 渲染引擎,C++ 接口只是语法糖,底层不依赖 STL、堆分配或操作系统——所以你不能写 new QPushButton 或调用 QTimer::singleShot。
常见错误现象:undefined reference to 'operator new(unsigned int)' 或启动后黑屏无响应,多半是因为误用了标准 Qt 惯用法。
- 必须关闭 C++ 异常和 RTTI(编译器选项:
-fno-exceptions -fno-rtti) - 所有 UI 元素生命周期由栈或静态内存管理,禁止
new/delete - 资源(字体、图片)必须提前编译进 Flash,不能运行时加载文件
- 不支持
QString,字符串用constexpr char[]或static const char[]
如何配置 Qt Creator 正确生成 MCU 可执行文件
Qt Creator 的 “Qt for MCUs” 构建套件不是选个 Kit 就完事——它实际调用的是 cmake + 专用工具链(如 ARM GCC 10.3+),且项目结构和普通 Qt CMakeLists 完全不同。
使用场景:你在 NXP RT1170 或 STM32H747 上跑 UI,目标是生成 .bin 或 .elf,烧录进 Flash 后直接启动。
立即学习“C++免费学习笔记(深入)”;
- 项目必须用
qt_add_mcus_executable替代add_executable(这是 Qt for MCUs 提供的 CMake 函数) - 必须显式指定平台:
set(CMAKE_MCUS_PLATFORM "rh850" / "stm32h747-disco" / "nxp-mimxrt1170-evk") - 字体需预处理:
qt_generate_font生成二进制资源,再通过qt_add_resource注入 - 调试时禁用优化(
-O0)否则 J-Link 调试符号会丢失,但最终固件必须开-Os
UI 逻辑怎么写才不会崩溃
没有事件循环,就没有“等待用户点击”的自然方式;所有交互靠轮询硬件中断 + 主循环中手动更新状态。所谓“按钮点击”,其实是检测 GPIO 电平变化后,手动调用一个回调函数。
参数差异明显:桌面 Qt 的 clicked() 是异步信号,MCU 版本里对应的是 onClicked() 成员函数,但它只是普通 C++ 函数,必须由你主动调用。
- 主循环结构固定:
while (true) { updateInputs(); ui.update(); render(); },缺一不可 -
ui.update()不自动触发重绘,必须紧接着调用render()(通常绑定到 LCD 刷新中断) - 动画靠帧计数器驱动,不能用
QPropertyAnimation——得自己写if (++frameCount > 30) { progress += 0.02f; } - 触摸坐标需先经校准(
Qul::PlatformInterface::TouchPoint),原始 ADC 值不能直接喂给 UI 层
为什么你的图片显示错位或文字模糊
Qt for MCUs 对图像格式和字体尺寸极其敏感。它不解析 PNG/JPEG,只接受特定打包格式;也不做亚像素渲染,字体大小必须严格匹配资源生成时的设置。
性能影响直接:一张未压缩的 400×240 ARGB8888 图片占 384KB Flash,而 MCU 通常只有 1–2MB 总 Flash。
- 图片必须用
qul_convert_image工具转成.bin,格式限定为RGB565或ARGB8565_Premultiplied - 字体必须用
qul_generate_font处理,字号写死(比如16),运行时不能缩放 - UI 布局单位是像素,但坐标系原点在左上角,且不支持
devicePixelRatio—— 高分屏设备要手动适配 - 启用抗锯齿需额外开启
QUL_RENDER_WITH_ALPHA,但会显著增加 RAM 占用(每行多 2 字节)
最常被忽略的是资源对齐:所有图片/字体二进制块必须按 4 字节对齐,否则 memcpy 读取时触发 HardFault。工具链默认会处理,但如果你手动生成资源,就得自己加 __attribute__((aligned(4)))。











