i
目 录
第 1 章 SD/MMC 卡读写模块.....................................................................................1
1.1 SD/MMC 卡的外部物理接口 ..................................................................................1
1.1.1 SD 模式.............................................................................................................2
1.1.2 SPI 模式 ............................................................................................................3
1.2 访问 SD/MMC 卡的 SPI 模式硬件电路设计 .........................................................4
1.2.1 SPI 总线 ............................................................................................................5
1.2.2 卡供电控制.......................................................................................................5
1.2.3 卡检测电路.......................................................................................................5
1.3 SD/MMC 卡读写模块的文件结构及整体构架 ......................................................5
1.3.1 SD/MMC 卡读写模块的文件组成 ..................................................................5
1.3.2 SD/MMC 读写模块整体框架 ..........................................................................6
1.4 SD/MMC 卡读写模块的使用说明 ..........................................................................6
1.4.1 SD/MMC 卡读写模块的硬件配置 ..................................................................6
1.4.2 SD/MMC 卡读写模块提供的 API 函数..........................................................9
1.5 SD/MMC 卡读写模块的应用示例一 ....................................................................11
1.5.1 硬件连接与配置.............................................................................................11
1.5.2 实现方法.........................................................................................................11
1.6 SD/MMC 卡读写模块的使用示例二 ....................................................................18
1.6.1 实现方法.........................................................................................................18
1.6.2 例子建立与运行步骤 .....................................................................................20
1.6.3 参考程序.........................................................................................................24
1.7 SD/MMC 软件包应用总结 ....................................................................................27
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 1 -
第1章 SD/MMC卡读写模块
SD/MMC 卡是一种大容量(最大可达 4GB)、性价比高、体积小、访问接口简单的存
储卡。SD/MMC 卡大量应用于数码相机、MP3 机、手机、大容量存储设备,作为这些便携
式设备的存储载体,它还具有低功耗、非易失性、保存数据无需消耗能量等特点。
SD 卡接口向下兼容 MMC(MutliMediaCard 多媒体卡)卡,访问 SD 卡的 SPI
及
部分命令也适用于 MMC 卡。
SD/MMC 卡读写模块是 ZLG 系列中间件的重要成员之一,又称为 ZLG/SD。该模块
是一个用来访问 SD/MMC 卡的软件读写模块,目前最新版本为 2.00,本版本不仅能读写
SD 卡,还可以读写 MMC 卡;不仅能在前后台系统(无实时操作系统)中使用,还可以在
嵌入式操作系统 μC/OS-II 中使用。本文模块只支持 SD/MMC 卡的 SPI 模式。
在本章中,除了特别说明以外,“卡”都是指 SD 卡或 MMC 卡。
1.1 SD/MMC 卡的外部物理接口
SD 和 MMC 卡的外形和接口触点如图 1.1 所示。其中 SD 卡的外形尺寸为:24mm x
32mm x 2.1mm(普通)或 24mm x 32mm x 1.4mm(薄 SD 存储卡),MMC 卡的外形尺寸为
24mm x 32mm x 1.4mm。
图 1.1 SD 卡和 MMC 卡实物图
图 1.2 SD 卡和 MMC 卡接口示意图(上视图)
1.1 为 SD/MMC 卡各触点的名称及作用,其中 MMC 卡只使用了 1 ~ 7 触点。
表 1.1 SD/MMC 卡的焊盘分配
SD 模式 SPI 模式 引
脚 名称 1 类型 描述 名称 类型 描述
1 CD/DAT32 I/O/PP3 卡的检测/数据线[Bit 3] CS I 片选(低电平有效)
2 CMD PP4 命令/响应 DI I5 数据输入
3 VSS1 S 电源地 VSS S 电源地
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 2 -
续上表
SD 模式 SPI 模式 引
脚 名称 1 类型 描述 名称 类型 描述
4 VDD S 电源 VDD S 电源
5 CLK I 时钟 SCLK I 时钟
6 VSS2 S 电源地 VSS2 S 电源地
7 DAT0 I/O/PP 数据线[Bit 0] DO O/PP 数据输出
8 DAT1 I/O/PP 数据线[Bit 1] RSV
9 DAT2 I/O/PP 数据线[Bit 2] RSV
注:1. S:电源;I:输入;O:推挽输出;PP:推挽 I/O。
2. 扩展的 DAT 线(DAT1 ~ DAT3)在上电后处于输入状态。它们在执行 SET_BUS_WIDTH 命令后
作为 DAT 线操作。当不使用 DAT1 ~ DAT3 线时,主机应使自己的 DAT1~DAT3 线处于输入模式。
这样定义是为了与 MMC 卡保持兼容。
3. 上电后,这条线为带 50KΩ 上拉电阻的输入线(可以用于检测卡是否存在或选择 SPI 模式)。用
户可以在正常的数据传输中用 SET_CLR_CARD_DETECT(ACMD42)命令断开上拉电阻的连接。
MMC 卡的该引脚在 SD 模式下为保留引脚,在 SD 模式下无任何作用。
4. MMC 卡在 SD 模式下为:I/O/PP/OD。
5. MMC 卡在 SPI 模式下为:I/PP。
由表 1.1 可见,SD 卡和 MMC 卡在不同的通信模式下,各引脚的功能也不相同。这里
的通信模式是指微控制器(主机)访问卡时使用的通信协议,分别为 SD 模式和 SPI 模式。
在具体通信过程中,主机只能选择其中一种通信模式。通信模式的选择对于主机来说
是透明的。卡将会自动检测复位命令的模式(即自动检测复位命令使用的协议),而且要
求以后双方的通信都按相同的通信模式进行。所以,在只使用一种通信模式的时候,无需
使用另一种模式。下面先简单介绍这两种模式。
1.1.1 SD 模式
在 SD 模式下,主机使用 SD 总线访问 SD 卡,其总线拓扑结构如图 1.3 所示。由图可
见,SD 总线上不仅可以挂接 SD 卡,还可以挂接 MMC 卡。
图 1.3 SD 存储卡系统(SD 模式)的总线拓扑结构
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 3 -
SD 总线上的信号线的详细功能描述如表 1.2 所示。
表 1.2 SD 总线信号线功能描述
信号线 功能描述
CLK 主机向卡发送的用于同步双方通信的时钟信号
CMD 双向的命令/响应信号
DAT0 ~ DAT3 4 个双向的数据信号(MMC 卡只有 DAT0 信号线)
VDD 电源正极,一般电压范围为 2.7 ~ 3.6V
VSS1、VSS2 电源地
SD 存储卡系统(SD 模式)的总线拓扑结构为: 一个主机(如微控制器)、多个从机(卡)
和同步的星形拓扑结构(参考图 1.3)。所有卡共用时钟 CLK、电源和地信号。而命令线
(CMD)和数据线(DAT0 ~ DAT3)则是卡的专用线,即每张卡都独立拥有这些信号线。
请注意,MMC 卡只能使用 1 条数据线 DAT0。
1.1.2 SPI 模式
在 SPI 模式下,主机使用 SPI 总线访问卡,当今大部分微控制器本身都带有硬件 SPI
接口,所以使用微控制器的 SPI 接口访问卡是很方便的。微控制器在卡上电后的第 1 个复
位命令就可以选择卡进入 SPI 模式或 SD 模式,但在卡上电期间,它们之间的通信模式不
能更改为 SD 模式。
卡的 SPI 接口与大多数微控制器的 SPI 接口兼容。卡的 SPI 总线的信号线如表 1.3 所示。
表 1.3 SD 卡与 MMC 卡的 SPI 接口描述
信号线 功能描述
CS 主机向卡发送的片选信号
CLK 主机向卡发送的时钟信号
DataIn 主机向卡发送的单向数据信号
DataOut 卡向主机发送的单向数据信号
SPI 总线以字节为单位进行数据传输,所有数据令牌都是字节(8 位)的倍数,而且字
节通常与 CS 信号对齐。SD 卡存储卡系统如图 1.4 所示。
图 1.4 SD 存储卡系统(SPI 模式)的总线拓扑结构
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 4 -
当主机外部连接有多张 SD 卡或 MMC 卡时,主机利用 CS 信号线对卡进行寻址。例如:
在图 1.4 中,当主机需要向 SD 存储卡 A 传输数据或需要从该卡接收数据时,必须将 CS(A)
置为低电平(同时其它卡的 CS 信号线必须置为高电平)。
CS 信号在 SPI 处理(命令、响应和数据)期间必须续持有效(低电平)。唯一例外的
情况是在对卡编程的过程。在这个过程中,主机可以使 CS 信号为高电平,但不影响卡的
编程。
由图 1.4 可见,当 SPI 总线上挂接 N 张卡时,需要 N 条 CS 片选线。
1.2 访问 SD/MMC 卡的 SPI 模式硬件电路设计
SD/MMC 卡可以采用 SD 总线访问,也可以采用 SPI 总线访问,考虑到大部分微控制
器都有 SPI 接口而没有 SD 总线接口,而且如果采用 I/O 口模拟 SD 总线,不但增加了软件
的开销,而且对大多数微控制器而言,模拟总线远不如真正的 SD 总线速度快,这将大大
降低总线数据传输的速度。
基于以上的考虑,采用 LPC2103 微控制器的 SPI 接口为例子,设计访问 SD/MMC 卡
的硬件接口电路。LPC2103 微控制器与 SD/MMC 卡卡座接口电路如图 1.5 所示。
图 1.5 SD 卡卡座与 LPC2103 接口电路(SPI 模式)
图中,LPC2103 与 SD/MMC 卡卡座的连接引脚如表 1.4 所示。
表 1.4 LPC2103 与 SD/MMC 卡卡座的连接引脚
LPC2103 接口 含 义
P0.8_CS SPI 片选信号,用于选择 SPI 从机,该引脚为普通 I/O 口
P0.4_SCK SPI 时钟信号,由主机发出,用于同步主机之间的数据传输
P0.6_MOSI SPI 主机输出,从机输入信号
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 5 -
续上表
LPC2103 接口 含 义
P0.5_MISO SPI 主机输入,从机输出信号
P0.9_SD_POWER 卡供电控制,当 LPC2103 的 P0.9 输出低电平时给卡供电
P0.10_SD_INSERT 卡完全插入到卡座中检测线,完全插入时卡座输出低电平,否则输出高电平
P0.11_SD_WP 卡是否写保护检测,写保护时卡座输出高电平,否则输出低电平
注意:对于不同的卡座,卡完全插入检测电平和写保护检测电平可能有所不同。
1.2.1 SPI 总线
如图 1.5 所示,LPC2103 SPI 接口的 P0.8_CS、P0.4_SCK、P0.6_MOSI、P0.5_MISO 直
接连接到卡座的相应接口,其中 SPI 的两个数据线 P0.6_MOSI、P0.5_MISO 还分别接上拉
电阻,这是为了使本电路可以与 MMC 卡的接口兼容。SPI 模式下无需用到的信号线 DAT2
和 DATA1 分别接下拉电阻。
1.2.2 卡供电控制
卡的供电采用可控方式,这是为了防止 SD/MMC 卡进入不确定状态时,可以通过对卡
重新上电使卡复位而无需拔出卡。
可控电路采用 P 型 MOS 管 2SJ355,由 LPC2103 的 GPIO 口 P0.9_SD_POWER 进行控
制,当 P0.9_SD_POWER 输出高电平时,2SJ355 关断,不给卡供电;当 P0.9_SD_POWER
输出低电平时,2SJ355 开通,VCC3.3 电源(电压为 3.3V)给卡供电。
采用 2SJ355 的目的是当它开通时,管子上的压降比较小。2SJ355 的相关特性请见其
数据手册。用户也可以采用其它 P 型的 MOS 管,但是要考虑管子开通时,漏极与源极之
间的压降要足够小(保证 SD/MMC 卡的工作电压在允许范围内),管子允许通过的电流也
要满足卡的要求,一般一张 SD/MMC 卡工作时的最大电流通常为 45mA 左右,所以选用的
MOS 管要求允许通过 100mA 左右的电流。
1.2.3 卡检测电路
卡检测电路包括两部分:卡是否完全插入到卡座中和卡是否写保护。
检测信号由卡座的两个引脚以电平的方式输出。当卡插入到卡座并插入到位时,
P0.10_CARD_INSERT(第 10 脚)由于卡座内部触点连接到 GND,输出低电平;当卡拔出
时,该引脚由于上拉电阻 R2 的存在而输出高电平,该输出由 LPC2103 的输入引脚
GPIO(P0.10_SD_INSERT)来检测。
卡是否写保护的检测与卡是否完全插入到卡座中的检测原理是一样的。
1.3 SD/MMC 卡读写模块的文件结构及整体构架
本小节介绍本模块的组成文件以及它们之间的关系。
1.3.1 SD/MMC 卡读写模块的文件组成
SD/MMC 卡读写模块包括的文件如表 1.5 所示。
表 1.5 SD/MMC 卡读写模块包含的文件
文 件 作 用
sdconfig.h 卡读写模块硬件配置头文件
sdspihal.c 读写模块硬件抽象层,实现 SPI 接口初始化,SPI 字节的收、发等与 SPI 硬件相关的函数
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 6 -
续上表
文 件 作 用
sdspihal.h sdspihal.c 头文件
sdcmd.c 读写模块命令层,实现卡的各种命令以及主机与卡之间的数据流控制
sdcmd.h sdcmd.c 头文件
sddriver.c 读写模块应用层,实现卡的读、写、擦 API 函数,该文件还包含一些卡操作函数
sddriver.h sddriver.c 头文件,包括函数执行错误代码
sdcrc.c 卡相关的 CRC 运算函数
sdcrc.h sdcrc.h 头文件
表 1.5 中这些文件构成了本模块,下面说明由这些文件构成的整体框架。
1.3.2 SD/MMC 读写模块整体框架
考虑到该模块的可移植性及易用性,将模块分为 3 个层,如图 1.6 所示。图中的实时
操作系统并不是必须的,也就是说,本模块既可以应用于前后台系统(无实时操作系统),
也可以应用于实时操作系统中,本模块提供在前后台系统和实时操作系统 μC/OS-II 中接口
统一的 API 函数。
是否使用实时操作系统由本模块 sdconfig.h 文件中的宏定义 SD_UCOSII_EN 来使能或
禁止。
图 1.6 SD/MMC 卡读写模块结构图
各层的特点如下:
(1) 硬件抽象层:读写 SD/MMC 卡的硬件条件配置,与硬件相关的函数;
(2) 命令层:SD/MMC 卡的相关命令以及卡与主机之间数据流的控制,这一层与硬件
无关;
(3) 应用层:向用户应用程序或文件系统提供操作卡的 API 函数。如果采用操作系统,
这一层由实时操作系统控制。
1.4 SD/MMC 卡读写模块的使用说明
使用本模块之前,必须配置好本模块使用的硬件条件,如果硬件条件与 1.2 小节中的
硬件条件一样,那么无须配置本软件包就可以立即使用。下面说明怎样配置本模块的硬件
条件,才能将其用于 LPC2103 系列微控制器。
1.4.1 SD/MMC 卡读写模块的硬件配置
SD/MMC 卡读写模块在 LPC2103 的配置只与 sdconfig.h 文件相关,配置头文件
sdconfig.h 使用户能方便地配置本模块的相关功能及裁剪某些对用户来说无需用到的函数。
该小节提到的所有程序清单都在该文件上。下面阐述该头文件的配置方法。
1. 模块参数配置
模块的参数配置如程序清单 1.1 所示,配置选项如下:
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 7 -
(1) 是否运行于 μC/OS-II 中。本模块既可以运行于前后台系统中,又可以运行于实时
操作系统 μC/OS-II 中。当运行于 μC/OS-II 中时,宏定义 SD_UCOSII_EN 的值应
置为 1,否则应置为 0。
(2) CRC 校验。由于 SD/MMC 卡在 SPI 通信模式下可以不需要进行数据传输的 CRC
校验,该宏用于使能或禁止本读写模块的数据传输 CRC 校验功能。使能 CRC 校
验则通信可靠性更高,但 CRC 运算也带来传输速度的一些损失,由于本模块采用
查表的方法计算 CRC16,所以速度只是略有损失。
(3) SPI 时钟频率。定义 SPI 总线的 CLK 线的频率,该频率值用于计算读、写、擦操
作中的超时时间对应的 CLK 个数,这样就将超时时间转换为超时计数。该频率值
的单位为:Hz,该值需要用户定义。
(4) SD/MMC 卡块的长度。定义 SD/MMC 卡块的最大长度,当今流行的 SD/MMC 卡
块的最大长度大部分都支持 512 字节。宏定义 SD_BLOCKSIZE_NBITS 值为 9,
对 应 于 29 = 512 字 节 ( 对 应 于 宏 定 义 SD_BLOCKSIZE 的 值 ),
SD_BLOCKSIZE_NBITS 与 SD_BLOCKSIZE 一定要有这样的对应关系。
SD_BLOCKSIZE_NBITS 参数用于固件程序数据计算的方便。用户一般无须改动
这两个宏定义的值。
程序清单 1.1 模块参数配置
#define SD_UCOSII_EN 1 /* 是否在 μC/OS-II 上运行本模块 */
#define SD_CRC_EN 0 /* 设置数据传输时是否使用 CRC */
#define SPI_CLOCK 5529600 /* 正常通信时,SPI 时钟频率(Hz) */
#define SD_BLOCKSIZE 512 /* SD/MMC 卡块的长度 */
#define SD_BLOCKSIZE_NBITS 9 /* 2 的 9 次方为 512(即 SD_BLOCKSIZE 的值)*/
2. 功能配置
模块中有一些功能不是所有用户都可能用到的,所以可以裁剪去不需要的函数,以减
小其代码量。程序清单 1.2 的宏定义用于使能编译读写模块中的某些比较少用的函数,当
取值为 1 时,使能编译对应的函数;为 0 时,禁止编译对应的函数。这些宏定义起到裁剪
读写模块代码大小的目的。
程序清单 1.2 模块函数使能
/* 下面函数不常用,如果用户不需要,可置为 0 裁剪指定函数 */
#define SD_ReadMultiBlock_EN 0 /* 是否使能读多块函数 */
#define SD_WriteMultiBlock_EN 0 /* 是否使能写多块函数 */
#define SD_EraseBlock_EN 0 /* 是否使能擦卡函数 */
#define SD_ProgramCSD_EN 0 /* 是否使能写 CSD 寄存器函数 */
#define SD_ReadCID_EN 0 /* 是否使能读 CID 寄存器函数 */
#define SD_ReadSD_Status_EN 0 /* 是否使能读 SD Status 寄存器函数 */
#define SD_ReadSCR_EN 0 /* 是否使能读 SCR 寄存器函数 */
3. 硬件条件配置
这部分以宏的形式对卡的 SPI 口和 IO 口相关操作进行定义,尽可能地将硬件相关的部
分放于这一部分。例如,配置 LPC2103 的 4 个 I/O 口为 SPI 接口的宏定义如程序清单 1.3(1)
所示。对于 SD 卡卡座供电引脚的控制如程序清单 1.3(2)所示。用户阅读 LPC2103 的数据
手册就可以了解这些配置的含义。该文件还包括对其它 IO 口的配置,详见 sdconfig.h 文件。
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 8 -
程序清单 1.3 LPC2103 的 IO 口配置宏定义
/* 初始化 IO 口为 SPI 接口 */
#define SPI_INIT() PINSEL0 &= ~((0x03 << 8) + (0x03 << 10) + (0x03 << 12)); \
PINSEL0 |= (0x01 << 8) + (0x01 << 10) + (0x01 << 12); (1)
/* 电源控制引脚 */ (2)
#define SD_POWER (0x01 << 9)
#define SD_POWER_GPIO() PINSEL0 &= ~(0x03 << 18) /* 设置 POWER 口为 GPIO 口 */
#define SD_POWER_OUT() IODIR |= SD_POWER /* 设置 POWER 口为输出口 */
#define SD_POWER_OFF() IOSET = SD_POWER /* 置 POWER 为高电平 */
#define SD_POWER_ON() IOCLR = SD_POWER /* 置 POWER 为低电平 */
配置头文件的全部
就介绍到此,如果要将本模块移植到其它 MCU,则还需修改
sdhal.c 文件,这一部分与 MCU 的 SPI 接口操作相关,如果使用 LPC2103,那么无须改动
该文件。
还有一点容易忽略的,就是必须将 LPC2103 的外设时钟频率 Fpclk 调至最高(在允许
范围内),这样,读写模块的读定速度才能达到最高。而且 SD/MMC 卡的 SPI 总线协议中,
要求 SPI 主机必须能够控制 SPI 总线的时钟频率。LPC2103 对 SPI 总线时钟的控制函数说
明如下。
4. 设置 SPI 接口的时钟频率小于 400kHz
该函数主要是在 SD/MMC 卡初始化阶段,用于设置 SPI 接口的时钟频率小于 400kHz,
因为 MMC 卡在初始化期间 SPI 总线的时钟频率不能高于 400kHz,这样本模块才能达到兼
容 MMC 卡的目的。该函数如程序清单 1.4 所示(见 sdhal.c 文件)。该函数只是修改 LPC2103
SPI 接口的 SPI 时钟计数寄存器 SPI_SPCCR 的分频值来达到目的。
程序清单 1.4 设置 SPI 接口的时钟频率小于 400kHz
void SPI_Clk400k(void)
{
SPI_SPCCR = 128; /* 设置 SPI 时钟分频值为 128 */
}
如果 LPC2103 的外部晶振频率 Fosc = 11.0592MHz,内核时钟频率 Fcclk 设置为 Fosc
的 4 倍,即 Fcclk = 44.2368 MHz。外设时钟频率设置为与内核时钟频率相同,即 Fpclk =
Fcclk = 44.2368 MHz,那么 SPI 总线的时钟为 Fpclk 经过 SPI_SPCCR 寄存器分频后的时钟。
所以,要使 SPI 接口的时钟频率少于 400kHz,同时又要保证 SPI_SPCCR 寄存器的值为大
于 8 的偶数,该寄存器的分频值要设为 128。
得到的 SPI 接口 SCK 的频率为:
44.2368 / 128 = 0.3456 MHz = 345.6kHz < 400kHz。
同样,如果要设置 SCK 的频率为最大值,只须调用 void SPI_ClkToMax(void)函数(见
sdhal.c 文件),该函数只是将 SPI_SPCCR 的值改为 8,那么得到 SCK 的频率为:
44.2368 / 8 = 5.5296MHz。
需要注意,当今流行的 SD/MMC 卡的 SPI 接口的时钟频率一般不允许超过 25MHz,
所以在定义 MCU 访问 SD/MMC 卡的时钟频率时,必须注意这一点。
如果读者的外部晶振频率 Fosc 或 LPC2103 外设时钟频率 Fpclk 改变了,请注意修改这
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 9 -
两个函数中的分频值,来优化读写模块对卡的访问速度。
配置好了硬件,那么可以使用本模块了,那么本模块提供了哪些 API 函数方便用户访
问 SD/MMC 卡?下面介绍这些 API 函数的接口。
1.4.2 SD/MMC 卡读写模块提供的 API 函数
用户可以利用本模块提供的 API 函数对 SD/MMC 卡进行访问,见表 1.6 至表 1.11。
表 1.6 SD_Initialize()
函数名称 SD_Initialize
函数原型 INT8U SD_Initialize(void)
功能描述 初始化 SD/MMC 卡、设置块大小为 512 字节,获取卡的相关信息
函数参数 无
函数返回值 SD_NO_ERR:初始化成功; > 0: 初始化失败(错误码,见表 1.12)
特殊说明
和注意点
该函数设置了卡的读/写块长度为 512 字节
表 1.7 SD_ReadBlock ()
函数名称 SD_ReadBlock
函数原型 INT8U SD_ReadBlock(INT32U blockaddr, INT8U *recbuf)
功能描述 读 SD/MMC 卡的一个块
函数参数
blockaddr:以块为单位的块地址。例如,卡开始的 0 ~ 511 字节为块地址 0,512 ~ 1023
字节的块地址为1
recbuf: 接收缓冲区,长度固定为 512 字节
函数返回值 SD_NO_ERR:读成功; > 0: 读失败(错误码,见表 1.12)
特殊说明
和注意点
recbuf 的长度必须是 512 字节
表 1.8 SD_WriteBlock()
函数名称 SD_WriteBlock
函数原型 INT8U SD_WriteBlock(INT32U blockaddr, INT8U *sendbuf)
功能描述 写 SD/MMC 卡的一个块
函数参数
blockaddr:以块为单位的块地址。例如,卡开始的 0 ~ 511 字节为块地址 0,512 ~ 1023
字节的块地址为1
sendbuf: 发送缓冲区,长度固定为 512 字节
函数返回值 SD_NO_ERR:写成功; > 0: 写失败(错误码,见表 1.12)
特殊说明
和注意点
sendbuf 的长度必须是 512 字节
表 1.9 SD_ReadMultiBlock()
函数名称 SD_ReadMultiBlock
函数原型 INT8U SD_ReadMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *recbuf)
功能描述 读 SD/MMC 卡的多个块
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 10 -
续上表
函数参数
blockaddr: 以块为单位的块地址
blocknum: 块数
recbuf: 接收缓冲区,长度为 512 * blocknum 字节
函数返回值 SD_NO_ERR:读成功; > 0: 读失败(错误码,见表 1.12)
特殊说明
和注意点
使用时必须将 sdconfig.h 中的宏定义值 SD_ReadMultiBlock_EN 置为1
表 1.10 SD_WriteMultiBlock ()
函数名称 SD_WriteMultiBlock
函数原型 INT8U SD_WriteMultiBlock(INT32U blockaddr, INT32U blocknum, INT8U *sendbuf)
功能描述 读 SD/MMC 卡的多个块
函数参数
blockaddr:以块为单位的块地址
blocknum:块数
sendbuf: 发送缓冲区,长度为 512 * blocknum 字节
函数返回值 SD_NO_ERR:写成功; > 0: 写失败(错误码,见表 1.12)
特殊说明
和注意点
使用时必须将 sdconfig.h 中的宏定义值 SD_WriteMultiBlock_EN 置为1
表 1.11 SD_EraseBlock()
函数名称 SD_EraseBlock
函数原型 INT8U SD_EraseBlock(INT32U startaddr, INT32U blocknum)
功能描述 擦除 SD/MMC 卡的多个块
函数参数
startaddr: 以块为单位的块擦除起始地址
blocknum:块数(取值范围 1 ~ sds.block_num)
函数返回值 SD_NO_ERR:擦除成功; > 0: 擦除失败(错误码,见表 1.12)
特殊说明
和注意点
使用时必须将 sdconfig.h 中的宏定义值 SD_EraseBlock_EN 置为1。Startaddr 和 blocknum
建议为 sds.erase_unit 的整数倍, 因为有的卡只能以 sds.erase_unit 为单位进行擦除
其它函数不常用,这里就不一一列出了。需要用到其它函数的读者可以阅读源码中的
函数说明。表 1.6 至表 1.11 函数返回值所代表的含义如表 1.12 所示。
表 1.12 错误代码列表
错误码宏定义 宏定义值 含义
SD_NO_ERR 0x00 函数执行成功
SD_ERR_NO_CARD 0x01 卡没有完全插入到卡座中
SD_ERR_USER_PARAM 0x02 用户使用 API 函数时,入口参数有错误
SD_ERR_CARD_PARAM 0x03 卡中参数有错误(与本模块不兼容)
SD_ERR_VOL_NOTSUSP 0x04 卡不支持 3.3V 供电
SD_ERR_OVER_CARDRANGE 0x05 操作超出卡存储器范围
SD_ERR_UNKNOWN_CARD 0x06 无法识别卡型
SD_ERR_CMD_RESPTYPE 0x10 命令类型错误
SD_ERR_CMD_TIMEOUT 0x11 命令响应超时
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 11 -
续上表
错误码宏定义 宏定义值 含义
SD_ERR_CMD_RESP 0x12 命令响应错误
SD_ERR_DATA_CRC16 0x20 数据流 CRC16 校验不通过
SD_ERR_DATA_START_TOK 0x21 读单块或多块时,数据开始令牌不正确
SD_ERR_DATA_RESP 0x22 写单块或多块时,卡数据响应令牌不正确
SD_ERR_TIMEOUT_WAIT 0x30 写或擦操作时,发生超时错误
SD_ERR_TIMEOUT_READ 0x31 读操作超时错误
SD_ERR_TIMEOUT_WRITE 0x32 写操作超时错误
SD_ERR_TIMEOUT_ERASE 0x33 擦除操作超时错误
SD_ERR_TIMEOUT_WAITIDLE 0x34 初始化卡时,等待卡退出空闲状态超时错误
SD_ERR_WRITE_BLK 0x40 写块数据错误
SD_ERR_WRITE_BLKNUMS 0x41 写多块时,想要写入的块与正确写入的块数不一致
SD_ERR_WRITE_PROTECT 0x42 卡外壳的写保护开关打在写保护位置
SD_ERR_CREATE_SEMSD 0xA0 创建访问卡的信号量失败
下面给出使用 SD/MMC 卡读写模块的一个例子。
1.5 SD/MMC 卡读写模块的应用示例一
下面给出在 LPC2103 微处理器上使用 SD/MMC 卡读写模块对 SD/MMC 卡进行读、写
数据的例子。该例子利用 LPC2103 提供的 SPI 接口读写 SD/MMC 卡,并将写入的数据读
出后与原始数据做比较,验证读写操作的正确性。
1.5.1 硬件连接与配置
用杜邦线将 EasyARM2103 与 SD CARD PACK 连接起来,连线方法如表 1.13 所示。
表 1.13 EasyARM2103 与 SD CARD PACK 连接关系
EasyARM2103(JP5) SD CARD PACK 引脚(J1) 引线含义
3.3V 3.3V SD CARD PACK 供电电源
GND GND 电源地
P0.9 POW_C 控制 3.3V 电源供给卡
P0.8 CS 选择 SD/MMC 卡
P0.6 MOSI 主机 SPI 数据输出,卡 SPI 数据输入
P0.4 SCK SPI 总线时钟
P0.5 MISO 主机 SPI 数据输入,卡 SPI 数据输出
P0.10 INSERT 卡完全插入卡座检测
P0.11 WP 卡写保护机械开关检测
SD/MMC 卡读写模块默认的硬件配置和表 1.13 的硬件条件相符。因此,不需要对读写
模块进行配置。
1.5.2 实现方法
本例子将对 SD/MMC 卡进行读、写和擦除等常用操作。例子的软件结构如图 1.7 所示。
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 12 -
图 1.7 主函数流程图
SD 卡应用示例主函数如程序清单 1.5 所示。
程序清单 1.5 SD 卡操作主函数代码
int main (void)
{
uint32 i;
uint8 status;
uint8 sdbuf[512]={0}; /* 存放写入数据缓冲区 */
uint8 sdbuf2[512]={0}; /* 存放读出数据缓冲区 */
PINSEL1 = 0x00000000; /* 设置管脚连接 GPIO */
IO0DIR |= BEEP; /* 设置 BEEP 控制口为输出 */
IO0SET = BEEP;
for(i=0;i<512;i++){ /* 初始化写入数据 */
sdbuf[i] = i&0xff;
}
status = SD_Initialize(&sds); /* SD 初始化 */
if (status != SD_NO_ERR){
while(1);
}
status = SD_WriteBlock(&sds,0,sdbuf); /* 将 sdbuf 缓冲区数据写入第 0 块中*/
if (status != SD_NO_ERR){
while(1);
}
status = SD_ReadBlock(&sds,0,sdbuf2); /* 读第 0 块的数据 */
if (status != SD_NO_ERR){
while(1);
}
status = memcmp(sdbuf,sdbuf2,512); /* 对 sdbuf2 与 sdbuf 的内容进行比较*/
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 13 -
if(status!=0){ /* 数据比较错误,蜂鸣器蜂鸣三声 */
BeepOnOff(3);
}
else{ /* 数据比较正确,蜂鸣一声 */
BeepOnOff(1);
}
while(1);
return 0;
}
下文将对程序清单 1.5 中的 SD 卡初始化、SD 卡单块读和单块写等常用命令进行简要
分析讲解。
1. SD 卡初始化
SD 卡初始化流程如图 1.8 所示,首先初始化访问卡的硬件条件,SdSpiHal_Initialize
()函数代码如程序清单 1.6 所示。
程序清单 1.6 初始化卡访问卡的硬件条件
INT8U SdSpiHal_Initialize(sd_struct *sds)
{
SD_Power(); /* 对卡先下电,再上电 */
SPI_INIT(); /* 初始化 SPI 接口 */
SD_INSERT_GPIO();
SD_INSERT_IN(); /* 检测卡完全插入口为输入口 */ (1)
SD_WP_GPIO();
SD_WP_IN(); /* 写保护检测口为输入口 */ (2)
SPI_CS_SET(); /* CS 置高 */
SdSpiHal_SetMCIClock(sds, SD_RATE_SLOW); /* 设置 SPI 频率小于等于 400kHZ */
SPI_SPCR = 0 << 3 | /* CPHA = 0 第一个时钟采样 */
1 << 4 | /* CPOL = 1,SCK 低有效 */
1 << 5 | /* MSTR = 1,设置为主模式 */
0 << 6 | /* LSBF = 0,SPI 传输 MSB 在先 */
0 << 7 ; /* SPIE = 0,SPI 中断禁止 */
return SD_NO_ERR;
}
对 SD 卡先下电,再上电后,对 SPI 总线接口进行初始化。程序清单 1.6(1)将用于
检测卡是否完全插入的卡座的 I/O 引脚初始化为 GPIO,并且设置为输入口。程序清单 1.6
(2)将用于检测卡是否写保护的 I/O 引脚初始化为 GPIO,并且设置为输入口。
设置 SPI 的 SCK 引脚输出频率小于等于 400KHz,是因为 MMC 卡在复位阶段要求 SPI
的时钟频率要小于等于 400KHz。
注意:在本软件包中没有用到 LPC2103 的 SPI 模块的 P0.7(SPI 从机选择输入)引脚,由于芯片特
性要求,在 LPC2103 的 SPI 模块不充当从机时,不需要将此引脚初始化为 SPI 模式,如果初始化,SPI
模块将自动转入从机模式。
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 14 -
图 1.8 SD 卡初始化流程
卡完全插入卡座与卡写保护检测只须检测相关 I/O 口的电平即可。卡完全插入卡座检
测函数如程序清单 1.7 所示。该函数返回 0 表示卡未完全插入,此时,SD/MMC 卡读/写
软件包不能对卡进行操作。当卡完全插入时,P0.10_SD_INSERT 引脚输出低电平。
程序清单 1.7 卡完全插入卡座检测函数
INT8U SdHal_CheckCard(sd_struct *sds)
{
if (SD_INSERT_STATUS() != 0)
return 0; /* 未完全插入 not insert entirely */
广州致远电子有限公司 Tel:(020)38730976 38730977 Fax:38730925 http://www.zlgmcu.com
- 15 -
else
return 1; /* 完全插入 insert entirely */
}
对于 SD 卡初始化流程中的其它操作如复位卡进入空闲状态、激活卡进入初始化以及
设置块长度读取卡信息等操作,是访问应用 SD/MMC 卡前规定必须要进行的准备性工作,
只有获取相应的信息,并将卡设置为合适的状态,才可对卡进行读写访问。
2. SD 卡单块写操作
SD/MMC 卡在 SPI 模式下的写操作包括两种:写单块和写多块。本示例重点介绍写单
块操作。卡初始化函数 SD_Initialize()已经调用了 SpiCmd_Set_BlockLen()函数设定了读/写
数据块的长度 SD_BLOCKSIZE 字节,卡在初始化后,读/写都是以块为单位,一次写操作
至少要写 SD_BLOCKSIZE 字节。SD_BLOCKSIZE 字节一般都为 512 字节。
SD 卡单块写操作流程图如图 1.9 所示。写单块是这样进行的:
图 1.9 SD 卡单块写操作流程图
(1) 主机检测卡是否完全插入到卡座中;
(2) 主机检测卡是否写保护;
(3) 以上条件满足后,主机向卡发送