2、硬件平台选型:MCU与MPU的选择策略、显示控制器(TFT/OLED)接口规范、帧缓冲与显存设计原则、DMA2D与GPU加速

做嵌入式GUI,第一步就是选硬件。这一步要是走偏了,后面再怎么优化也救不回来。我见过太多项目,芯片选得太弱,界面卡成PPT;选得太强,成本又压不住。说白了,这就是个平衡的艺术。

2.1 MCU与MPU:你到底需要谁?

很多人问我:「MCU和MPU到底怎么分?」其实没那么玄乎。我的判断标准很简单——看你的UI复杂度。

MCU(微控制器),适合做轻量级界面。比如家电面板、仪表盘、小尺寸彩屏。这类场景下,RTOS + 轻量级GUI库(像LVGL、uGFX)就够用了。我做过一个温控器项目,STM32F429 + 480×272的TFT,跑LVGL,帧率稳稳的。

MPU(微处理器),适合跑复杂界面。比如带动画、视频播放、多窗口交互的场合。这时候你需要Linux + Qt或Flutter。我有个朋友做医疗监护仪,界面要同时显示波形、参数、报警动画,MCU根本扛不住,最后换了i.MX6ULL才搞定。

我的选型口诀:

  • 界面简单、实时性高 → MCU + RTOS
  • 界面复杂、需要生态 → MPU + Linux
  • 两者之间?看看有没有硬件加速(DMA2D、GPU)

嗯,这里要注意一个坑:别以为MCU就做不了好UI。现在很多MCU内置了TFT控制器和DMA2D,跑个60帧的动画完全没问题。关键看你会不会用。

2.2 显示控制器接口规范

选好芯片,接下来就是连屏幕。接口这块,我踩过的坑比走过的路还多。

TFT接口:MCU接口 vs RGB接口

接口类型 引脚数 速度 适用场景
MCU 8080/6800 8/16/18 较慢 小尺寸(< 5寸),低分辨率
RGB并行 16/18/24 大尺寸,高分辨率
SPI 4-6 最慢 小屏,低刷新率
MIPI DSI 2-4对差分 极快 手机屏,高清大屏

我个人习惯,3.5寸以下用MCU接口,省引脚、布线简单。4.3寸以上用RGB接口,不然刷新率上不去。我曾经在一个7寸屏项目上用了MCU接口,结果刷一帧要50ms,动画根本没法看。后来改成RGB接口,配合DMA2D,直接降到8ms。

OLED接口:I2C vs SPI

OLED屏通常分辨率不高(128×64、128×32之类),接口也简单。我建议:

  • I2C:引脚少(2根),适合小数据量、低刷新率。比如显示静态文字、图标。
  • SPI:速度快,适合需要局部刷新的场合。比如做动态波形显示。

避坑指南:OLED屏的驱动芯片(如SSD1306)内部自带GRAM,你只需要往里面写数据就行。但要注意,它的刷新率有限,别指望用它做60fps的动画。我曾经试过用SPI刷OLED做小游戏,结果画面撕裂严重——后来才明白,OLED的帧率瓶颈在驱动芯片本身,不是接口速度。

2.3 帧缓冲与显存设计原则

帧缓冲,说白了就是一块内存区域,存着屏幕上每个像素的颜色值。显存设计得好不好,直接决定你的UI能不能跑起来。

原则一:显存大小 = 分辨率 × 色深

举个例子:480×272分辨率,16位色(RGB565),显存 = 480 × 272 × 2 = 261KB。嗯,看起来不大?但如果你用双缓冲,就要翻倍到522KB。很多MCU内部SRAM才256KB,根本放不下。

注意:别以为外部SDRAM就能随便用。SDRAM的访问延迟比内部SRAM高很多,频繁刷屏会导致CPU被拖死。我建议:

  • 内部SRAM放帧缓冲 → 用于当前显示帧
  • 外部SDRAM放显存 → 用于离屏渲染、资源存储
  • 如果MCU有DMA2D,让它直接操作外部SDRAM

原则二:双缓冲 vs 单缓冲

单缓冲简单,但会有撕裂。双缓冲能解决撕裂,但内存翻倍。我的经验是:

  • 静态界面(菜单、设置页)→ 单缓冲就够了
  • 动态界面(动画、视频、滑动)→ 必须双缓冲
  • 如果内存实在不够,可以用局部刷新 + 行缓冲

原则三:显存对齐

这个很多人会忽略。DMA2D和GPU通常要求显存地址按32字节对齐。不对齐的话,性能直接腰斩。我习惯在分配显存时,用 __attribute__((aligned(32))) 或者手动做地址对齐。

// 显存对齐示例(C语言)
#define FRAME_BUFFER_SIZE  (480 * 272 * 2)  // RGB565
static uint8_t fb[FRAME_BUFFER_SIZE] __attribute__((aligned(32)));

// 或者手动对齐
static uint8_t fb_raw[FRAME_BUFFER_SIZE + 32];
static uint8_t *fb = (uint8_t *)(((uint32_t)fb_raw + 31) & ~31);

2.4 DMA2D与GPU加速

说到加速,DMA2D是MCU界的「神兵利器」。它本质上是个2D图形DMA,能独立完成图像拷贝、颜色填充、像素格式转换、Alpha混合等操作。CPU只需要发个指令,剩下的DMA2D自己搞定。

DMA2D能干的事:

  • 快速清屏(比CPU memset快5-10倍)
  • 图像叠加(比如把图标合成到背景上)
  • 颜色格式转换(ARGB8888 → RGB565)
  • 矩形区域填充

我做过一个对比测试:用CPU逐像素画一个480×272的矩形,耗时约12ms;用DMA2D,只要1.2ms。差距就是这么明显。

DMA2D使用要点:

  1. 初始化时配置好时钟,DMA2D需要独立的时钟源
  2. 操作前检查DMA2D是否忙(读寄存器状态位)
  3. 用中断或轮询等待传输完成
  4. 注意源地址和目标地址不能重叠(除非做内存拷贝)

GPU加速:什么时候需要?

如果你用的是MPU(比如i.MX系列、全志、瑞芯微),通常内置了GPU。GPU能处理更复杂的图形操作,比如:

  • 3D变换(旋转、缩放)
  • 贝塞尔曲线渲染
  • 多图层合成
  • 视频解码叠加

但GPU也有代价:驱动复杂、功耗高、调试困难。我建议:

  • 如果你的UI只是2D平面,DMA2D完全够用
  • 如果需要3D效果或复杂动画,再考虑GPU
  • 别为了「炫技」而用GPU,简单才是王道

我的经验:在STM32F769上做智能家居面板,我用DMA2D实现了60fps的滑动动画,效果跟手机差不多。但同样的代码移植到没有DMA2D的芯片上,帧率直接掉到15fps。所以选型时,DMA2D比CPU主频更重要

最后说一句:硬件选型没有银弹。你得多问自己几个问题:屏幕多大?刷新率要求多少?动画复杂吗?成本预算多少?把这些想清楚了,选型自然就清晰了。