|
SD卡协议全解析:从SD 1.0到SD 8.0的演进、总线模式与速度等级(2026实战指南)

SD卡协议全解析:从SD 1.0到SD 8.0的演进、总线模式与速度等级(2026实战指南)

SD卡(Secure Digital Memory Card)是目前最广泛使用的可移动存储介质之一,从数码相机到嵌入式开发板,从无人机到行车记录仪,几乎无处不在。作为一个诞生于1999年的存储标准,SD卡协议经历了多次重大演进,从最初的最大2GB容量发展到如今单卡128TB的理论极限。

本文将从协议演进、总线接口、命令体系、速度等级和容量规范等维度,全面剖析SD卡协议的技术细节,帮助嵌入式工程师和硬件开发者深入理解这一”小而强大”的存储协议。

一、SD卡的发展历史

1.1 前身:MMC卡的诞生

要理解SD卡,必须先了解它的前身——MMC(MultiMediaCard)。1997年,西门子(Siemens)和SanDisk联合开发了MMC卡,采用7针接口,设计理念是小型化、低功耗。

SD卡的诞生源于一个实际需求:MMC卡没有内置加密功能。1999年,松下(Matsushita)、东芝(Toshiba)和SanDisk三家公司联合成立了SD协会(SD Association,简称SDA),在MMC的基础上推出了SD卡标准。关键改进包括:

  • 增加了一个加密(CPRM)寄存器,实现”Secure Digital”
  • 将引脚数从7针增加到9针,增加了专用的数据传输线
  • 将总线频率从MMC的20MHz提升到25MHz
  • 引入了4-bit并行传输模式

1.2 SD卡30年演进全景

从1999年至今,SD卡协议经历了8个主要版本的演进:

SD 1.0(1999年)

  • 最大容量:2GB(SDSC,Standard Capacity)
  • 总线频率:25MHz
  • 传输模式:SPI、1-bit SD模式
  • 电压范围:2.7V-3.6V
  • 传输速率:最高12.5MB/s(1-bit模式)

SD 1.1(2001年)

  • 增加4-bit SD总线模式
  • 引入高速模式(High Speed Mode),频率提升至50MHz
  • 传输速率:最高25MB/s(4-bit高速模式)

SD 2.0(2006年)

  • 里程碑版本,引入SDHC(Secure Digital High Capacity)规范
  • 文件系统从FAT12/FAT16切换到FAT32
  • 最大容量:32GB
  • 引入速度等级(Speed Class):Class 2/4/6/10
  • 总线频率仍为25MHz/50MHz
  • 新增ACMD41命令支持高容量寻址(SDHC使用块地址而非字节地址)

SD 3.0(2010年)

  • 重大升级,引入UHS-I(Ultra High Speed Phase I)总线
  • 引入SDXC(Secure Digital eXtended Capacity)规范
  • 文件系统支持exFAT
  • 最大容量:2TB
  • UHS-I总线频率:100MHz(DDR模式)
  • UHS-I传输速率:最高104MB/s
  • 新增UHS Speed Class:UHS-I(U1)

SD 4.0(2011年)

  • 引入UHS-II(Ultra High Speed Phase II)
  • 新增一行引脚(背面的第二排触点),实现全双工通信
  • UHS-II总线速率:312MB/s
  • 引入UHS Speed Class U3(保证最低30MB/s写入)
  • 新增Video Speed Class的雏形

SD 5.0(2016年)

  • 引入SDUC(Secure Digital Ultra Capacity)规范
  • 最大容量:128TB
  • 新增Video Speed Class:V6/V10/V30/V60/V90
  • 引入SD-Transport(SD Transport)用于固件更新

SD 6.0(2018年)

  • 引入UHS-III
  • UHS-III全双工速率:624MB/s
  • 引入新的电源管理功能
  • 支持更低电压操作(1.2V信号电平)

SD 7.0(2018年)

  • 引入SD Express,基于PCIe 3.0和NVMe协议
  • 理论最大速度:接近985MB/s
  • 保持与旧版SD卡的向后兼容(双模式设计)
  • 支持USB 3.2协议作为备选

SD 8.0(2023年)

  • 升级SD Express到PCIe 4.0
  • 理论最大速度:约3938MB/s(x1 lane PCIe 4.0)
  • 支持x2 lane PCIe配置
  • 进一步降低功耗设计

1.3 版本演进时间线

