硬件与设计 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针):
| 引脚 | 名称 | 功能 |
|---|---|---|
| 1 | CD/DAT3 | 卡检测 / 数据线3 |
| 2 | CMD | 命令/响应线(双向) |
| 3 | VSS1 | 地 |
| 4 | VDD | 电源(2.7V-3.6V) |
| 5 | CLK | 时钟信号 |
| 6 | VSS2 | 地 |
| 7 | DAT0 | 数据线0 |
| 8 | DAT1 | 数据线1 |
| 9 | DAT2 | 数据线2 |
UHS-II扩展引脚(背面的第二排):
UHS-II卡在背面增加了额外一排触点,实现全双工数据传输:
| 位置 | 功能 |
|---|---|
| 背面 1-2 | 差分对 TX(发送) |
| 背面 3-4 | 差分对 RX(接收) |
| 背面 5-7 | 保留/地 |
MicroSD vs 标准SD卡的物理差异:
| 参数 | 标准SD卡 | MicroSD卡 |
|---|---|---|
| 尺寸 | 32mm × 24mm × 2.1mm | 15mm × 11mm × 1mm |
| 重量 | 约2g | 约0.25g |
| 引脚数 | 9 | 8(去掉一个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模式 |
|---|---|---|
| 所需引脚 | 4 | 6(1-bit)/ 6+(4-bit) |
| 通信协议 | 标准SPI | SD专用协议 |
| 最大速度 | 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 Speed | 1-bit | 25MHz | SDR | 3.125 MB/s | 3.3V |
| High Speed | 1-bit | 50MHz | SDR | 6.25 MB/s | 3.3V |
| Default Speed | 4-bit | 25MHz | SDR | 12.5 MB/s | 3.3V |
| High Speed | 4-bit | 50MHz | SDR | 25 MB/s | 3.3V |
| SDR50 | 4-bit | 100MHz | SDR | 50 MB/s | 1.8V |
| DDR50 | 4-bit | 50MHz | DDR | 50 MB/s | 1.8V |
| SDR104 | 4-bit | 208MHz | SDR | 104 MB/s | 1.8V |
| UHS-II | 差分Lane | — | LVDS | 312 MB/s | 1.8V |
| UHS-III | 差分Lane | — | LVDS | 624 MB/s | 1.8V |
| SD Express (PCIe 3.0) | 差分Lane | — | PCIe | 985 MB/s | 1.8V |
| SD Express (PCIe 4.0) | 差分Lane | — | PCIe | 3938 MB/s | 1.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:命令编号(CMD0
CMD63,ACMD0ACMM63) - Argument:32位参数,含义随命令不同而不同
- CRC7:7位校验码(SPI模式下CMD0和CMD8外的命令可关闭CRC)
- End bit:始终为1
响应类型:
SD卡命令执行后会返回响应(Response),响应类型有多种:
| 响应类型 | 长度 | 典型命令 | 内容 |
|---|---|---|---|
| R1 | 48 bit | 大多数命令 | 卡状态寄存器 + CMD Index |
| R1b | 48 bit + Busy | CMD7, CMD12 | R1 + 忙信号(DAT0拉低) |
| R2 | 136 bit | CMD9, CMD10 | CID/CSD寄存器完整内容 |
| R3 | 48 bit | ACMD41 | OCR寄存器(无CRC) |
| R6 | 48 bit | CMD3 | RCA(相对卡地址)+ 状态 |
| R7 | 48 bit | CMD8 | 电压支持 + 检查模式回显 |
3.2 关键命令速查表
以下是SD卡开发中最常用的命令:
| 命令 | 名称 | 说明 | 参数 |
|---|---|---|---|
| CMD0 | GO_IDLE_STATE | 复位卡,进入Idle状态 | 无 |
| CMD2 | ALL_SEND_CID | 所有卡发送CID(序列号等) | 无 |
| CMD3 | SEND_RELATIVE_ADDR | 卡返回相对地址(RCA) | 无 |
| CMD5 | SLEEP_AWAKE | 睡眠/唤醒(UHS-II) | RCA |
| CMD7 | SELECT/DESELECT_CARD | 选中/取消选中卡 | RCA |
| CMD8 | SEND_IF_COND | 电压兼容性检查(SD 2.0+必需) | 电压+检查模式 |
| CMD9 | SEND_CSD | 读取CSD寄存器(容量/速度信息) | RCA |
| CMD10 | SEND_CID | 读取CID寄存器 | RCA |
| CMD12 | STOP_TRANSMISSION | 停止多块读写传输 | 无 |
| CMD13 | SEND_STATUS | 查询卡状态 | RCA |
| CMD16 | SET_BLOCKLEN | 设置块长度(SDSC用,SDHC忽略) | 块大小 |
| CMD17 | READ_SINGLE_BLOCK | 读取单个数据块 | 地址 |
| CMD18 | READ_MULTIPLE_BLOCK | 连续读取多个数据块 | 地址 |
| CMD24 | WRITE_BLOCK | 写入单个数据块 | 地址 |
| CMD25 | WRITE_MULTIPLE_BLOCK | 连续写入多个数据块 | 地址 |
| CMD55 | APP_CMD | 应用命令前缀(下一条为ACMD) | RCA |
| ACMD6 | SET_BUS_WIDTH | 设置总线宽度(1-bit或4-bit) | 0=1bit, 2=4bit |
| ACMD41 | SD_SEND_OP_COND | SD卡初始化(发OCR,获取能力) | OCR |
| ACMD51 | SEND_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状态
关键细节:
- CMD8是区分SD 1.x和SD 2.0+的分水岭。如果你的代码只支持SD 1.x,将无法使用SDHC/SDXC卡
- ACMD41必须通过CMD55前缀触发(CMD55告诉卡”下一条命令是ACMD”)
- ACMD41的HCS位(Host Capacity Support) 必须置1,否则卡会以为主机只支持SDSC,SDHC卡将拒绝初始化
- 初始化循环需要超时机制,通常设为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 2 | 2 MB/s | 已基本淘汰 |
| Class 4 | 4 MB/s | 低分辨率视频录制 |
| Class 6 | 6 MB/s | 720p视频录制 |
| Class 10 | 10 MB/s | 1080p全高清视频、连拍照片 |
注意:Speed Class标注的是最低持续写入速度,不是最大读取速度。一张标称Class 10的卡,读取速度可能达到95MB/s,但写入保证不低于10MB/s。
4.2 UHS Speed Class(UHS速度等级)
随UHS-I总线引入(SD 3.0),用字母U包围数字表示:
| 等级 | 最低持续写入速度 | 典型应用 |
|---|---|---|
| U1 | 10 MB/s | 1080p实时视频 |
| U3 | 30 MB/s | 4K视频录制(30fps) |
UHS Class的卡同时也会标注传统Speed Class(如U3卡通常也标Class 10)。
4.3 Video Speed Class(视频速度等级)
SD 5.0引入,专为高分辨率视频设计,用字母V加数字表示:
| 等级 | 最低持续写入速度 | 典型应用 |
|---|---|---|
| V6 | 6 MB/s | 标清/720p视频 |
| V10 | 10 MB/s | 1080p全高清视频 |
| V30 | 30 MB/s | 4K @ 60fps视频、VR内容 |
| V60 | 60 MB/s | 8K @ 30fps视频、高码率4K |
| V90 | 90 MB/s | 8K @ 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 | 最低持续写入 |
|---|---|---|---|
| A1 | 1500 | 500 | 10 MB/s |
| A2 | 4000 | 2000 | 10 MB/s |
A2等级需要卡支持命令队列(Command Queue),主机端也需支持相应协议。树莓派等SBC使用A2卡可以显著提升系统响应速度。
五、容量规范:SDSC / SDHC / SDXC / SDUC
SD卡的容量规范与寻址方式密切相关,不同容量卡的底层行为有本质差异。
5.1 容量规范对比
| 规范 | 引入版本 | 容量范围 | 文件系统 | 寻址方式 |
|---|---|---|---|---|
| SDSC (Standard Capacity) | SD 1.0 | 1MB ~ 2GB | FAT12/FAT16/FAT32 | 字节地址(Byte Address) |
| SDHC (High Capacity) | SD 2.0 | 2GB ~ 32GB | FAT32 | 块地址(Block Address,512字节/块) |
| SDXC (eXtended Capacity) | SD 3.0 | 2GB ~ 2TB | exFAT | 块地址(Block Address,512字节/块) |
| SDUC (Ultra Capacity) | SD 5.0 | 2GB ~ 128TB | exFAT | 块地址(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读取:
| 字段 | 长度 | 说明 |
|---|---|---|
| MID | 8 bit | 制造商ID(如SanDisk=0x03,Samsung=0x1B) |
| OID | 16 bit | OEM/Application ID |
| PNM | 40 bit | 产品名(ASCII字符串) |
| PRV | 8 bit | 产品版本 |
| PSN | 32 bit | 产品序列号 |
| MDT | 12 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 SBC | SD模式(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/SDHC | Class 10 | SPI模式 | 成本优先,16GB足够 |
| 树莓派/Linux SBC | SDHC/SDXC | A2, V30 | SD模式(内核驱动) | A2等级显著提升随机IO |
| 4K视频录制 | SDXC | V30/U3 | SD模式 | 64GB起步,V30保证持续写入 |
| 8K专业摄影/电影 | SDXC | V60/V90 | SD模式(UHS-II) | 需要UHS-II卡槽支持 |
| 工业温控/恶劣环境 | SDHC | Class 10 | SPI/SD模式 | 选择工业级(-40°C~85°C) |
| IoT边缘设备 | MicroSD SDHC | Class 10/A1 | SPI模式 | 注意功耗,选低功耗型号 |
小结
SD卡协议经过30年演进,已经发展成一个复杂而完善的存储标准体系。作为嵌入式工程师,理解SD卡协议需要把握以下几个核心维度:
- 两种工作模式:SPI模式(简单低速)和SD模式(复杂高速),根据项目需求选择
- 总线演进路线:从1-bit → 4-bit → UHS-I(DDR) → UHS-II(差分) → SD Express(PCIe),速率从3MB/s跨越到近4GB/s
- 命令体系:CMD0
CMD63 + ACMD0ACMD63,其中初始化流程(CMD0→CMD8→ACMD41→CMD2→CMD3→CMD7)是驱动开发的核心 - 速度等级:三套并行体系(Class/UHS Class/Video Class)+ A等级(随机IO),V等级是视频应用的首选标准
- 容量与寻址:SDSC用字节地址,SDHC/SDXC用块地址——这是嵌入式开发中最容易出错的细节
对于大多数嵌入式项目,SPI模式 + Class 10 SDHC卡就足以满足需求。如果你的项目需要更高性能(如音视频采集、高速数据记录),建议直接使用SDIO接口 + UHS卡,并充分利用Linux内核的SD卡驱动栈。
希望这篇全面解析能帮助你深入理解SD卡协议,在选型和开发中少走弯路。如果有任何问题,欢迎在评论区讨论。