SD卡彻底解析和程序SD(SecureDigitalMemoryCard)中文翻译为安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛的用于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。大小犹如一张邮票的SD记忆卡,重量只有2克,但却拥有高记忆容量、快速数据传输率、极大的移动灵活性以及很好的安全性。SD卡一般支持2种操作模式:1,SD卡模式:2,SPI模式:主机可以选择以上任意一种模式同SD卡通信,SD卡模式允许4线的高速数据传输。SPI模式允许简单的通过SPI接口来和SD卡通信,这种模式同SD卡模式相比就丧失了速度。SD卡引脚功能描述如下图所示:SD卡的引脚排序如下图所示:SD卡只能使用3.3V的IO电平,所以,MCU一定要能够支持3.3V的IO端口输出。注意:在SPI模式下,CS/MOSI/MISO/CLK都需要加10-100K左右的上拉电阻。SD卡要进入SPI模式很简单,就是在SD卡收到复位命令(CMD0)时,CS为有效电平(低电平则SPI模式被启用。不过在发送CMD0之前,要发送74个时钟,这是因为SD卡内部有个供电电压上升时间,大概为64个CLK,剩下的10个CLK用于SD卡同步,之后才能开始CMD0的操作,在卡初始化的时候,CLK时钟最大不能超过400KHz!下面终点介绍一下SD卡在SPI模式下的相关操作。首先介绍SPI模式下几个重要的操作命令,如下图所示:其中R1的回应格式如下表所示:接着看看SD卡的初始化,SD卡的典型初始化过程如下:1、初始化与SD卡连接的硬件条件(MCU的SPI配置,IO口配置);2、上电延时(74个CLK);3、复位卡(CMD0);4、激活卡,内部初始化并获取卡类型(CMS1(用于MMC卡)、CMD5。CMD41);5、查询OCR,获取供电状况(CMD58);6、是否使用CRC(CMD59);7、设置读写块数据长度(CMD16);8、读取CSD,获取存储卡的其他信息(CMD9);9、发送8CLK后,禁止片选;这样我们完成了对SD卡的初始化,这里我们一般设置读写块数据长度为512个字节,并禁止使用CRC。在完成了初始化之后,就可以开始读写数据了。SD卡读数据,这里通过CMD17来实现,具体过程如下:1、发送CMD17;2、接收卡响应R1;3、接收数据起始令牌0XFE;4、接收数据;5、接收2个字节的CRC,如果没有开启CRC,这两个字节在读取后可以丢掉;6、8CLK之后禁止片选。以上就是一个典型的读取SD卡数据过程,SD卡的写与读数据差不多,写数据通过CMD24来实现,具体过程如下:1、发送CMD24;2、接收卡响应R1;3、发送写数据起始令牌0XFE;4、发送数据;5、发送2字节的伪CRC;6、8CLK之后禁止片选。以上就是一个典型的写SD卡过程。#includeMMC.hunsignedcharInit_Flag;//Setitto1whenInitisprocessing.unsignedcharcard_type;voidNOP(void);unsignedcharCMD[]={0x40,0x00,0x00,0x00,0x00,0x95};//CMD0/**********************************************************延时子函数**********************************************************/voiddelay(unsignedinttime){while(time--);}/**********************************************************us延时子程序(4.34us)**********************************************************/voiddelayNOP(){NOP();NOP();NOP();NOP();}/**********************************************************延时程序**********************************************************/voidNOP(){vu16i;for(i=0;i}/**********************************************************卡端口初始化***********************************************************voidMMC_Port_Init(){//SPI_CLK=1;GPIO_SetBits(GPIOA,SPI_CLK);//置位LCD_RS//SPI_DO=1;GPIO_SetBits(GPIOA,SPI_DO);//SPI_CS=1;GPIO_SetBits(GPIOA,SPI_CS);}//*********************************************************//RoutineforsendingabytetoMMC/SD-Card//writeabyte//*********************************************************voidWrite_Byte_MMC(ucharvalue){unsignedchari;for(i=0;i{if(value&0x80)//SPI_DI=1;//Sendbitbybit(MSBFirst)GPIO_SetBits(GPIOA,SPI_DI);else//SPI_DI=0;GPIO_ResetBits(GPIOA,SPI_DI);//SPI_CLK=0;//ClocklowGPIO_ResetBits(GPIOA,SPI_CLK);if(Init_Flag)delayNOP();//SPI_CLK=1;//ClockHighGPIO_SetBits(GPIOA,SPI_CLK);if(Init_Flag)delayNOP();value}}//*********************************************************//RoutineforreadingabytefromMMC/SD-Card//SoftwareSPI//*********************************************************unsignedcharRead_Byte_MMC(){unsignedchartemp=0;unsignedchari;//SPI_DO=1;GPIO_SetBits(GPIOA,SPI_DO);for(i=0;i{//SPI_CLK=0;//ClockLowGPIO_ResetBits(GPIOA,SPI_CLK);if(Init_Flag)delayNOP();//SPI_CLK=1;//ClockHighGPIO_SetBits(GPIOA,SPI_CLK);if(Init_Flag)delayNOP();temp=(temp}return(temp);}//*********************************************************//SendaCommandtoMMC/SD-Card//Return:thesecondbyteofresponseregisterofMMC/SD-Card//*********************************************************unsignedcharWrite_Command_MMC(unsignedchar*CMD){unsignedchartmp;unsignedchari;//setMMC_Chip_Selecttohigh(MMC/SD-Carddisable)//SPI_CS=1;GPIO_SetBits(GPIOA,SPI_CS);//send8ClockImpulseWrite_Byte_MMC(0xFF);//setMMC_Chip_Selecttolow(MMC/SD-Cardactive)//SPI_CS=0;GPIO_ResetBits(GPIOA,SPI_CS);//send6ByteCommandtoMMC/SD-Cardfor(i=0;i{Write_Byte_MMC(*CMD++);}i=0;//get16bitresponseRead_Byte_MMC();//readthefirstbyte,ignoreit.do{//Onlylast8bitisusedhere.Readitout.tmp=Read_Byte_MMC();i++;}while((tmp==0xff)&&(ireturn(tmp);}//*********************************************************//RoutineforInitMMC/SDcard(SPI-MODE)unsignedcharMMC_Init()//*********************************************************{unsignedchartemp;unsignedchari;MMC_Port_Init();//InitSPIportdelay(200);Init_Flag=1;//Settheinitflagfor(i=0;i{Write_Byte_MMC(0xff);//send74clockatleast!!!}//SendCommandCMD0toMMC/SDCardi=0;do{//retry200timestosendCMD0commandtemp=Write_Command_MMC(CMD);i++;if(i=200){//timeoutreturn(INIT_CMD0_ERROR);//CMD0Error!}}while(temp!=1);i=0;do{CMD[0]=0x77;//CMD55命令temp=Write_Command_MMC(CMD);//先发送CMD55if(temp==0x01)//如果有反应{CMD[0]=0x69;//ACMD41命令temp=Write_Command_MMC(CMD);//发送CMD41进行激活if(temp==0x00)//激活成功就是SD卡{card_type=1;//SD}}else//如果发送CMD55无反应,改发送CMD1{CMD[0]=0x41;//CMD1命令CMD[5]=0xFF;temp=Write_Command_MMC(CMD);//发送CMD1进行激活if(temp==0x00)//激活成功就是MMC卡{card_type=0;//MMC}}i++;if(i=200){return(INIT_CMD1_ERROR);//CMD1Error!}}while(temp!=0x00);//MMC和SD卡激活后的返回值均为0x00Init_Flag=0;//Initiscompleted,cleartheflag//SPI_CS=1;//setMMC_Chip_SelecttohighGPIO_SetBits(GPIOA,SPI_CS);//wr_string(0,2,INITSUCCESS);return(0);//Allcommandshavebeentaken.}//*********************************************************//RoutineforreadingdataReg