flowchart LR
    V1["SD 1.0<br>1999"]
    V11["SD 1.1<br>2001"]
    V2["SD 2.0<br>2006"]
    V3["SD 3.0<br>2010"]
    V4["SD 4.0<br>2011"]
    V5["SD 5.0<br>2016"]
    V6["SD 6.0<br>2018"]
    V7["SD 7.0<br>2018"]
    V8["SD 8.0<br>2023"]
    V1 -->|SDSC 2GB| V11
    V11 -->|4-bit, 50MHz| V2
    V2 -->|SDHC 32GB| V3
    V3 -->|SDXC 2TB<br>UHS-I 104MB/s| V4
    V4 -->|UHS-II 312MB/s| V5
    V5 -->|SDUC 128TB<br>Video Class| V6
    V6 -->|UHS-III 624MB/s| V7
    V7 -->|SD Express<br>PCIe 3.0 985MB/s| V8

二、SD卡协议架构

2.1 物理接口

SD卡的物理接口设计是其核心创新之一。标准SD卡有9个引脚,MicroSD卡同样为9引脚但尺寸缩小至15mm × 11mm × 1mm。

标准SD卡引脚定义(9针):

引脚名称功能
1CD/DAT3卡检测 / 数据线3
2CMD命令/响应线(双向)
3VSS1
4VDD电源(2.7V-3.6V)
5CLK时钟信号
6VSS2
7DAT0数据线0
8DAT1数据线1
9DAT2数据线2

UHS-II扩展引脚(背面的第二排):

UHS-II卡在背面增加了额外一排触点,实现全双工数据传输:

位置功能
背面 1-2差分对 TX(发送)
背面 3-4差分对 RX(接收)
背面 5-7保留/地

MicroSD vs 标准SD卡的物理差异:

参数标准SD卡MicroSD卡
尺寸32mm × 24mm × 2.1mm15mm × 11mm × 1mm
重量约2g约0.25g
引脚数98(去掉一个DAT3/CD复用)
卡检测机械式检测开关依赖插入检测弹片
典型应用相机、录音笔、工控板手机、无人机、运动相机、树莓派

2.2 SD卡的工作模式

SD卡支持两种基本工作模式,这是理解SD协议的第一个关键分叉点:

SPI模式(Serial Peripheral Interface Mode):

SPI模式是SD卡最基础的通信方式,使用标准的SPI总线协议。在这种模式下,SD卡本质上相当于一个SPI从设备。

  • 使用4根线:CLK、MOSI(CMD)、MISO(DAT0)、CS(DAT3)
  • DAT1和DAT2引脚不使用
  • 通信协议简单,兼容所有带SPI接口的MCU
  • 速度较低,最高约12.5MB/s(SDSC)或25MB/s(SDHC)
  • 关键区别:SPI模式下使用块地址(Block Address),而非字节地址
MCU                    SD卡 (SPI模式)
-----                  -------------
SCK  ────────────── CLK
MOSI ────────────── CMD  (命令输入)
MISO ────────────── DAT0 (数据输出)
CS   ────────────── DAT3 (片选,低有效)
                      DAT1, DAT2 不使用

SD模式(SD Bus Mode / Native Mode):

SD模式是SD卡的原生工作模式,使用SD协会定义的专用总线协议,支持1-bit、4-bit甚至8-bit并行传输。

  • 使用全部9根引脚(至少CMD + CLK + DAT0~DAT3,共6根信号线)
  • 需要专用的SDIO控制器(大多数SoC内置)
  • 支持更高的传输速率(UHS-I/II/III)
  • 支持完整的SD卡功能(UHS、SCR寄存器、ACMD命令等)
MCU/SoC              SD卡 (SD模式)
---------            -------------
CLK  ────────────── CLK
CMD  ←─────────────→ CMD  (双向,命令/响应)
DAT0 ←─────────────→ DAT0 (双向,数据)
DAT1 ←─────────────→ DAT1 (双向,数据/中断)
DAT2 ──────────────→ DAT2 (数据方向)
DAT3 ←─────────────→ DAT3 (数据/片选)

SPI模式 vs SD模式对比:

特性SPI模式SD模式
所需引脚46(1-bit)/ 6+(4-bit)
通信协议标准SPISD专用协议
最大速度25MB/s最高3938MB/s(SD Express)
ACMD命令不支持支持
UHS支持不支持支持
适用场景低速嵌入式、MCU资源有限高性能存储、手机、相机
驱动复杂度

2.3 总线传输模式详解

SD模式(Native Mode)下,SD卡支持多种总线传输模式,速率逐级提升:

1-bit SD总线模式:

  • 仅使用DAT0一根数据线进行传输(CMD + CLK + DAT0,共3根信号线)
  • 每个时钟周期传输1 bit数据
  • 默认模式(Default Speed):25MHz,理论速率 3.125 MB/s
  • 高速模式(High Speed):50MHz,理论速率 6.25 MB/s
  • 适用于引脚受限的场景

