1、课程导论:为什么需要外部存储加载图片?BMP格式简介与DMA2D硬件加速原理
1.1 嵌入式UI的“内存之痛”
做嵌入式GUI开发,尤其是用LVGL做复杂界面时,你很快会遇到一个现实问题——内存不够用。
我刚开始做智能家居面板项目时,觉得STM32F429的256KB SRAM挺大的。结果放了几张320×240的图片做背景,再跑个LVGL控件,系统直接崩了。你想想看,一张24位深度的320×240 BMP图片,未经压缩就要占用320×240×3 ≈ 225KB。MCU内部SRAM才多大?
所以,把图片资源放在外部存储,按需加载到内存,是嵌入式UI的必然选择。
1.2 为什么选择BMP格式?
LVGL支持PNG、JPG、BMP等多种图片格式。我个人习惯在开发阶段大量使用BMP,原因很简单:
- 结构简单:BMP文件头+信息头+像素数据,没有复杂的压缩算法,解析起来非常直接。
- 像素数据对齐:BMP的像素排列与显存格式高度相似,方便做DMA2D加速。
- 调试友好:用十六进制编辑器打开BMP文件,你能直接看到像素值,排查问题很方便。
当然,BMP的缺点是文件体积大。但配合外部存储的大容量,这个缺点可以被接受。
1.3 BMP文件结构速览
BMP文件由四部分组成。我画了一张图帮你快速理解:
解析BMP时,最关键的是从文件头读出宽度、高度、位深度,然后定位到像素数据的起始位置。嗯,这里要注意:BMP的像素数据是从最后一行开始存储的(倒序),读取时别搞反了。
1.4 色彩格式转换:躲不开的坑
BMP存储的是BGR格式,而LVGL的显示缓冲区通常是RGB565或RGB888。这就意味着,每加载一张图片,你都得做一次色彩转换。
我曾经在项目里用纯软件做BGR→RGB565的转换,一张800×480的图片,转换耗时接近200ms。界面切换时明显卡顿,用户体验很差。
| 转换方式 | 800×480图片耗时 | CPU占用 | 适用场景 |
|---|---|---|---|
| 纯软件逐像素转换 | ~180ms | 100% | 小尺寸图片、非实时场景 |
| 优化查表法 | ~80ms | 60% | 中等尺寸、可接受延迟 |
| DMA2D硬件加速 | ~5ms | 0% | 大尺寸图片、实时界面切换 |
1.5 DMA2D硬件加速原理
DMA2D是STM32系列中一个专门做2D图形加速的外设。说白了,它就是一个“像素搬运工+格式转换器”。
它的核心能力有三个:
- 内存到内存拷贝:把外部存储的图片数据搬到内部SRAM或SDRAM。
- 色彩格式转换:在搬运过程中,自动完成BGR→RGB、RGB888→RGB565等转换。
- 像素混合(Alpha Blending):支持透明度混合,适合做图标叠加。
DMA2D的工作流程是这样的:
使用DMA2D时,你只需要配置好源地址(外部存储)、目标地址(显示缓冲区)、数据格式和传输长度,然后启动传输。剩下的交给硬件。
1.6 本章小结
外部存储加载图片,解决了嵌入式UI的内存瓶颈。BMP格式虽然体积大,但结构简单、解析方便,配合DMA2D硬件加速,可以高效完成色彩格式转换。
接下来的课程,我会带你从零开始实现一个完整的BMP解码器,并集成DMA2D加速。你会看到:
- 如何解析BMP文件头,提取关键参数
- 如何配置DMA2D,实现BGR→RGB565的硬件转换
- 如何将解码后的图片数据直接送入LVGL显示
嗯,准备好了吗?我们开始动手。