硬件明白之后,下面就开始看软件部分了。 下面就来具体分析一下如何初始化及读写TF卡。 还是得先补充一点基础知识,以前欠下不会的,都得还回来啊,^^ SD卡的命令格式如下:
它由6 个字节组成,字节1 的最高2 位固定为01,低6 位为命令号(比如CMD16,为10000,完整的CMD16,第一个字节为01010000)。字节2~5 为命令参数,共4个字节,并不是所有命令都有参数,没有参数的话该位一般就置0。最后一个字节由7bit CRC校验位和1bit停止位(该位固定为1)组成。在SPI模式下,CRC是被忽略的,可以都置1或置0.但是发送CMD0时要记得加上CRC,即最后1字节为0x95(因为发送CMD0时还未进入SPI模式,[url=]PS[/url]:CMD8也要,但一般大家都把发送CMD8省略了)。 每次发送完一次命令后,SD卡都会有回应。SD卡的回应有多种格式,1字节的R1,2字节的R2等,不过一般在SPI模式中我们只用到R1,下面介绍R1的格式: 向SD卡写入一个CMD或者ACMD指令的过程是这样的: 首先使CS为低电平,SD卡使能;其次在SD卡的DI写入指令;写入指令后还要附加8个填充时钟,使SD卡完成内部操作;之后在SD卡的DO上接受回应;回应接受完毕使CS为高电平,再附加8个填充时钟。 初始化的典型流程如下: 1、初始化与 SD 卡连接的硬件条件(MCU 的 SPI 配置,IO 口配置); 2、拉高片选,上电延时(>74 个 CLK); 3、选择片选,发送CMD0命令 ,进入 IDLE状态; 4、发送 CMD8,检查是否支持 2.0 协议; 5、根据不同协议检查 SD 卡(命令包括:CMD55、CMD41、CMD58 和 CMD1 等); 6、取消片选,发多 8 个 CLK,结束初始化。 拉高CS,发送至少74个clk周期是为了使SD卡达到正常工作电压和进行同步,原因是SD卡内部有个供电电压上升时间,大概为64个CLK,剩下的10个CLK用于SD卡同步,之后才能开始CMD0的操作,在卡初始化的时候,CLK时钟最大不能超过400Khz! 发送CMD0,需要收到回应0x01表示成功进入idle状态,这由上述R1的格式可以看出来。 上述2,3过程可用下图来表示: 对于4,发送CMD8,它的返回格式如下:
接收到的第一个字节,如果为0x01,表示SD卡响应了CMD8命令,此卡为V2.0版本,如果不为0x01(一般会是0x05或者0x09),表示SD卡不支持CMD8命令,此卡为V1.0卡或者MMC卡。对于V2.0版本,后续还会收到4个字节,这里只需要关注最后两字节,8-11表示SD卡支持的电压范围,此处应该得到0001,最后一字节在发送CMD8指令时发来的数据,在程序中我们调用r1= SDSendCmd(CMD8,0x000001aa,0x87);这里应该收到aa. 如果CMD8收到的第一个字节不是0x01的话,就不用再读后续的三个字节了。
对于5,如果是V2.0卡那么流程如下:不断发送CMD55+ACMD41,先发送CMD55,在收到0x01之后,再发送ACMD41,直到收到0x00表示V2.0初始化成功,进入Ready状态。再发送CMD58命令来判断是HCSD还是SCSD,到此SD2.0卡初始化成功。SD卡按容量的大小可以分为SC、HC 、XC三种类型,如下表所示:
需要注意的是:SD卡和SDHC 卡协议基本兼容,但是SDXC 卡,同这两者区别就比较大了,我们讨论的主要是SD/SDHC 卡 。 对于5, 如果CMD8返回错误,表示不支持V2.0卡,则进一步判断为1.0卡还是MMC卡,方法循环发送CMD55+ACMD41,返回无错误,则为SD1.0卡,到此SD1.0卡初始化成功,如果在一定的循环次数下,返回为错误,则进一步发送CMD1进行初始化,如果返回无错误,则确定为MMC卡,如果在一定的次数下,返回为错误,则不能识别该卡,初始结束。
总结:一个完整的驱动是应该包括上述所有过程的,CMD0是必须要发送的,CMD8用来区分是否为V2.0卡,如果是V2.0,再发送CMD55+ACMD41 来确认初始化是否成功,CMD58用来区分卡容量大小。所以对于V2.0卡,完整的驱动应该包括CMD0,CMD8,CMD55+ACMD41,CMD58 这几个命令。对于V1.0卡,需要CMD0,CMD8,CMD55+ACMD41命令。对于MMC卡,需要CMD0,CMD1命令。
|