4-bit SD总线模式:

  • 使用DAT0~DAT3共4根数据线
  • 每个时钟周期传输4 bit数据
  • 默认模式(Default Speed):25MHz × 4 = 12.5 MB/s
  • 高速模式(High Speed):50MHz × 4 = 25 MB/s
  • 这是最常见的SD卡工作模式,绝大多数SD卡读卡器和SoC默认使用此模式

UHS-I(Ultra High Speed Phase I):

  • 使用4-bit总线,但采用DDR(Double Data Rate)采样
  • 在时钟的上升沿和下降沿都采样数据,等效频率翻倍
  • 总线频率:100MHz(DDR),实际传输速率 104 MB/s(SDR50)或 208 MB/s(DDR50)
  • SDR104模式:208MHz时钟,单沿采样,理论速率 104 MB/s
  • 需要1.8V信号电平(通过CMD11电压切换实现)

UHS-II(Ultra High Speed Phase II):

  • 使用背面的额外一排差分触点(Lane)
  • 采用LVDS(Low Voltage Differential Signaling)差分信号
  • 全双工通信(独立的TX和RX差分对)
  • 总线速率:312 MB/s
  • 主要用于高端相机和视频设备

UHS-III(Ultra High Speed Phase III):

  • 同样使用背面差分触点
  • 全双工速率翻倍至 624 MB/s
  • 引入新的电源管理和流控机制

SD Express(SD 7.0 / 8.0):

  • 在UHS-II/III的差分触点上运行 PCIe 3.0/4.0 + NVMe协议
  • SD 7.0(PCIe 3.0 x1):理论速率 985 MB/s
  • SD 8.0(PCIe 4.0 x1):理论速率 3938 MB/s
  • 保持向后兼容——插入传统SD读卡器时自动回退到UHS-I/II模式
  • 使用双模设计(Dual-mode):卡内同时有SD控制器和PCIe/NVMe控制器

各总线模式速率对比:

模式总线宽度时钟频率采样方式理论速率信号电压
Default Speed1-bit25MHzSDR3.125 MB/s3.3V
High Speed1-bit50MHzSDR6.25 MB/s3.3V
Default Speed4-bit25MHzSDR12.5 MB/s3.3V
High Speed4-bit50MHzSDR25 MB/s3.3V
SDR504-bit100MHzSDR50 MB/s1.8V
DDR504-bit50MHzDDR50 MB/s1.8V
SDR1044-bit208MHzSDR104 MB/s1.8V
UHS-II差分LaneLVDS312 MB/s1.8V
UHS-III差分LaneLVDS624 MB/s1.8V
SD Express (PCIe 3.0)差分LanePCIe985 MB/s1.8V
SD Express (PCIe 4.0)差分LanePCIe3938 MB/s1.8V

三、SD卡命令体系(CMD指令集)

SD卡的所有操作都通过命令(Command)来完成。理解命令体系是嵌入式开发中驱动SD卡的核心。

3.1 命令格式

SD模式下的命令帧长度为48 bit(标准命令)或136 bit(长响应命令),结构如下:

标准命令格式(48 bit):

┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ Start bit│Transmit  │ CMD Index│ Argument │ CRC7     │ End bit │
│  (1 bit) │ Direction│ (6 bit) │ (32 bit) │ (7 bit)  │ (1 bit) │
│    0     │   1 bit  │          │          │          │    1    │
└──────────┴──────────┴──────────┴──────────┴──────────┴─────────┘
  • Start bit:始终为0,标志命令开始
  • Transmission bit:Host→Card为0,Card→Host为1
  • CMD Index:命令编号(CMD0CMD63,ACMD0ACMM63)
  • Argument:32位参数,含义随命令不同而不同
  • CRC7:7位校验码(SPI模式下CMD0和CMD8外的命令可关闭CRC)
  • End bit:始终为1

响应类型:

SD卡命令执行后会返回响应(Response),响应类型有多种:

响应类型长度典型命令内容
R148 bit大多数命令卡状态寄存器 + CMD Index
R1b48 bit + BusyCMD7, CMD12R1 + 忙信号(DAT0拉低)
R2136 bitCMD9, CMD10CID/CSD寄存器完整内容
R348 bitACMD41OCR寄存器(无CRC)
R648 bitCMD3RCA(相对卡地址)+ 状态
R748 bitCMD8电压支持 + 检查模式回显

3.2 关键命令速查表

以下是SD卡开发中最常用的命令:

