一、SPI 方式驱动 SD 卡的方法
SD 卡的 SPI 通信接口使其可以通过 SPI 通道进行数据读写。从应用的角度来看,采用 SPI 接口的好处在于,很多单片机内部自带 SPI 控制器,不光给开发上带来方便,同时也见降低了开发成本。然而,它也有不好的地方,如失去了 SD 卡的性能优势,要解决这一问题,就要用 SD 方式,因为它提供更大的总线数据带宽。SPI 接口的选用是在上电初始时向其写入第一个命令时进行的。以下介绍 SD 卡的驱动方法,只实现简单的扇区读写。
为了使SD卡初始化进入SPI模式,我们需要使用的命令有3个CMD0,CMD55,ACMD41(使用ACMD类的指令前应先发CMD55,CMD55起到一个切换到ACMD类命令的作用
为什么在使用CMD0以后不使用CMD1?CMD1是MMC卡使用的指令。我们上电或者发送CMD0后,应该首先发送CMD55+ACMD41确认是否有回应,如果有回应则为SD卡,如果等回应超时,则可能是MMC卡,再发CMD1确认。
二、SD卡调试步骤:
1.上电时要延时足够长的时间给SD卡一个准备的过程,SD卡初始化第一步发送CMD命令之前,在片选有效的情况下首先要发送至少74个时钟,否则可能会出现SD卡不能初始化的问题。那么为什么要74个CLK呢?因为在上电初期,电压的上升过程据SD卡组织的计算约合64个CLK周期才能到达SD卡的正常工作电压他们管这个叫做Supply ramp up time,其后的10个CLK是为了与SD卡同步,之后开始CMD0的操作,严格按照此项操作,一定没有问题。
2.SD卡发送CMD0命令,返回状态为0x01,则复位成功。
3.SD卡发送复位命令CMD0后,要发送版本查询命令CMD8,返回状态一般分为两种,若返回0x01,表示此SD卡接收CMD8,也就是说SD卡支持版本2;若返回0x05则表示SD卡支持版本1.
4.理论上要求发送CMD58获得SD卡电压参数,但实际上都实现知道SD卡的工作电压是3.3v,所以可以省略这一步。
5.发送CMD55命令,返回0x01,起到转换的作用。
6.再发送ACMD41,等待返回0x00,则表示完成初始化。这里要说的是如果最后的回应内容还是0x01的话,可以循环发送CMD55+ACMD41,直到回应的内容0x00
三、SD卡操作命令作步骤:
1.读步骤:
发送CMD17(单块)或CMD18(多块)读命令,返回0x00
接收数据开始令牌0xfe(或0xfc)+正式数据512B+CRC校验2B
2.写步骤:
发送CMD24(单块)或CMD25(多块)写命令,返回0x00.
发送数据开始令牌0xfe(或0xfc)+正式数据512B+CRC校验2B
3.擦除步骤:
发送CMD32,跟一个参数来指定首个要擦除的起始地址
发送CMD33,指定最后的地址
发送CMD38,擦除指定区间的内容。
向SD卡写入一个CMD或者ACMD指令的过程是这样的:
1.首先使CS为低电平,SD卡使能;其次在SD卡的Din写入指令;写入指令后还要附加8个填充时钟,是SD卡完成内部操作;之后在SD卡的Dout上接受回应;回应接受完毕使CS为低电平,再附加8个填充时钟。
2.在SD卡的Din没有数据写入时,应使Din保持高电平。
四、一些常用的指令格式:
CMD0:0x40,0x00,0x00,0x00,0x00,0x95
CMD8:0x48,0x00,0x00,0x01,0xaa,0x87
CMD55:0x77,0x00,0x00,0x00,0x00,0xff 0x77=0x40+0x37(55的16进制表示) ACMD41:0x69,0x40,0x00,0x00,0x00,0xff
CMD58:0x7a,0x00,0x00,0x00,0x00,0xff
ACMD41属于附加命令,发送起来要麻烦一些,必须提前通知SD卡下一条要发送的命令为ACMD,这个通知就是CMD55,它的4字节参数都为0即可。
五、SD卡的命令格式:
每一个命令的长度都是固定的6个字节,前1个字节的值=命令号+0x40;中间4个字节为参数,不同的命令参数格式都不相同,但参数最多为4个字节;最后1个字节是CRC校验码和1位固定结束位‘1’。这里需要说明一下0x40的意思,任何命令都有一个固定的起始格式,即先0后1,这是固定的命令起始标志,前两个字节的二进制码就是:01xx xxxx SD 卡所有的命令都是由 48 个数据位组成的,其结构如表 2 所示。
需要特殊说明的是CRC的问题,这是一种检验错误的方法,具体问题度娘说的还算明白,在SPI模式中,CRC校验默认是关闭的,也就是说这7位必须要发,但是SD卡会在读到CRC以后自动忽略它,所以全部发1就可以。例外的是,CMD0,CMD8这两个命令发送的时候SD卡还没有进入SPI模式,也就是说CRC校验在这个时候还是启用状态,因此这两个命令的CRC效验码必须要写正确,SD卡才会执行命令,否在在返回值R1中就会有相应的错误标志位提示开发人员CRC校验码错误。
六、SD卡读取与写入(SPI模式)
1、发送CMD17;
2、接收卡响应R1;
3、接收数据起始令牌0XFE;
4、接收数据;
5、接收2个字节的CRC,如果不使用CRC,这两个字节在读取后可以丢掉。
6、禁止片选之后,发多8个CLK;
以上就是一个典型的读取SD卡数据过程。
七、SD卡的写于读数据差不多,写数据通过CMD24来实现,具体过程如下:
1、发送CMD24;
2、接收卡响应R1;
3、发送写数据起始令牌0XFE;
4、发送数据;
5、发送2字节的伪CRC;
6、禁止片选之后,发多8个CLK;
以上就是一个典型的写SD卡过程。
八、SD卡操作命令作步骤:
1.读步骤:
发送CMD17(单块)或CMD18(多块)读命令,返回0x00
接收数据开始令牌0xfe(或0xfc)+正式数据512B+CRC校验2B
2.写步骤:
发送CMD24(单块)或CMD25(多块)写命令,返回0x00.
发送数据开始令牌0xfe(或0xfc)+正式数据512B+CRC校验2B
3.擦除步骤:
发送CMD32,跟一个参数来指定首个要擦除的起始地址
发送CMD33,指定最后的地址
发送CMD38,擦除指定区间的内容。
九、ACMD指令
ACMD指令是SD卡中的应用命令(Application Command)。ACMD指令是通过CMD55命令激活的,用于执行与SD卡应用相关的操作。ACMD指令与CMD指令的区别在于,ACMD指令需要先发送CMD55命令,然后再发送对应的ACMD指令。
以下是一些常用的ACMD指令:
1. ACMD6:设置SD卡的默认工作模式,可以选择高速模式或默认速度模式。
2. ACMD13:发送SD卡状态,用于获取SD卡的状态信息。
3. ACMD22:发送发送指定扇区的写保护状态,用于查询指定扇区是否被写保护。
4. ACMD23:设置或清除指定扇区的写保护状态,用于设置或取消指定扇区的写保护。
5. ACMD41:初始化SD卡,用于初始化SD卡并获取SD卡的OCR(Operation Condition Register)寄存器的值。
6. ACMD42:设置或清除SD卡的写保护状态,用于设置或取消SD卡的写保护。
7. ACMD51:读取SD卡的SCR(SD Configuration Register),用于获取SD卡的配置信息。
这些ACMD指令是与SD卡应用相关的命令,通过发送CMD55命令后再发送对应的ACMD指令,可以执行与SD卡应用相关的操作,例如初始化SD卡、获取状态信息、设置写保护状态等。具体的应用中,可以根据需要使用这些指令来执行相应的操作。
十、CMD指令
SD卡的CMD指令是一组用于与SD卡进行交互和控制的命令。以下是一些常用的SD卡CMD指令:
1. CMD0:进入IDLE状态,用于初始化SD卡。
2. CMD8:发送SD卡接口条件,用于检查SD卡是否支持特定的电压和功能。
3. CMD9:读取SD卡的CSD(Card Specific Data)寄存器,用于获取SD卡的参数信息。
4. CMD16:设置SD卡的块大小,用于指定读写操作的块大小。
5. CMD17:读取指定扇区的数据,用于从SD卡中读取数据。
6. CMD18:连续读取数据块,用于从SD卡中连续读取数据。
7. CMD24:写入指定扇区的数据,用于向SD卡中写入数据。
8. CMD25:连续写入数据块,用于向SD卡中连续写入数据。
9. CMD32:设置SD卡的起始扇区,用于指定写入数据的起始位置。
10. CMD33:设置SD卡的结束扇区,用于指定写入数据的结束位置。
11. CMD38:擦除指定扇区,用于将指定扇区的数据擦除。
12. CMD55:发送应用特定命令之前的准备命令。
13. CMD58:读取OCR(Operation Condition Register)寄存器,用于获取SD卡的操作特性。
这些CMD指令是通过SPI或SD模式与SD卡进行通信和控制的基本命令。在具体的应用中,可以根据需要使用这些指令来操作SD卡进行读写数据等操作。