3. 外部存储设备选型:SPI Flash、SD 卡、NAND Flash 对比,文件系统选择 (FATFS, LittleFS)
做 LVGL 外部存储加载图片,第一个绕不开的问题就是:图片放哪儿?
我见过不少新手,在 PC 上把 LVGL 跑得飞起,一上硬件就卡成幻灯片。为什么?因为图片数据还在内部 Flash 里挤着,或者用了个慢得要命的存储方案。
说白了,LVGL 的图片解码和渲染,本质上是「数据搬运工」。存储设备的读取速度、文件系统的开销,直接决定了你的 UI 能不能跑满 60fps。
这一章,咱们就把市面上主流的三种外部存储设备掰开揉碎,再聊聊文件系统怎么选。
3.1 三大存储设备:核心参数对比
先看一张表,把它们的底裤扒干净。
| 参数项 | SPI Flash (如 W25Q64) | SD 卡 (SPI/SDIO 模式) | NAND Flash (如 MT29F) |
|---|---|---|---|
| 典型容量 | 1MB ~ 256MB | 128MB ~ 32GB+ | 128MB ~ 8GB+ |
| 读取速度 (SPI 40MHz) | ~5 MB/s (连续读) | ~2 MB/s (SPI 模式) ~20 MB/s (SDIO 4bit) |
~15 MB/s (连续读) |
| 写入速度 | ~0.5 MB/s (页编程) | ~1 MB/s (SPI 模式) | ~3 MB/s (页编程) |
| 擦除方式 | 扇区擦除 (4KB) | 无显式擦除 (FTL 管理) | 块擦除 (128KB+) |
| 随机读取 | 快 (按地址直接读) | 慢 (文件系统+FTL 开销) | 较慢 (需地址映射) |
| 寿命 (擦写次数) | 10万次 (典型) | 取决于 SD 卡主控 | 1万~10万次 (MLC/SLC) |
| 引脚数 | 8 脚 (SOIC-8) | 9 脚 (SD 卡座) | 48 脚 (TSOP-48) |
| 硬件复杂度 | 低 (SPI 总线) | 中 (SPI/SDIO + 卡座) | 高 (需 ECC + 坏块管理) |
关键结论:对于 LVGL 图片加载场景,连续读取速度和随机读取延迟是核心指标。写入速度反而不重要——图片通常是预烧录的。
3.2 SPI Flash:小容量场景的「甜点」
我个人最喜欢 SPI Flash。为什么?因为它简单、可靠、便宜。
如果你做的产品是智能家居面板、小尺寸彩屏设备,图片总量不超过 64MB,SPI Flash 几乎是唯一正确的选择。
- 优势:硬件接口极其简单,4 根线(CS、SCK、MOSI、MISO)搞定。MCU 几乎都有 SPI 外设,驱动代码网上大把。
- 劣势:容量天花板低。市面上最大也就 256MB,再大就得用 NAND 了。
- 读取速度:40MHz SPI 时钟下,连续读能跑到 5MB/s 左右。对于 320x240 的 RGB565 图片(150KB),加载时间约 30ms,够用。
我的经验:用 SPI Flash 时,记得开启 Quad SPI (QSPI) 模式。同样是 40MHz 时钟,QSPI 能跑到 20MB/s,速度翻 4 倍。很多 MCU 都支持,别浪费这个功能。
3.3 SD 卡:大容量场景的「万金油」
如果你的产品需要存几百张高清图片,或者要支持用户通过 USB 拷贝图片,SD 卡是首选。
但 SD 卡有个坑——随机读取性能很差。
LVGL 加载图片时,经常需要跳转到文件的不同位置读取数据(比如解码 JPEG 时需要读取 Huffman 表)。SD 卡的 FTL(Flash Translation Layer)在处理随机小数据块时,延迟可能高达几十毫秒。
- SPI 模式 vs SDIO 模式:SPI 模式速度慢(~2MB/s),但几乎所有 MCU 都支持。SDIO 4bit 模式速度快(~20MB/s),但需要 MCU 有 SDIO 外设,且布线要小心。
- 文件系统:SD 卡出厂通常是 FAT32 格式。FAT32 在读取大文件时效率不错,但目录项多时,查找文件会变慢。
避坑指南:我曾经在一个项目里用 SD 卡存 200 张 800x480 的图片,结果 UI 切换时卡顿明显。后来发现是 SD 卡在读取每个文件时,FAT 表查找花了大量时间。解决方案:把图片打包成一个 .bin 文件,用偏移量直接读取,跳过文件系统开销。
3.4 NAND Flash:高性能场景的「重武器」
NAND Flash 通常用在高端产品上,比如工业平板、车载仪表。它的容量大、连续读取速度快,但代价是硬件复杂度高。
- 坏块管理:NAND Flash 出厂就有坏块,使用过程中还会产生新坏块。你必须实现坏块管理算法,或者用现成的软件包(如 UFFS、YAFFS)。
- ECC 纠错:NAND Flash 的存储单元会随着擦写次数增加而出现位翻转。你需要硬件 ECC 或软件 ECC 来保证数据正确性。
- 读取速度:连续读取能到 15MB/s 以上,对于大尺寸图片(如 1024x600 的 JPEG)加载非常有利。
我的建议:除非你的产品图片总量超过 256MB,或者对读取速度有极致要求,否则别碰 NAND Flash。它的开发成本太高,不值得在小项目上折腾。
3.5 文件系统选择:FATFS vs LittleFS
存储设备选好了,接下来就是文件系统。文件系统决定了你怎么组织、读取图片文件。
| 对比项 | FATFS | LittleFS |
|---|---|---|
| 设计目标 | 兼容 Windows/Linux 文件系统 | 嵌入式小容量、掉电安全 |
| 掉电保护 | 弱 (需额外日志/事务) | 强 (内建掉电安全) |
| 磨损均衡 | 无 | 有 (动态磨损均衡) |
| RAM 占用 | ~2KB (最小配置) | ~4KB (典型配置) |
| ROM 占用 | ~10KB | ~8KB |
| 最大文件大小 | 4GB (FAT32) | 取决于配置 (通常 < 4GB) |
| 适用场景 | SD 卡、大容量存储 | SPI Flash、小容量 NOR Flash |
3.6 我的推荐组合
做了这么多项目,我总结了一套「懒人选择法」:
- 图片总量 < 64MB,用 SPI Flash + LittleFS。 LittleFS 的掉电安全和磨损均衡,让 SPI Flash 的寿命大大延长。而且 LittleFS 在读取小文件时速度很快。
- 图片总量 > 64MB,用 SD 卡 + FATFS。 SD 卡容量大,FATFS 兼容性好。但记得把图片打包成
.bin文件,或者用 LVGL 的lv_fs接口做缓存。 - 工业级产品,用 NAND Flash + 专用文件系统。 比如 UFFS 或 YAFFS。别用 FATFS 直接怼 NAND,会出大问题。
小技巧:不管你用哪种组合,都建议在 LVGL 初始化时,用 lv_fs_set_ready_cb() 注册一个回调,检测存储设备是否就绪。如果 SD 卡没插,或者 SPI Flash 初始化失败,LVGL 可以优雅地降级显示默认图片。
3.7 知识结构图:存储选型决策流程
下面这张图,帮你快速定位自己的需求。
3.8 小结
存储选型没有银弹。你得根据图片总量、读取速度要求、硬件成本、开发周期来权衡。
我个人最常用的组合是 SPI Flash + LittleFS,因为 90% 的嵌入式 UI 产品,图片总量都在 64MB 以内。这个组合开发快、成本低、可靠性高。
如果你非要用 SD 卡,记得做好文件系统缓存和图片打包,不然 LVGL 的刷新率会很难看。