命令名称说明参数
CMD0GO_IDLE_STATE复位卡,进入Idle状态
CMD2ALL_SEND_CID所有卡发送CID(序列号等)
CMD3SEND_RELATIVE_ADDR卡返回相对地址(RCA)
CMD5SLEEP_AWAKE睡眠/唤醒(UHS-II)RCA
CMD7SELECT/DESELECT_CARD选中/取消选中卡RCA
CMD8SEND_IF_COND电压兼容性检查(SD 2.0+必需)电压+检查模式
CMD9SEND_CSD读取CSD寄存器(容量/速度信息)RCA
CMD10SEND_CID读取CID寄存器RCA
CMD12STOP_TRANSMISSION停止多块读写传输
CMD13SEND_STATUS查询卡状态RCA
CMD16SET_BLOCKLEN设置块长度(SDSC用,SDHC忽略)块大小
CMD17READ_SINGLE_BLOCK读取单个数据块地址
CMD18READ_MULTIPLE_BLOCK连续读取多个数据块地址
CMD24WRITE_BLOCK写入单个数据块地址
CMD25WRITE_MULTIPLE_BLOCK连续写入多个数据块地址
CMD55APP_CMD应用命令前缀(下一条为ACMD)RCA
ACMD6SET_BUS_WIDTH设置总线宽度(1-bit或4-bit)0=1bit, 2=4bit
ACMD41SD_SEND_OP_CONDSD卡初始化(发OCR,获取能力)OCR
ACMD51SEND_SCR读取SCR寄存器(SD规范版本)

3.3 SD卡初始化流程(关键!)

SD卡的初始化是整个驱动开发中最复杂也最关键的部分。以下是完整的初始化流程:

sequenceDiagram
    participant Host
    participant SD卡

    Host->>SD卡: CMD0 (GO_IDLE_STATE) — 复位卡
    Host->>SD卡: CMD8 (SEND_IF_COND) — arg: 0x1AA
    SD卡-->>Host: R7 — 电压兼容回显
    Note over Host,SD卡: 正确响应=SD2.0+;无响应=SD1.x

    loop 循环直到busy位=1(超时约1s)
        Host->>SD卡: CMD55 + ACMD41 (HCS=1)
        SD卡-->>Host: R3 (OCR)
    end
    Note over Host: CCS=1→SDHC(块寻址)<br>CCS=0→SDSC(字节寻址)

    Host->>SD卡: CMD2 (ALL_SEND_CID)
    SD卡-->>Host: R2 (CID)
    Host->>SD卡: CMD3 (SEND_RELATIVE_ADDR)
    SD卡-->>Host: R6 (RCA)
    Host->>SD卡: CMD9 (SEND_CSD)
    SD卡-->>Host: R2 (CSD)
    Host->>SD卡: CMD7 (SELECT)
    SD卡-->>Host: R1b
    Host->>SD卡: CMD55 + ACMD6 — 切换到4-bit
    Note over Host,SD卡: 初始化完成,进入Data Transfer状态

关键细节:

  1. CMD8是区分SD 1.x和SD 2.0+的分水岭。如果你的代码只支持SD 1.x,将无法使用SDHC/SDXC卡
  2. ACMD41必须通过CMD55前缀触发(CMD55告诉卡”下一条命令是ACMD”)
  3. ACMD41的HCS位(Host Capacity Support) 必须置1,否则卡会以为主机只支持SDSC,SDHC卡将拒绝初始化
  4. 初始化循环需要超时机制,通常设为1秒。卡可能需要数百次ACMD41才能就绪

3.4 数据读写流程

初始化完成后,典型的数据读写流程如下:

单块读取(CMD17):

sequenceDiagram
    participant Host
    participant SD卡
    Host->>SD卡: CMD17 (地址)
    SD卡-->>Host: R1
    SD卡-->>Host: Data Block<br>Start(0xFE) + 512B + CRC16

多块读取(CMD18):

sequenceDiagram
    participant Host
    participant SD卡
    Host->>SD卡: CMD18 (地址)
    SD卡-->>Host: R1
    SD卡-->>Host: Data Block 1
    SD卡-->>Host: Data Block 2
    SD卡-->>Host: ...
    Host->>SD卡: CMD12 (STOP)
    SD卡-->>Host: R1b

多块写入(CMD25)——注意预擦除:

sequenceDiagram
    participant Host
    participant SD卡
    Host->>SD卡: CMD25 (地址)
    SD卡-->>Host: R1
    Host->>SD卡: Data Block 1<br>Start(0xFC) + 512B + CRC16
    SD卡-->>Host: Data Response (接受/拒绝)
    Host->>SD卡: Data Block 2
    SD卡-->>Host: Data Response
    Host->>SD卡: CMD12 (STOP)
    SD卡-->>Host: R1b (等待编程完成)

