硬件基础:SD卡接口协议(SPI/SDIO)选型与对比
做嵌入式UI,尤其是用LVGL加载外部图片时,SD卡几乎是绕不开的存储介质。但SD卡怎么跟单片机通信?这就涉及到两种接口协议:SPI和SDIO。很多初学者一上来就纠结选哪个,其实没那么玄乎。
我个人习惯,先把两种协议的本质搞清楚,再根据项目需求做取舍。今天咱们就掰开揉碎聊聊这个。
SD卡物理接口长什么样?
先看一张标准SD卡的引脚定义。SD卡有9个引脚,但实际用到的取决于你选哪种模式。
| 引脚编号 | SDIO模式名称 | SPI模式名称 |
|---|---|---|
| 1 | CD/DAT3(卡检测/数据线3) | CS(片选) |
| 2 | CMD(命令线) | MOSI(主出从入) |
| 3 | VSS1(地) | VSS1(地) |
| 4 | VDD(电源) | VDD(电源) |
| 5 | CLK(时钟) | SCLK(时钟) |
| 6 | VSS2(地) | VSS2(地) |
| 7 | DAT0(数据线0) | MISO(主入从出) |
| 8 | DAT1(数据线1) | 保留/未用 |
| 9 | DAT2(数据线2) | 保留/未用 |
看到没?SPI模式只用了6个引脚,SDIO模式则用满了9个。这就是性能差异的根源——数据通道宽度不同。
SPI模式:简单可靠,但慢
SPI模式说白了就是把SD卡当成一个SPI从设备来操作。你发命令,它回数据,一主一从,全双工。
优点很明显:
- 几乎所有MCU都自带SPI外设,硬件门槛极低
- 引脚占用少,就6根线(CS、MOSI、MISO、SCLK、VDD、GND)
- 驱动代码成熟,网上大把现成的
- 适合低速、低复杂度场景
缺点也扎心:
- 半双工?不,SPI是全双工,但SD卡SPI协议本身是命令-响应模式,实际吞吐量受限
- 单数据线传输,理论极限也就20-25MB/s(实际往往更低)
- 不支持卡的热插拔检测(需要额外引脚或轮询)
我的经验: 如果你只是用LVGL加载一些几百KB的图标或背景图,SPI模式完全够用。我曾经在一个STM32F103项目上,用SPI驱动SD卡,配合FatFS,加载一张800x480的JPEG图片(约150KB),耗时大概200ms。用户基本感觉不到延迟。
SDIO模式:高速通道,但复杂
SDIO是SD卡的原生协议。它用4条数据线并行传输,速度直接翻倍。
优势:
- 4位并行传输,理论速度可达100MB/s以上(取决于SD卡等级和时钟频率)
- 支持CMD线独立传输命令,数据线专用于数据,效率更高
- 原生支持卡检测、写保护等特性
- 适合大文件、高帧率场景(比如LVGL播放视频或连续加载高清图片)
劣势:
- 需要MCU有SDIO控制器,不是所有芯片都带
- 引脚占用多,至少9根线,布线麻烦
- 驱动复杂,初始化流程比SPI繁琐得多
- 对PCB走线长度、阻抗匹配有要求,高频下容易出问题
避坑指南: 我曾经在一个项目上,用SDIO驱动SD卡,结果发现读出来的数据偶尔会错位。查了两天,最后发现是PCB上SDIO数据线之间串扰太大,时钟线也没做包地处理。后来把线间距拉开,时钟线单独包地,问题才解决。SDIO高频布线,真不能马虎。
SPI vs SDIO:一张表说清楚
| 对比维度 | SPI模式 | SDIO模式 |
|---|---|---|
| 引脚数量 | 6(含电源地) | 9(含电源地) |
| 数据宽度 | 1位 | 1位或4位 |
| 理论最大速度 | ~25 MB/s(25MHz时钟) | ~100 MB/s(50MHz时钟,4位模式) |
| 硬件要求 | 通用SPI外设 | 专用SDIO控制器 |
| 驱动复杂度 | 低 | 高 |
| 热插拔支持 | 需额外引脚 | 原生支持 |
| 典型应用 | 低功耗、低成本、低速场景 | 高性能、大文件、实时性要求高 |
怎么选?我的决策框架
说实话,没有绝对的好坏,只有合不合适。我一般按下面这个思路来选:
- 先看MCU资源: 芯片有没有SDIO?没有的话,直接SPI,别纠结。
- 再看图片大小和数量: 如果LVGL要加载的图片单张超过1MB,或者需要同时缓存多张高清图,建议上SDIO。否则SPI够用。
- 考虑实时性: 如果你的UI有动画或视频播放需求,SDIO是必须的。SPI的带宽撑不住。
- 评估开发周期: 项目赶时间?用SPI,驱动现成,调通快。时间充裕?可以上SDIO,性能更好。
- 别忘了功耗: SPI模式功耗更低,适合电池供电设备。SDIO 4位模式全速运行时,电流会大不少。
一句话总结: 做LVGL图片加载,如果MCU支持SDIO且项目对性能有要求,优先选SDIO;如果MCU资源有限或项目周期紧,SPI是稳妥的选择。我自己的项目里,大概七成用SDIO,三成用SPI。
一张图看懂选型逻辑
下面这张SVG图,把整个决策流程画出来了,方便你对照自己的项目情况做判断。
实际项目中的坑与经验
最后分享几个我踩过的坑,希望能帮你少走弯路。
坑1:SPI时钟极性搞反
我曾经在移植SD卡SPI驱动时,卡死活初始化不成功。折腾了半天,发现是SPI的时钟极性(CPOL)和相位(CPHA)配置错了。SD卡SPI模式要求CPOL=0、CPHA=0(模式0),但我的MCU默认是模式3。改过来就好了。
我曾经在移植SD卡SPI驱动时,卡死活初始化不成功。折腾了半天,发现是SPI的时钟极性(CPOL)和相位(CPHA)配置错了。SD卡SPI模式要求CPOL=0、CPHA=0(模式0),但我的MCU默认是模式3。改过来就好了。
坑2:SDIO的4位模式不稳定
有个项目用SDIO 4位模式,读大文件时偶尔会卡死。后来发现是电源纹波太大,导致SD卡内部逻辑紊乱。在SD卡电源引脚旁边加了个100μF电解电容+0.1μF瓷片电容,问题解决。SD卡对电源质量其实挺敏感的。
有个项目用SDIO 4位模式,读大文件时偶尔会卡死。后来发现是电源纹波太大,导致SD卡内部逻辑紊乱。在SD卡电源引脚旁边加了个100μF电解电容+0.1μF瓷片电容,问题解决。SD卡对电源质量其实挺敏感的。
坑3:文件系统挂载失败
这个跟接口协议无关,但经常遇到。SD卡在电脑上格式化后,分区表可能是MBR或GPT,有些文件系统库只支持MBR。我习惯在电脑上格式化时选“FAT32”并勾选“MBR分区表”,这样兼容性最好。
这个跟接口协议无关,但经常遇到。SD卡在电脑上格式化后,分区表可能是MBR或GPT,有些文件系统库只支持MBR。我习惯在电脑上格式化时选“FAT32”并勾选“MBR分区表”,这样兼容性最好。