Freescale KL26 SD卡读写程序

来源:互联网 发布:詹姆斯07总决赛数据 编辑:程序博客网 时间:2024/04/30 18:07

   在实际项目开发中经常会用到SD卡存储数据,Kinetis  单片机操作SD卡有两种接口,一个是SDHC接口,另外就是普通的SPI接口(对于不带SDHC的MCU可以选择SPI)。

   本篇博客硬件以Kinetis KL26为基础介绍SD卡的使用,最后实现的Demo是一个SD卡USB读卡器的功能,它同时包括了USB和文件系统部分。

   先了解一下SD卡和Micro SD卡的基本常识:

    SD卡是SecureDigital Card卡的简称,直译成汉语就是“安全数字卡”,是1999年由日本松下公司、东芝公司和美国SANDISK公司共同开发研制的全新的存储卡产品。SD存储卡是一个完全开放的标准(系统),多用于MP3、数码摄像机、数码相机、电子图书、AV器材等等。

 MicroSD卡(这家伙原名叫TF卡(Trans-Flashcard),2004年改的名,原来不仅人名可以改,这玩意也改名~~),是一种极细小的快闪存储器卡,由著名的存储厂商闪迪(SanDisk)公司发明创立。这种卡主要于手机使用,但因它拥有体积极小的优点,随着不断提升的容量,它慢慢开始于GPS设备、便携式音乐播放器和一些快闪存储器盘中使用。

   那么这两种卡到底有什么区别呢?其实从这哥俩的名字就能看出一些端倪,MicroSD是在SD的前面加了一个Mirco,哦哦,Micro,那就是更小的SD喽。对的,其实SD卡与MicroSD卡在功能上没区别,MicroSD卡就是SD卡的微型版,也可以看作是升级版本,既然它们关系如此密切,所以在MicroSD卡外面加个卡套(专业一点是叫做adapter,适配器),就可以把MicroSD当作SD卡来使用了。如下图所示,将右侧MicroSD卡插入左侧卡套中,之后再插入电脑SD卡槽中,就可以使用把它当作U盘来使用了。



    再多说两句,你应该还听说过MMC卡,它的全称叫做Multimedia Card),翻译成中文为“多媒体卡”。在1997年由西门子及SanDisk共同开发的。这玩意和SD卡又有什么关联呢?SD卡的技术是基于MMC上发展而来的,它们区别在于初始化过程不同。

OK,下面看一下SD卡和Micro SD的引脚定义:

                             

SD卡的内部结果如下:




     上图需要说明的是,SD卡和micro SD卡支持两种操作模式,分别为SD模式和SPI模式, SD模式速度快,安全性好,不过它需要引脚多而且主要是驱动起来复杂,当然有些MCU会自带SD模式的硬件接口,这样就方便多了,而SPI模式就方便许多了,虽然速度上没有SD模式快,不过很多MCU都自带SPI硬件资源,这样使用起来就比较方便,如果MCU不带SPI硬件接口的话,就需要使用IO口去模拟了。

    上面两张图看着有点头晕,再来一张看起来简单一点的图:

   


  再来对比一下它们引脚之间的关系,

 


  可以发现Micro SD卡只是比SD卡少了一个VSS  引脚,这更加证明了这两个卡时如此的关系密切。。

  了解这些概念之后,我们就开始用MCU来控制它了。首先看一下SD卡硬件电路部分:



SPI下电路的连接非常简单,接上电源线Vdd和地线Vss,再接上SPI的CS,SCLK,DI(MOSI)和DO(MISO)就可以了,其他引脚可以放空。注意SD卡的电源和操作电压都为2.7-3.6V,如果使用5V的单片机要进行电平转换或串电阻限流。还有记得SD卡的CS,SCLK和DI要用10~100K的电阻上拉,下图是SD卡的一个连接示意图,对于MicroSD卡一样的接法,只是注意下引脚的不同就行了。

   由于本实验是在YL-KL26开发板上进行的,该板子是优龙公司做的,链接如下:http://www.ucdragon.cn/product/showproduct.php?lang=cn&id=14,淘宝网址为:

http://item.taobao.com/item.htm?spm=a1z10.1.w137644-2186920978.41.JbpFWl&id=36763794750  ,售价99RMB,还挺便宜,记得我大学那会买了一个51开发板还一百多元呢。

所以让我们来看一下此开发板上Micro SD卡部分的原理图:


   

 这张图有一点困惑了我老半天,那就是9脚nCD是什么玩意?刚开始我一直以为J5是一个将TF卡转换为SD卡的卡套,因为看到左侧有9个引脚,就想当然的这么认为了,结果怎么也搞不明白9脚nCD是什么功能?后来才恍然明白,J5只不是一个TF卡的卡座而已,直接上图,这玩意如下:

 

你如果数一数它最下侧引脚数目的话,会发现有9个引脚,这是怎么回事?之前明明说TF卡只有8个引脚,那么多出来的这个引脚是怎么回事?原来多出来的这个CD引脚具有这样的功能,平时卡座不插卡的时候,它和GND脚是断开的,当插入卡时,它就和GND连在一起了。CD原来是CardDetection的意思。可以通过这个这个脚来检测有没有卡插入。

这个卡座的引脚定义如下,pin1到pin8的定义和TF卡的引脚定义是一样的,就是多了9脚.



硬件明白之后,下面就开始看软件部分了。

下面就来具体分析一下如何初始化及读写TF卡。

操作SD卡,本质是给它发送一系列的命令,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模式,PS:CMD8也要,但一般大家都把发送CMD8省略了)。