四、速度等级详解

SD卡的速度等级体系在30年中不断复杂化,目前有三套并行的速度标识系统。理解它们是正确选型的关键。

4.1 Speed Class(速度等级)

最早引入的速度标识(SD 2.0),用字母C包围数字表示:

等级最低持续写入速度典型应用
Class 22 MB/s已基本淘汰
Class 44 MB/s低分辨率视频录制
Class 66 MB/s720p视频录制
Class 1010 MB/s1080p全高清视频、连拍照片

注意:Speed Class标注的是最低持续写入速度,不是最大读取速度。一张标称Class 10的卡,读取速度可能达到95MB/s,但写入保证不低于10MB/s。

4.2 UHS Speed Class(UHS速度等级)

随UHS-I总线引入(SD 3.0),用字母U包围数字表示:

等级最低持续写入速度典型应用
U110 MB/s1080p实时视频
U330 MB/s4K视频录制(30fps)

UHS Class的卡同时也会标注传统Speed Class(如U3卡通常也标Class 10)。

4.3 Video Speed Class(视频速度等级)

SD 5.0引入,专为高分辨率视频设计,用字母V加数字表示:

等级最低持续写入速度典型应用
V66 MB/s标清/720p视频
V1010 MB/s1080p全高清视频
V3030 MB/s4K @ 60fps视频、VR内容
V6060 MB/s8K @ 30fps视频、高码率4K
V9090 MB/s8K @ 60fps、专业电影级拍摄

4.4 速度等级关系总结

flowchart TB
    Root["速度等级体系演进"]
    SC["Speed Class (2006)<br>Class 2 / 4 / 6 / 10"]
    UHS["UHS Speed Class (2010)<br>U1 / U3"]
    VSC["Video Speed Class (2016)<br>V6 / V10 / V30 / V60 / V90"]
    Note["三套体系并行使用<br>V等级是目前最推荐的视频选型标准"]
    Root --> SC
    Root --> UHS
    Root --> VSC
    VSC --> Note

一张卡上的速度标识解读示例:

┌─────────────────────────┐
│  SanDisk Extreme Pro    │
│  64GB  SDXC  U3  V30    │  ← SDXC容量 + U3 + V30
│  A2  Class 10           │  ← A2应用性能 + Class 10
│  300 MB/s READ          │  ← 最大读取速度(厂商标称,非标准)
└─────────────────────────┘

4.5 Application Performance Class(A等级)

SD 5.1新增,衡量随机读写性能(IOPS),对运行操作系统或App很重要:

等级最低随机读取IOPS最低随机写入IOPS最低持续写入
A1150050010 MB/s
A24000200010 MB/s

A2等级需要卡支持命令队列(Command Queue),主机端也需支持相应协议。树莓派等SBC使用A2卡可以显著提升系统响应速度。

五、容量规范:SDSC / SDHC / SDXC / SDUC

SD卡的容量规范与寻址方式密切相关,不同容量卡的底层行为有本质差异。

5.1 容量规范对比

规范引入版本容量范围文件系统寻址方式
SDSC (Standard Capacity)SD 1.01MB ~ 2GBFAT12/FAT16/FAT32字节地址(Byte Address)
SDHC (High Capacity)SD 2.02GB ~ 32GBFAT32块地址(Block Address,512字节/块)
SDXC (eXtended Capacity)SD 3.02GB ~ 2TBexFAT块地址(Block Address,512字节/块)
SDUC (Ultra Capacity)SD 5.02GB ~ 128TBexFAT块地址(Block Address,512字节/块)

5.2 寻址方式差异(开发关键!)

这是嵌入式开发中最容易踩的坑

SDSC卡使用字节地址(Byte Address):

  • CMD17读取命令的参数是数据的字节偏移量
  • 读取第0块:参数 = 0
  • 读取第1块:参数 = 512(每块512字节)
  • 读取第N块:参数 = N × 512

SDHC/SDXC卡使用块地址(Block Address):

  • CMD17读取命令的参数是块号
  • 读取第0块:参数 = 0
  • 读取第1块:参数 = 1
  • 读取第N块:参数 = N
// 伪代码:读写时的地址转换
if (card_type == SDSC) {
    // 字节寻址:地址 = 块号 × 512
    argument = block_number * 512;
} else {
    // SDHC/SDXC:块寻址,地址就是块号
    argument = block_number;
}

