SD卡 SPI模式下 初始化以及 数据传输过程 和 命令详解

个人学习笔记可能稍许有些乱,但仔细阅读之后 您肯定会有所收获,如有疑问请留下评论 我会一一解答(2018.10.1之前)。

SPI通信模式为3线制 CLK MOSI MISO,SPI通信为数据交换的方式,所以在通信时无需使用中断方式(也可使用中断节省一些时间,但实际意义不大),如SPI通信 主机发数据 从机收,但从机不发送数据时,因为SPI三根通信线都是开漏电路接上拉电阻,所有主机收到全0xff 并且将RENX位置1。可以通过判断接受的是否为全1(0xff)来了解到从机是否发送数据。在写SPI发送数据的函数中,也要写接受数据的函数,并且在SPI_I2S_SendData()函数后要延时一定的时间之后再来判断接受是否置位,具体的延时时间可由SPI通信时钟频率和所要传输的位数决定

1、SD卡上电  必须给SD卡提过不少于74个脉冲信号,用于上电延时。

2、发送CMD0命令的同时将CS片选线 置0,当SD卡回应R1为 0x01时卡进入idle状态。

3、发送CMD8命令 参数 VHS 和 CRC必须正确,格式如下:

VHS

Host supplied voltage range

根据以上几个表图可得:在SPI模式下发送CMD8 命令的二进制为:

01001000  00000000  00000000  00000001 10101010  10000111

标黄的这8位可以任意,但低8位的CRC校验必须与之匹配!

如果CMD8命令回应为:00000001  00000000 00000000 00000001 10101010

(注意:上图Table 7-5 最后一行 写明 如果电压匹配(Match * 2),上面标黄部分只是ECHO BACK,与CMD8的参数一致。)

说明SD卡适应所提供的电压。

4、发送CMD58命令(读取OCR寄存器,查看SD卡所支持的电压范围),OCR寄存器具体内容如下:

经过实验发现,不管之前给多少个时钟脉冲,读取OCR寄存器31 30位总不会置位,此时读取OCR寄存器只能得到SD卡所支持的电压范围。

并且发送CMD58命令无需关注参数和CRC校验。CMD58命令回复如下:

5、发送CMD55命令(命令参数,CRC不关注) 告知SD卡 下一条命令为APP_CMD类型的命令。

回应为R1,如正确回应应为0x01,

此时卡还处于idle状态。

发送ACMD41命令,手册上说明如下:

It is mandatory to issue CMD8 prior to the first ACMD41. Receiving of CMD8 expands the

CMD58 and ACMD41 function; HCS (High Capacity Support) in the argument of ACMD41 and CCS

(Card Capacity Status) in the response of CMD58. HCS is ignored by the card, which didn’t accept

CMD8. Standard Capacity SD Memory Card ignores HCS. The “in idle state” bit in the R1 response of

ACMD41 is used by the card to inform the host if initialization of ACMD41 is completed.

大致翻译:发送ACMD41命令之前必须要先发送CMD8命令,标准的命令流程应为CMD8、CMD58、CMD55、ACMD41。在发送ACMD41时也应该指定HCS位(高容量支持位,编者按:但好像此时我们还不知道SD卡是否支持高容量),如果未在ACMD41命令之前发送CMD8,SD卡忽略HCS位,标准容量SD卡忽略HCS位。RI的idle state位指示是否完成初始化过程,当R1的idle位为1时,SD卡处于初始化状态,为0完成初始化过程。

ACMD41命令也无需指定CRC。

经过实验发现,在发送ACMD41命令时必须将HCS位置1,如果不置1,初始化过程不会完成。对于标准容量的SD卡,指定HCS位也不会对初始化产生任何的影响,如上面所说,标准的SD卡忽略HCS位。所以HCS位在发送ACMD41命令时必须置1!

6、发送CMD58命令,查看SD卡所支持的SD协议。

如果支持2.0 协议可以降低SPI的分频,高速传输数据。(在此说明,刚开始初始化SPI需要将分频置为最大值,防止低版本SD卡无法完成初始化)。

至此SD卡初始化全部完成,进入数据传输模式!

但在数据传输之前还需要完成读写块的设置,标准容量的SD卡可以通过CMD16命令设置读写块大小;高容量SD卡读写块大小固定为512字节,并且忽略CMD16命令。读写块的最大值在CSD寄存器中指定,使用CMD16设置大于最大值将被忽略。当CSD寄存器READ_BL_PARTIAL 置1时,可以设置不大于512字节的任意读写块大小。

手册上说高速卡只支持固定大小512字节读写块。所以上面的都是扯淡!

可以忽略设置读写块大小。

数据传输时,会对512字节的数据进行CRC校验,CRC多项式为x16+x12+x5+1。

在实际读写操作中不用使用CMD16命令来指定下一条命令的开操作长度,一般不设置读写块大小,使用默认的512字节的块大小。

CMD17命令用来读一个块,32位参数指定要读取块的地址(好像到现在为止,我们还不知道SD卡的容量大小,也不知道SD卡的地址范围,所以要在读取块内容之前,先了解到SD卡的地址范围和容量信息)Follow contents describe the detail for read CSD and get the range of SD's address。

CMD9命令参数填充0,获得SD卡的CSD寄存器内容,CSD寄存器提供了一些接入SD卡的信息。在SDIO模式下,读取CSD通过SD卡响应获得(SDIO,R2),在SPI模式下,通过标准的块数据读取获得,传输格式与块读取格式相同(0xfe标记数据开始传输,紧接着传输16字节的CSD寄存器内容,2字节CRC校验)。不同版本的SD卡的CSD寄存器内容有所不同。CSD高4位指定了该SD卡的协议版本。如下:

这里只说明如何获取Version 2.0 版本SD卡的地址范围和容量大小。

Version 2.0 CSD寄存器的具体内容如下:

C_SIZE [69:48] 使我们关注的区域!

我的SD卡读出的[69:48]为:

0001 1101 1110 0011( 高位全0省略)转换为十进制为:7651

所以卡的地址范围为(0-7651),容量为:7652 * 512 Byte = 3917824 Byte 大约为4GB

至此读写一个块的准备工作全部完成!

发送CMD17命令参数为所要读取的地址(32位),无需关注CRC,SD卡接收到以后返回该地址块的全部内容 (512字节)。SD卡返回数据格式如下:

response R1为0,说明SD卡接收到命令,且命令无误。数据的起始标记为0xfe(SD卡处理命令需要一些时间,SD卡处理命令时SPI读得0xff,编程时需要判断接受到0xfe时才将数据写进buf)

,紧接着512字节数据内容,后接2字节CRC校验(可以通过CMD59命令关闭CRC校验)。

读多个块,写一个块、多个块,同(LAZY)理(TO)操(WRITE)作(DOWN)。For the detail please read 协议手册!

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值