每次发送完一次命令后,SD卡都会有回应。SD卡的回应有多种格式,1字节的R1,2字节的R2等,下面先介绍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过程可用下图来表示,发送CMD0指令的过程也称为Reset过程。



对于4,发送CMD8,发的格式如下:



注意CMD8 不同于CMD0,它是有参数的,需要在参数中指定VHS位和Check Pattern。

它返回5个字节的R7,返回格式如下:



接收到的第一个字节和R1是一样的,如果为0x01,表示SD卡响应了CMD8命令,此卡为V2.0版本,如果不为0x01(一般会是0x05或者0x09),表示SD卡不支持CMD8命令,此卡为V1.0卡或者MMC卡。

31-28 command version 为 命令号,这里为1000,表示CMD8

27-12 为保留位 值为0000h

11-8 为接收的电压范围



7-0 为发送CMD8 带过来的参数值

对于V2.0版本,后续还会收到4个字节,这里只需要关注最后两字节,8-11表示SD卡支持的电压范围,此处应该得到0001,最后一字节在发送CMD8指令时发来的数据,在程序中我们调用r1= SDSendCmd(CMD8,0x000001aa,0x87);这里应该收到aa.

如果CMD8收到的第一个字节不是0x01的话,就不用再读后续的三个字节了。

 

   对于5,如果是V2.0卡那么流程如下:不断发送CMD55+ACMD41,CMD55 表示下一条要发送的指令是应用相关指令ACMD,它的返回格式是R1格式。

ACMD41的说明如下,它用来发送卡容量支持信息并激活SD的初始化过程。


它的返回值为R1格式,R1的最低位(In Idle State)用来表示是否初始化完成,如果为1表示SD卡仍然在初始化之中,如果为0表示初始化完成。

初始化完成之后就可以通过CMD58指令来获取CCS信息,如果CCS=0,表示是SDSD;如果CCS=1,表示是SDHC或者SDXC。

CMD58 是读OCR寄存器的值。


它的返回值为R3。



先发送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命令。

 

 

初始化完成之后,就可以进行读写操作了。

SD卡读单块和多块的命令分别为CMD17CMD18,它们的参数即要读的区域的开始地址。因为考虑到一般SD卡的读写要求地址对齐,所以一般我们都将地址转为块,并以扇区(块)(512Byte)为单位进行读写,比如读扇区0参数就为0,读扇区1参数就为1<<9(即地址512),读扇区2参数就为2<<9(即地址1024),依此类推。

   读单块方法:

   1.发送CMD17,收到0x00表示成功

   2.连续读直到读到开始字节0xFE

   3.读512个字节

   4.读两个CRC字节

   读单块时序图:

 

读多块方法:

   1.发送CMD18读,收到0x00表示成功

   2.连续读直到读到开始字节0xFE

   3.读512字节

   4.读两个CRC字节

   5.如果还想读下一扇区,重复2-4

   6.发送CMD12来停止读多块操作

 

写单块和多块:

   SD卡用CMD24和CMD25来写单块和多块,参数的定义和读操作是一样的。

   写单块方法:

   1.发送CMD24,收到0x00表示成功

   2.发送若干时钟

   3.发送写单块开始字节0xFE

   4.发送512个字节数据

   5.发送2字节CRC(可以均为0xff)

   6.连续读直到读到XXX00101表示数据写入成功

   7.继续读进行忙检测(读到0x00表示SD卡正忙),当读到0xff表示写操作完成

写单块时序图:



写多块方法:

   1.发送CMD25,收到0x00表示成功

   2.发送若干时钟

   3.发送写多块开始字节0xFC

   4.发送512字节数据

   5.发送两个CRC(可以均为0xff)

   6.连续读直到读到XXX00101表示数据写入成功

   7.继续读进行忙检测,直到读到0xFF表示写操作完成

   8.如果想读下一扇区重复2-7步骤

   9.发送写多块停止字节0xFD来停止写操作

   10.进行忙检测直到读到0xFF


初始化一旦正确完成,就成功了一大半了。

在实际调试SD 卡的过程中,我遇到过很多的问题,在此做个总结:

1) SD卡初始化流程问题:我相信这是困惑很多人的一个问题,因为网上众说纷纭而且代码也是不太一样,其实最标准的流程在 SD卡的规范里:SD card Specification 下载  


2) 使用SPI接口调试SD 卡,首先要保证SPI是可以正常工作的,如果SPI无法工作,那SD card 肯定无法工作了。所以第一步可以用示波器观察SPI是否工作正常。


3) SPI 片选信号的控制需要十分注意: 就是该拉高的时候需要拉高,该拉低的时候需要拉低。否则有可能无法正常通讯。

比如下面的读CID寄存器的时序,是要求CS一直拉低的,如果你不注意在发送CMD10指令后拉高了,紧接再拉低读数据那么就有可能读取不成功。



代码下载地址:

https://github.com/Wangwenxue/KL26_SDCard

下载后可以直接download到YL-KL26中,将FRDM_KL26的USB接口也接入电脑,电脑上就会映射出一个U盘出来,可以直接在电脑上像操作U盘一样操作SD卡。


参考内容:

http://blog.chinaaet.com/detail/25269

http://blog.csdn.net/ming1006/article/details/7281597

http://blog.csdn.net/ming1006/article/details/7283689

http://download.csdn.net/download/ming1006/4196053

http://www.cnblogs.com/gmh915/archive/2010/08/24/1945406.html

http://blog.sina.com.cn/s/blog_4f09c0b50101636h.html

http://blog.csdn.net/g_salamander/article/details/14167055

http://blog.163.com/lxy_fight/blog/static/2041580702012422111910662

 


0 0