为什么需要区分? 在初始化阶段通过ACMD41的响应(R3)中的CCS位(Card Capacity Status)来判断。CCS=1表示SDHC/SDXC(块寻址),CCS=0表示SDSC(字节寻址)。如果搞混了,读写的数据位置会完全错乱。

5.3 CSD寄存器——容量信息的来源

CSD(Card-Specific Data)寄存器包含卡的容量、速度、编程时间等关键信息。通过CMD9读取,长度为128 bit。

CSD V1.0(SDSC/SDHC)关键字段:

字段位域说明
CSD_STRUCTURE[127:126]CSD版本:00=V1.0(SDSC),01=V2.0(SDHC)
READ_BL_LEN[83:80]最大读取块长度(SDSC,通常为9=512B)
C_SIZE[73:62]容量乘数(SDSC)
C_SIZE_MULT[49:47]容量乘数因子
C_SIZE (V2.0)[69:48]SDHC容量值(直接映射)

SDSC容量计算公式:

memory_capacity = (C_SIZE + 1) × (C_SIZE_MULT + 2) × (2 ^ READ_BL_LEN)

SDHC/SDXC容量计算公式(V2.0):

memory_capacity = (C_SIZE + 1) × 512KB

例如:C_SIZE = 60951 → 容量 = 60952 × 512KB ≈ 30.4GB

5.4 CID寄存器——卡的身份证

CID(Card Identification)寄存器包含卡的唯一标识信息,通过CMD10读取:

字段长度说明
MID8 bit制造商ID(如SanDisk=0x03,Samsung=0x1B)
OID16 bitOEM/Application ID
PNM40 bit产品名(ASCII字符串)
PRV8 bit产品版本
PSN32 bit产品序列号
MDT12 bit生产日期(年/月)

六、SCR寄存器与SD规范版本

SCR(SD Configuration Register)是一个64位的寄存器,包含SD卡的规范版本和总线能力信息。通过ACMD51(需先CMD55前缀)读取。

SCR关键字段:

字段位域说明
SCR_STRUCTURE[63:60]SCR版本号
SD_SPEC[59:56]SD规范版本:0=1.0-1.01, 1=1.10, 2=2.00-3.0X
DATA_STAT_AFTER_ERASE[55]擦除后数据状态(0/1)
SD_SECURITY[54:52]安全支持(CPRM等)
SD_BUS_WIDTHS[51:48]支持的总线宽度(bit0=1bit, bit2=4bit)
SD_SPEC3[47]SD 3.0+支持:0=No, 1=Yes
SD_SPEC4[46]SD 4.0+支持
SD_SPECX[45:42]SD 5.0+扩展版本
CMD_SUPPORT[35:32]支持的命令(CMD23等)

为什么SCR重要? SD_SPEC字段可以告诉你这张卡遵循哪个SD规范版本,但不能告诉你主机将使用哪种总线模式。总线模式是通过初始化过程中的命令协商来确定的,而不是由卡单方面决定。

七、嵌入式开发实战要点

7.1 选择SD卡接口方案

在嵌入式项目中,选择SPI模式还是SD模式取决于具体需求:

场景推荐方案理由
STM32/Arduino低速数据记录SPI模式驱动简单,MCU资源占用少
树莓派/Linux SBCSD模式(4-bit)内核已有驱动,性能最优
高速数据采集(>25MB/s)SD模式(UHS-I)SPI模式无法满足速率需求
引脚资源极紧张SPI模式仅需4根线
需要卡热插拔检测SD模式DAT3引脚可做机械检测

7.2 STM32 + SPI模式驱动SD卡(实战框架)

以下是使用STM32 HAL库通过SPI接口驱动SD卡的核心代码框架:

#include "stm32f4xx_hal.h"
#include <string.h>

// SD卡类型枚举
typedef enum {
    SD_TYPE_SDSC,
    SD_TYPE_SDHC_SDXC
} SD_CardType;

// SD卡信息结构体
typedef struct {
    SD_CardType type;
    uint32_t capacity_mb;      // 容量(MB)
    uint8_t cid[16];           // CID寄存器
    uint8_t csd[16];           // CSD寄存器
} SD_CardInfo;

static SPI_HandleTypeDef hspi1;
static SD_CardInfo sd_info;

// CS片选控制
#define SD_CS_LOW()   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
#define SD_CS_HIGH()  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)

// SPI传输单字节
static uint8_t SPI_TransferByte(uint8_t data) {
    uint8_t rx;
    HAL_SPI_TransmitReceive(&hspi1, &data, &rx, 1, 100);
    return rx;
}

