一、概要

前段时间公司提出需求需要在EFR32BG22上用到TF卡,但是并不着急,然后以我的性格而言,你要么不说,这一说出扣我就手痒,于是,就。。。。。。

对于SD/TF卡而言,有两种驱动方式:SDIO和SPI,前者更适合SD卡的驱动,更加稳定、快速和方便。但是对于EFR32BG22来说,并没有SDIO的硬件接口,这里只能用SPI来驱动它。

EFR32自带硬件SPI,之前也用它来驱动过ADS1220(一款TI的24位ADC芯片),有兴趣的可以过去看看:
ADS1220驱动代码
可能因为理解不够,在用硬件SPI驱动SD卡的时候,一直无法初始化通过,死在了ACMD41指令处,一直返回0x01,经过很多测试,甚至有投机取巧的方式,看上去是初始化过去了,但是在后面一直无法对SD卡进行正常读写,期间还把一块SD卡写坏了。

在这里特别声明一下,切勿直接对SD卡进行写操作(读操作无所谓),否则很容易将SD卡写坏。

后面我尝试直接用GPIO模拟SPI,时间已经是凌晨两点,可喜的是,竟然一次性过了。

既然搞了,就把SD卡相关的东西,搞深一点吧,下面记录一下SD卡相关的知识。

本文将分为三个部分学习记录:
(1)SD介绍,包括文档相关协议介绍:SD卡引脚排布即功能、相关寄存器以及命令格式;
(2)SD卡程序初始化流程以及读写;
(3)FATFS文件系统。

如果您觉得自己对SD卡有了一定的掌握,可以直接跳到下一篇,感谢批评指正:
SD/TF卡驱动(二)--------SD卡程序初始化流程以及读写

二、SD卡相关介绍

1.基本介绍

SD卡,中文名叫安全数码卡,由日本松下、东芝和美国SanDisk公司在1999年8月共同开发研制。2g重的他们容量却可以达到32GB以上。

SD卡按照容量分,可分为3类:SD卡、SDHC卡和SDXC卡
SD卡:0~2G
SDHC卡:2G~32G
SDXC卡:32G~2T
前面两种卡协议基本一致,但是SDXC卡协议就相差很大了。对于我们一般嵌入式设备而言,一般32G以下就基本够用了,所以下面大多都是介绍SD卡和SDHC卡的。

前面已经说过,SD卡的驱动一般可以有两种方式:
①SD模式(SDIO驱动)
②SPI模式
嵌入式主机可以任意选择两种中的一种进行通信,与SDIO相比,SPI最大的软肋就是速度问题,但是对于一般的设备而言,SPI的速度也足够满足日常要求。(STM32F103用SPI驱动SD卡,速度可以达到每秒2MByte的速度)。

需要说明的是,有任何问题,请查看SD卡协议文档,本文所有的说明皆出自这份文档说明:
SD卡协议文档

2.SD卡引脚排布及功能描述

SD卡的引脚排布如下:
在这里插入图片描述
其引脚功能描述如下所示(不知道为啥,没办法贴图,凑合看):

针脚        1 		2		3		4		5		6		7		8		9
SDIO模式	CD/DAT3 CMD		VSS		VCC		CLK		VSS		DAT0	DAT1	DAT2
SPI模式		CS		MOSI	VSS 	VCC		CLK		VSS		MISO	NC		NC

上面的VCC只能使用3.3V,注意,切勿使用5V,各个引脚电平IO只支持3.3V。在SPI模式下,四个控制引脚都必须加10~100K的上拉电阻。若你的MCU引脚电平输出不是3.3V,可以参考下面的电路进行电平转换(注意不要照搬照抄,下面图片展示的是3.3V–>5V):
IO电平转换

3.SD卡相关寄存器及命令格式

(1)SD卡一共有5个寄存器,其描述如下:

寄存器名		宽度		描述
CID 		128 	卡的识别码:用于识别单个卡的编号。
RCA 		16		卡的相对地址(这个寄存器在SPI模式下不可用)
CSD 		128 	卡的特性数据:是关于这个卡工作条件的相关信息,卡的容量等信息就保存在这个寄存器中
SCR 		64 		SD配置寄存器:关于这个SD卡的特殊功能的特性信息。
OCR 		32		工作条件寄存器(电压)

(2)命令格式
SD卡的命令格式在SD卡协议文档中有详细说明如下所示:
在这里插入图片描述
翻译下来如下:

字节1		  	字节2~5			字节6
7 6 5……0		31……0			7~1 0
0 1 command		命令参数			CRC 1

①SD卡的指令由6个字节组成,字节1的高两位固定为0 1,低六位为command,后续在代码中会讲到这一点。
②字节2~5为命令参数,需要注意的是,有些命令是没有参数的。
③字节6的高七位为CRC校验值,具体的计算方法有兴趣的可以查一下,挺复杂的,最低一位固定为1。

SD卡的命令总共有12类,有兴趣的可以看看协议文档P20:

在SPI模式下,并不是所有命令都支持,而且可以用的命令也不是都能用上(可参照协议文档P90),从大多数的资料来看,常用的就以下几个(为区分SPI模式还是SDIO模式):

命令			参数					回复			描述
CMD0		无			  		R1			复位SD卡
CMD8		VHS+CHeck pattern	R7			发送接口状态命令(确定工作电平等)
CMD9		无					R1			读取卡特定数据寄存器
CMD10		无					R1			读取卡特定标志寄存器
CMD16		块大小				R1  		设置块大小
CMD17		地址				R1			读取一个块数据
CMD24		地址				R1			写入一个块数据
CMD41		无					R3			发送给主机容量支持信息和激活卡初始过程
CMD55		无					R1			告诉SD卡,下一个是特定应用命令
CMD58		无					R3			读取OCR寄存器

注意:SPI模式下,上面的命令中CMD41命令保留,不被支持,而支持的是ACMD41(A开头的CMD为特定应用程序的命令)
上面的命令中,CMD0、CMD8、CMD16、CMD41、CMD55、CMD58都是初始化中用到的。R1、R3和R7则是卡的回应,他们表示什么意思呢?我们找到SD卡协议文档P95看下:
Response R1:
在这里插入图片描述
Response R3:
在这里插入图片描述
当主机发来CMD58(READ_OCR)命令时,SD卡回复它R3格式数据,R3格式下有5byte,最高位byte为R1格式(如上),后面是四个字节为OCR寄存器值(一个32位的工作条件寄存器,与电压有关,感兴趣的可以看文档P74)。

Response R7:
在这里插入图片描述
当主机发送CMD8命令后,SD卡回复R7格式数据,一样是5byte,最高位byte为R1格式的数据,剩余四位如上图所示。这是检测SD卡是否支持哪个SD卡协议(2.0?1.0?)以及工作电压范围。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