SD 卡 SPI 模式:用一个 SPI 口读写 SD/TF 卡
更新时间:2026-09-12。本文是「集成电路大类 · 芯片设计」**入门层(beginner)**数字逻辑基础第一百零二篇。SD/TF 卡原生走 SDIO,但规范留了一条「退路」:上电时用特定序列把它切到 SPI 兼容模式,于是任何带 SPI 主机的器件都能读它。它比直接操作 SPI NOR Flash 复杂得多,关键在初始化握手和命令/令牌协议。
本文要回答的问题
- 一张 SDIO 卡怎么被「哄」进 SPI 模式?为什么要先发 74 个时钟?
- CMD0/CMD8/ACMD41 各做什么,怎么判断卡的版本和容量类型?
- 读一个 512 字节块时,卡回的 R1、起始 token、数据、CRC 怎么排列?
- 写块后怎么知道卡还在「忙」?SDHC 的地址为什么和小卡不一样?
- 为什么初始化必须低速、之后才能提速?
一、进入 SPI 模式:上电握手
卡上电时根据上电后第一条命令的电平决定用 SD 模式还是 SPI 模式。标准进入流程:
- 供电与时钟:插入后至少等 1ms,在 /CS 拉高下先给 ≥74 个时钟周期(让卡内部上电、初始化);SPI 用模式 0,初始化速率 100~400kHz;
- CMD0(0x40,参数 0):拉低 /CS 发软件复位命令。这一条必须带正确的 CRC(0x95)使卡识别为合法 SPI 复位;进入 SPI 模式后数据阶段默认不再校验 CRC(可用 CMD59 关);
- CMD8(0x48):询问电压范围,判断是 V2+ 卡还是老 V1 卡;
- ACMD41(先发 CMD55 再发 0x41,参数含 HCS 位):发起初始化并询问是否 SDHC/SDXC(高容量),反复发直到 R1 的 idle(busy) 位清零(卡可能要几百 ms);
- 成功后卡处于 SPI 待命态,可把时钟提到更高(普通卡 ≤25MHz、更高规格按手册)。
这个序列是「状态+重试」的典型控制器状态机,任何一步应答不对就要超时重来。
二、命令与应答格式
- 命令:6 字节 = 1 字节命令码(0x40+命令号,如 CMD17=0x51)+ 4 字节参数 + 1 字节 CRC(CMD0/CMD8 需正确,其余可填 0x01/0xFF);
- R1 应答:1 字节,bit0=idle(1 表示还没就绪)、其它位是复位/参数/地址错误等;发完命令后持续读 MISO,直到读到的字节最高位为 0 即为 R1(之前是 0xFF 填充);
- ACMD 类命令要先发 CMD55 前缀。
三、读单块/多块
寻址以 512 字节块为单位(SDHC/SDXC 直接用块号;老的 SDSC 用字节地址,驱动里要区分 CCS 位)。读单块 CMD17(0x51),卡响应序列:
R1(1B) → 若干 0xFF → 起始 token 0xFE → 512B 数据 → CRC(2B) → 0xFF- 主机发命令、读到合法 R1 后,继续读直到出现数据起始令牌 0xFE;
- 随后正好收 512 字节和 2 字节 CRC(SPI 模式多忽略);
- **CMD18(0x52)**连续读多块,每块都带 token 和 CRC,直到主机发 **CMD12(0x4C)**停止。
实现上用一个接收状态机:发命令→等 R1→等 token→收满 512B→(多块则循环),全程设超时,因为卡未插/接触不良时会一直回 0xFF。
四、写块与忙检测
写单块 CMD24(0x58)/多块 CMD25(0x59):
- 发命令、读 R1;
- 主机发写令牌:单块 0xFE(多块每块前 0xFC,最后发 0xFD 结束);
- 紧接着发 512 字节 + 2 字节伪 CRC(0xFF 0xFF);
- 卡返回一个数据响应令牌(如 xxx0_0101 表示接受),然后进入编程忙状态:把 MISO(DAT0)拉低。
主机轮询 MISO:读到 0x00(或非 0xFF)表示忙、重新读到 0xFF 表示完成,期间不能发下一块。擦除、多块写尤其要按这个「响应令牌+忙等待」协议处理,并加写超时。
五、工程要点
- 初始化必须慢:先 100~400kHz 完成 CMD0/8/ACMD41,再切到高速;/CS 发命令时要保持拉低,命令之间按要求给时钟;
- 上拉与供电:SPI 模式 MISO/MOSI/CLK/CS 需要上拉以得到 0xFF 填充,TF 卡座常带检测开关;电平多为 3.3V,不能直接喂 5V SPI(用电平转换);
- 文件系统:裸块读写之上由 FAT32/exFAT 等文件系统组织文件,驱动只需提供「初始化、读块、写块」三个原语;
- SPI 模式比 SDIO 慢、CPU 占用高,追求性能用专用 SDIO 控制器或 DMA搬运,但它最大的价值是通用、只要有 SPI 就能用。
与现有篇目的衔接
总结
一句话总结:SD/TF 卡原生走 SDIO,但上电时可用特定握手把它切进兼容的 SPI 模式,使任何只有普通 SPI 主机的 MCU/FPGA 都能读写;进入流程是在片选拉高下先供至少 74 个时钟让卡上电、以 100~400kHz 低速发带正确 CRC 的 CMD0 软复位(进 SPI 模式后数据阶段默认不再校验 CRC)、用 CMD8 识别版本与电压、再以 CMD55 为前缀反复发 ACMD41 直到 R1 的 idle 位清零并据此判断是否 SDHC/SDXC,之后才能提速;命令为 6 字节(0x40+命令号、4 字节参数、CRC),发完持续读 MISO 直到收到最高位为 0 的 R1 应答;读写以 512 字节块为单位,高容量卡用块号而老卡用字节地址,读单块 CMD17 的应答是 R1、填充、起始令牌 0xFE、512 字节数据和 2 字节 CRC,CMD18 连续读到 CMD12 停止,写单块 CMD24/多块 CMD25 则在 R1 后发 0xFC/0xFE 写令牌、512 字节和伪 CRC,再依据卡返回的数据响应令牌并轮询被拉低的 MISO 判断编程忙、重新读到 0xFF 才算完成;实现是带超时的接收状态机,工程上要先低速初始化再提速、加好上拉和电平转换,文件系统只建立在初始化/读块/写块三个原语之上;SPI 模式比 SDIO 慢但极其通用。