// 发送命令并获取响应
static uint8_t SD_SendCommand(uint8_t cmd, uint32_t arg) {
    uint8_t response;
    uint8_t retry = 0;

    SD_CS_LOW();

    // 发送命令帧
    SPI_TransferByte(0x40 | cmd);      // Start + Direction + CMD Index
    SPI_TransferByte((arg >> 24) & 0xFF);  // Argument [31:24]
    SPI_TransferByte((arg >> 16) & 0xFF);  // Argument [23:16]
    SPI_TransferByte((arg >> 8) & 0xFF);   // Argument [15:8]
    SPI_TransferByte(arg & 0xFF);           // Argument [7:0]

    // CRC(仅CMD0和CMD8需要有效CRC)
    if (cmd == 0) SPI_TransferByte(0x95);  // CMD0 CRC
    else if (cmd == 8) SPI_TransferByte(0x87); // CMD8 CRC
    else SPI_TransferByte(0xFF);  // 伪CRC

    // 等待响应(去掉start bit)
    do {
        response = SPI_TransferByte(0xFF);
        retry++;
    } while (response == 0xFF && retry < 100);

    return response;
}

// SD卡初始化
HAL_StatusTypeDef SD_Init(void) {
    uint8_t response;
    uint32_t retry;

    // 1. 上电延时 + 发送74个以上时钟脉冲
    HAL_Delay(10);
    SD_CS_HIGH();
    for (int i = 0; i < 10; i++) {
        SPI_TransferByte(0xFF);  // 80个时钟
    }

    // 2. CMD0 复位到Idle状态
    retry = 0;
    do {
        response = SD_SendCommand(0, 0);
        retry++;
    } while (response != 0x01 && retry < 100);
    if (response != 0x01) return HAL_ERROR;  // 未进入Idle

    // 3. CMD8 检查电压兼容性
    response = SD_SendCommand(8, 0x000001AA);
    if (response == 0x01) {
        // SD 2.0+ 卡:读取R7响应的后4字节
        uint8_t r7[4];
        for (int i = 0; i < 4; i++) r7[i] = SPI_TransferByte(0xFF);
        // 验证回显:r7[3]应为0xAA
        sd_info.type = SD_TYPE_SDHC_SDXC;  // 假定为SDHC
    } else {
        sd_info.type = SD_TYPE_SDSC;  // SD 1.x 卡
    }
    SD_CS_HIGH();

    // 4. ACMD41 循环初始化(直到就绪)
    retry = 0;
    do {
        SD_SendCommand(55, 0);  // CMD55 前缀
        uint32_t acmd41_arg = 0x40000000;  // HCS=1,支持SDHC
        if (sd_info.type == SD_TYPE_SDSC) acmd41_arg = 0;
        response = SD_SendCommand(41, acmd41_arg);
        retry++;
        HAL_Delay(1);
    } while (response != 0x00 && retry < 200);
    if (response != 0x00) return HAL_ERROR;

    // 5. CMD16 设置块长度为512(SDSC需要)
    if (sd_info.type == SD_TYPE_SDSC) {
        SD_SendCommand(16, 512);
    }

    // 6. 读取容量(CMD9读取CSD)... 省略,参见CSD解析

    return HAL_OK;
}

// 读取单个块(512字节)
HAL_StatusTypeDef SD_ReadBlock(uint32_t block_num, uint8_t *buf) {
    uint32_t addr;
    uint8_t token;
    uint32_t retry;

    // 地址转换
    if (sd_info.type == SD_TYPE_SDSC) {
        addr = block_num * 512;  // 字节地址
    } else {
        addr = block_num;        // 块地址
    }

    SD_CS_LOW();

    // 发送CMD17
    if (SD_SendCommand(17, addr) != 0x00) {
        SD_CS_HIGH();
        return HAL_ERROR;
    }

    // 等待数据Token(0xFE)
    retry = 0;
    do {
        token = SPI_TransferByte(0xFF);
        retry++;
    } while (token == 0xFF && retry < 10000);

    if (token != 0xFE) {
        SD_CS_HIGH();
        return HAL_ERROR;
    }

    // 读取512字节数据
    for (int i = 0; i < 512; i++) {
        buf[i] = SPI_TransferByte(0xFF);
    }

    // 丢弃CRC16(2字节)
    SPI_TransferByte(0xFF);
    SPI_TransferByte(0xFF);

    SD_CS_HIGH();
    return HAL_OK;
}

7.3 树莓派/Linux下的SD卡

在Linux系统(如树莓派)上,内核已内置SD卡驱动,通常无需手动编写驱动代码:

# 查看SD卡信息
cat /sys/block/mmcblk0/device/cid    # CID寄存器
cat /sys/block/mmcblk0/device/csd    # CSD寄存器
cat /sys/block/mmcblk0/size          # 容量(512字节块数)

# 查看SD卡总线速度
cat /sys/block/mmcblk0/device/max_current
ls -la /sys/bus/mmc/devices/

# 测试SD卡读写速度
sudo hdparm -tT /dev/mmcblk0

# 查看SD卡实际协商的总线模式
dmesg | grep mmc
# 典型输出:
# mmc0: new ultra high speed DDR50 SDHC card ...
# 或:mmc0: new high speed SDHC card ...

7.4 常见问题与调试技巧

问题1:SD卡初始化失败(ACMD41无响应)

排查清单:

  • 检查SPI接线(MOSI/MISO/CLK/CS)是否牢固
  • 确认SPI时钟频率初始化阶段不超过400kHz(SD规范要求)
  • 检查供电是否稳定(SD卡初始化瞬间电流可达150mA)
  • 确保CS引脚在初始化前保持高电平至少74个时钟

问题2:能初始化但读写数据错乱

最常见的原因是地址模式混淆

  • 检查是否正确区分了SDSC(字节地址)和SDHC(块地址)
  • 用CMD9读取CSD,确认CSD_STRUCTURE字段(0=SDSC, 1=SDHC)
// 调试:打印CSD结构类型
uint8_t csd_structure = (csd[0] >> 6) & 0x03;
printf("CSD Version: %s\n", csd_structure == 0 ? "V1.0 (SDSC)" : "V2.0 (SDHC/SDXC)");

问题3:高速模式协商失败

  • UHS-I需要1.8V信号电平切换(CMD11触发)
  • 如果主机不支持1.8V切换,卡会回退到3.3V高速模式(25MB/s)
  • 确保PCB走线的信号完整性(走线长度<10cm,避免过孔)

问题4:写入速度慢

  • 检查卡的速度等级是否匹配应用需求
  • SD卡写入前需要擦除,写入速度受擦除块大小影响
  • 使用CMD23(SET_BLOCK_COUNT)预通知块数可提升多块写入性能
  • 确保不使用写保护(检查DAT1引脚状态或卡的物理写保护开关)

问题5:卡无法被识别

# Linux下诊断SD卡识别问题
dmesg | tail -20                    # 查看内核日志
lsblk                                # 查看块设备
sudo fdisk -l /dev/mmcblk0          # 查看分区
sudo mmc extcsd read /dev/mmcblk0   # 查看扩展寄存器(需mmc-utils)

八、SD卡协议选型指南

根据不同的应用场景,推荐选择不同规格的SD卡:

应用场景推荐容量规范推荐速度等级推荐接口模式选型建议
嵌入式数据记录(低速)SDSC/SDHCClass 10SPI模式成本优先,16GB足够
树莓派/Linux SBCSDHC/SDXCA2, V30SD模式(内核驱动)A2等级显著提升随机IO
4K视频录制SDXCV30/U3SD模式64GB起步,V30保证持续写入
8K专业摄影/电影SDXCV60/V90SD模式(UHS-II)需要UHS-II卡槽支持
工业温控/恶劣环境SDHCClass 10SPI/SD模式选择工业级(-40°C~85°C)
IoT边缘设备MicroSD SDHCClass 10/A1SPI模式注意功耗,选低功耗型号

小结

SD卡协议经过30年演进,已经发展成一个复杂而完善的存储标准体系。作为嵌入式工程师,理解SD卡协议需要把握以下几个核心维度:

  1. 两种工作模式:SPI模式(简单低速)和SD模式(复杂高速),根据项目需求选择
  2. 总线演进路线:从1-bit → 4-bit → UHS-I(DDR) → UHS-II(差分) → SD Express(PCIe),速率从3MB/s跨越到近4GB/s
  3. 命令体系:CMD0CMD63 + ACMD0ACMD63,其中初始化流程(CMD0→CMD8→ACMD41→CMD2→CMD3→CMD7)是驱动开发的核心
  4. 速度等级:三套并行体系(Class/UHS Class/Video Class)+ A等级(随机IO),V等级是视频应用的首选标准
  5. 容量与寻址:SDSC用字节地址,SDHC/SDXC用块地址——这是嵌入式开发中最容易出错的细节

对于大多数嵌入式项目,SPI模式 + Class 10 SDHC卡就足以满足需求。如果你的项目需要更高性能(如音视频采集、高速数据记录),建议直接使用SDIO接口 + UHS卡,并充分利用Linux内核的SD卡驱动栈。

希望这篇全面解析能帮助你深入理解SD卡协议,在选型和开发中少走弯路。如果有任何问题,欢迎在评论区讨论。