sd卡引脚定义及命令2011-05-12 15:32 682人阅读评论(0) 收藏举报SD卡引脚定义:针脚名称类型描述1 CD DAT3 I/O/PP 卡监测数据位32 CMD PP 命令/回复3 Vss S 地4 Vcc S 供电电压5 CLK I 时钟6 Css2 S 地7 DAT0 I/O/PP 数据位08 DAT1 I/O/PP 数据位19 DAT2 I/O/PP 数据位2SD卡接口标准规范SD卡上所有单元由内部时钟发生器提供时钟。
接口驱动单元同步外部时钟的DAT和CMD 信号到内部所用时钟。
本卡由6线SD卡接口控制,包括:CMD,CLK,DAT0-DAT3。
在多SD卡垛叠中为了标识SD卡,一个卡标识寄存器(CID)和一个相应地址寄存器(RCA)预先准备好。
一个附加的寄存器包括不同类型操作参数。
这个寄存器叫做CSD。
使用SD卡线访问存储器还是寄存器的通信由SD卡标准定义。
卡有自己的电源开通检测单元。
无需附加的主复位信号来在电源开启后安装卡。
它防短路,在带电插入或移出卡时。
无需外部编程电压。
编程电压卡内生成。
SD卡支持第二接口工作模式SPI。
如果接到复位命令(CMD0)时,CS信号有效(低电平),SPI模式启用。
sd卡接口规范(完整规范标准)特性:◎容量:32MB/64MB/128MB/256MB/512MB/1GByte◎兼容规范版本1.01◎卡上错误校正◎支持CPRM◎两个可选的通信协议:SD模式和SPI模式◎可变时钟频率0-25MHz◎通信电压范围:2.0-3.6V工作电压范围:2.0-3.6V◎低电压消耗:自动断电及自动睡醒,智能电源管理◎无需额外编程电压◎卡片带电插拔保护◎正向兼容MMC卡◎高速串行接口带随即存取---支持双通道闪存交叉存取---快写技术:一个低成本的方案,能够超高速闪存访问和高可靠数据存储---最大读写速率:10Mbyte/s◎最大10个堆叠的卡(20MHz,Vcc=2.7-3.6V)◎数据寿命:10万次编程/擦除◎CE和FCC认证◎PIP封装技术◎尺寸:24mm宽×32mm长×1.44mm厚本SD卡高度集成闪存,具备串行和随机存取能力。
可以通过专用优化速度的串行接口访问,数据传输可靠。
接口允许几个卡垛叠,通过他们的外部连接。
接口完全符合最新的消费者标准,叫做SD卡系统标准,由SD卡系统规范定义。
SD卡系统是一个新的大容量存储系统,基于半导体技术的变革。
它的出现,提供了一个便宜的、结实的卡片式的存储媒介,为了消费多媒体应用。
SD卡可以设计出便宜的播放器和驱动器而没有可移动的部分。
一个低耗电和广供电电压的可以满足移动电话、电池应用比如音乐播放器、个人管理器、掌上电脑、电子书、电子百科全书、电子词典等等。
使用非常有效的数据压缩比如MPEG,SD卡可以提供足够的容量来应付多媒体数据。
SD卡上所有单元由内部时钟发生器提供时钟。
接口驱动单元同步外部时钟的DAT和CMD 信号到内部所用时钟。
本卡由6线SD卡接口控制,包括:CMD,CLK,DAT0-DAT3。
在多SD卡垛叠中为了标识SD卡,一个卡标识寄存器(CID)和一个相应地址寄存器(RCA)预先准备好。
一个附加的寄存器包括不同类型操作参数。
这个寄存器叫做CSD。
使用SD卡线访问存储器还是寄存器的通信由SD卡标准定义。
卡有自己的电源开通检测单元。
无需附加的主复位信号来在电源开启后安装卡。
它防短路,在带电插入或移出卡时。
无需外部编程电压。
编程电压卡内生成。
SD卡支持第二接口工作模式SPI。
如果接到复位命令(CMD0)时,CS信号有效(低电平),SPI模式启用。
(译者按:以下部分为本人翻译)接口该SD卡的接口可以支持两种操作模式:。
SD卡模式。
SPI模式主机系统可以选择以上其中任一模式,SD卡模式允许4线的高速数据传输。
SPI模式允许简单通用的SPI通道接口,这种模式相对于SD模式的不足之处是丧失了速度。
SD卡模式针脚定义1:S:电源供电,I:输入O:输出I/O:双向PP:I/O使用推挽驱动SD卡的总线概念SD总线允许强大的1线到4线数据信号设置。
当默认的上电后,SD卡使用DAT0。
初始化之后,主机可以改变线宽(译者按:即改为2根线,3根线。
)。
混和的SD卡连接方式也适合于主机。
在混和连接中Vcc,Vss和CLK的信号连接可以通用。
但是,命令,回复,和数据(DAT0~3)这几根线,各个SD卡必须从主机分开。
这个特性使得硬件和系统上交替使用。
SD总线上通信的命令和数据比特流从一个起始位开始,以停止位中止。
CLK:每个时钟周期传输一个命令或数据位。
频率可在0~25MHz之间变化。
SD卡的总线管理器可以不受任何限制的自由产生0~25MHz的频率。
CMD:命令从该CMD线上串行传输。
一个命令是一次主机到从卡操作的开始。
命令可以以单机寻址(寻址命令)或呼叫所有卡(广播命令)方式发送。
回复从该CMD线上串行传输。
一个命令是对之前命令的回答。
回复可以来自单机或所有卡。
DAT0~3:数据可以从卡传向主机或副versa。
数据通过数据线传输。
二、SD卡的命令1.SD卡的命令格式:SD卡的指令由6字节(Byte)组成,如下:Byte1:0 1 x x x x x x(命令号,由指令标志定义,如CMD39为100111即16进制0x27,那么完整的CMD39第一字节为01100111,即0x27+0x40)Byte2-5:Command Arguments,命令参数,有些命令没有参数Byte6:前7位为CRC(Cyclic Redundacy Check,循环冗余校验)校验位,最后一位为停止位02.SD卡的命令SD卡命令共分为12类,分别为class0到class11,不同的SDd卡,主控根据其功能,支持不同的命令集如下:Class0 :(卡的识别、初始化等基本命令集)CMD0:复位SD 卡.CMD1:读OCR寄存器.CMD9:读CSD寄存器.CMD10:读CID寄存器.CMD12:停止读多块时的数据传输CMD13:读Card_Status 寄存器Class2 (读卡命令集):CMD16:设置块的长度CMD17:读单块.CMD18:读多块,直至主机发送CMD12为止.Class4(写卡命令集) :CMD24:写单块.CMD25:写多块.CMD27:写CSD寄存器 .Class5 (擦除卡命令集):CMD32:设置擦除块的起始地址.CMD33:设置擦除块的终止地址.CMD38: 擦除所选择的块.Class6(写保护命令集):CMD28:设置写保护块的地址.CMD29:擦除写保护块的地址.CMD30: Ask the card for the status of the write protection bitsclass7:卡的锁定,解锁功能命令集class8:申请特定命令集。
class10 -11 :保留有关sd卡驱动和fat fs的实现用了3个文件来实现。
sdboot.c为sd的驱动(可理解为pdd)层,主要实现一些对sd控制器的配置以及一些基本sd命令的实现和对sd卡的操作。
sdmmc.c实现了从sd卡读取nk并跳到内存去运行的代码(基本可以理解为sd驱动的mdd 层)。
sdfat.c文件就是实现fat fs的。
mdd层通过fatfs来对pdd层操作以实现读取文件。
在整个过程中遇到了很多问题,现在列举如下:1)sd卡初始化问题……………………………………2)对sd卡操作问题SD卡包括:一个标识寄存器CID,一个相应地址寄存器RCA,一个其他参数寄存器CSD。
检测卡的插入,直接用中断引脚的电平来判断。
判断插入的卡是否是sd卡,用命令cmd55和cmd41,因为mmc卡对cmd55不做回应。
命令9就是获取sd卡中csd寄存器的值的,该值包括很多sd卡的信息,其中就有sd卡的容量。
这个值在sd卡接收到cmd9之后会以response的形式存放在sd控制器的SDI Response Register[0,1,2,3]中。
在执行cmd9,cmd10等这样的命令的时候,卡的状态应该是不选中的,或直接在执行它们之前发送cmd7(0)不选中卡,不然的话会timeout。
用cmd17来读取单个block的数据,该命令要带地址参数(该参数通过cmd3命令来获取),然后根据SDIDSTA和SDIFSTA状态值来从sd控制器的SDIDAT寄存器中读出要读的数据。
该命令与cmd9相反,在执行它之前要选中卡。
读完一个block之后要做一些善后工作,为下次读取做好准备,不然的话checkcmdend就要一直循环了。
因为用的是每次都读一个block,并地址要以block对齐,这样就要考虑要读取的地址是否是block对齐的,长度是否够一个block。
SDIDCON这个数据控制寄存器也很重要,一些对数据的操作形式就是在这里设置的。
3)fat文件系统问题根据MBR找到分区表,根据分区表找到该分区MBR[446B+4个分区表(每个16B)+2B 结束符)分区表中的第9-12字节为该分区的启始地址(单位没sector),第13-16字节为分区的长度(单位也是sector)4) 通信模式的切换:SD卡有两种通信模式:SPI模式和SD模式,默认情况下的通信模式是SD模式,但是我们常用的模式是SPI模式,这就需要一个切换模式的方法,具体的实现方法在其他地方也都有介绍,其关键的地方就是先上电延时大于74个时钟周期后发送复位命令,复位成功(接收到0x01的响应)后,连续发送CMD55和ACMD41,直到响应0X00为止,此时SD卡已经进入SPI模式。
TF卡,参考,未验证1,DATA22,CD/DATA33,CMD4,VCC5,CLK6,GND7,DATA08,DATA1sd卡:一、SD MODE1、CD/DATA32、CMD3、VSS14、VDD5、CLK6、VSS27、DATA08、DATA19、DATA2二、SPI MODE1、CS2、DI3、VSS4、VDD5、SCLK6、VSS27、DO8、RSV9、RSVCF卡一、PC CARD MEMORY MODE1、GND2、D33、D44、D55、D66、D77、CE18、A109、OE10、A911、A812、A713、VCC14、A615、A516、A417、A318、A219、A120、A021、D022、D123、D224、WP25、CD226、CD127、D1128、D1229、D1330、D1431、D1532、CE234、IORD35、IOWR36、WE37、RDY/BSY38、VCC39、CSEL40、VS241、RESET42、WAIT43、INPACK44、REG45、BVD246、BVD147、D848、D949、D1050、GNDCF卡二、PC I/O CARD MODE1、GND2、D33、D44、D55、D66、D77、CE18、A109、OE10、A911、A812、A713、VCC14、A615、A517、A318、A219、A120、A021、D022、D123、D224、IOIS1625、CD226、CD127、D1128、D1229、D1330、D1431、D1532、CE233、VS134、IORD35、IOWR36、WE37、RDY/BSY38、VCC39、CSEL40、VS241、RESET42、WAIT43、INPACK44、REG45、SPKR46、STSCHG47、D848、D949、D1050、GND三、TRUE IDE MODE1、GND2、D33、D44、D55、D66、D77、CS08、A109、ATA SEL10、A911、A812、A713、VCC14、A615、A516、A417、A318、A219、A120、A021、D022、D123、D224、IOIS1625、CD226、CD127、D1128、D1229、D1330、D1431、D1532、CS133、VS134、IORD35、IOWR36、WE37、INTRQ38、VCC39、CSEL40、VS241、RESET42、IORDY43、INPACK44、REG45、DASP46、PDIAG47、D848、D949、D1050、GND#include "../inc/includes.h"#include "New_sd.h"sbit c_SPI_CS = P2^4; //Sht-mp3 Config//set MMC_Chip_Select to high (MMC/SD-Card Invalid) #define SD_Disable() c_SPI_CS = 1//set MMC_Chip_Select to low (MMC/SD-Card Active) #define SD_Enable() c_SPI_CS = 0sbit c_SPI_SI = P1^5;sbit c_SPI_SO = P1^6;sbit c_SPI_CLK = P1^7;sbit c_SD_In = P2^7;sbit c_SD_WP = P2^6;sbit c_SD_Power = P2^3;#define Macro_Set_SI_High() c_SPI_SI = 1#define Macro_Set_SI_Low() c_SPI_SI = 0#define Macro_Set_CLK_High() c_SPI_CLK = 1 #define Macro_Set_CLK_Low() c_SPI_CLK = 0//bool bSPICLK_LowSpeed;static void SD_PowerOn(void){c_SD_Power = 0;}/*static void SD_PowerOff(void){c_SD_Power = 1;}*///extern uint8 BUFFER[512];uint8 SD_SPI_ReadByte(void);void SD_SPI_WriteByte(uint8 ucSendData);//#define SPI_ReadByte() SD_SPI_ReadByte()//#define SPI_TransferByte(x) SD_SPI_WriteByte(x) /*static uint8 SPI_ReadByte(void){uchar ucReadData;uchar ucCount;ucReadData = 0;Macro_Set_SI_High();for(ucCount=0; ucCount<8; ucCount++){ucReadData <<= 1;//降低时钟频率Macro_Set_CLK_Low();//降低时钟频率// if(bSPICLK_LowSpeed)// {// Delay_100us();// }Macro_Set_CLK_High();// if(bSPICLK_LowSpeed)// {// Delay_100us();// }if(c_SPI_SO){ucReadData |= 0x01;}}return(ucReadData);// SPDR = 0xFF;// while (!(SPSR & 0x80));// return SPDR;}static void SPI_TransferByte(uint8 ucSendData){uchar ucCount;uchar ucMaskCode;ucMaskCode = 0x80;for(ucCount=0; ucCount<8; ucCount++) {Macro_Set_CLK_Low();if(ucMaskCode & ucSendData){Macro_Set_SI_High();}else{Macro_Set_SI_Low();}//降低时钟频率// if(bSPICLK_LowSpeed)// {// Delay_100us();// }Macro_Set_CLK_High();ucMaskCode >>= 1;//降低时钟频率// if(bSPICLK_LowSpeed)// {// Delay_100us();// }}//SPDR=cmp1;//while(!(SPSR&(1<<SPIF)));}*/static uint8 SPI_ReadByte(void){uchar ucReadData;uchar ucCount;ucReadData = 0;Macro_Set_SI_High();for(ucCount=0; ucCount<8; ucCount++) {ucReadData <<= 1;//降低时钟频率Macro_Set_CLK_Low();//降低时钟频率// if(bSPICLK_LowSpeed)// {// Delay_100us();// }Macro_Set_CLK_High();// if(bSPICLK_LowSpeed)// {// Delay_100us();// }if(c_SPI_SO){ucReadData |= 0x01;}}return(ucReadData);// SPDR = 0xFF;// while (!(SPSR & 0x80));// return SPDR;}static void SPI_TransferByte(uint8 ucSendData) {uchar ucCount;uchar ucMaskCode;ucMaskCode = 0x80;for(ucCount=0; ucCount<8; ucCount++){Macro_Set_CLK_Low();if(ucMaskCode & ucSendData){Macro_Set_SI_High();}else{Macro_Set_SI_Low();}//降低时钟频率// if(bSPICLK_LowSpeed)// {// Delay_100us();// }Macro_Set_CLK_High();ucMaskCode >>= 1;//降低时钟频率// if(bSPICLK_LowSpeed)// Delay_100us();// }}//SPDR=cmp1;//while(!(SPSR&(1<<SPIF)));}void SD_Port_Init(void)//**************************************************************************** {c_SPI_SO = 1;c_SD_In = 1;c_SD_WP = 1;SD_PowerOn();}//**************************************************************************** //Send a Command to MMC/SD-Card//Return: the second byte of response register of MMC/SD-Card uint8 Write_Command_SD(uint8 *cmd)//**************************************************************************** {uint8 tmp,i;uint8 retry=0;SD_Disable();SPI_TransferByte(0xFF);SD_Enable();for(i=0;i<6;i++)SPI_TransferByte(*cmd++);}SPI_ReadByte();do{tmp = SPI_ReadByte();}while((tmp==0xff)&&(retry++ <100));return(tmp);}//**************************************************************************** //Send a Command to MMC/SD-Card//Return: the second byte of response register of MMC/SD-Card uint8 Write_Command_SD_HighSpeed(uint8 *cmd)//**************************************************************************** {uint8 tmp,i;uint8 retry=0;SD_Disable();SD_SPI_WriteByte(0xFF);SD_Enable();for(i=0;i<6;i++){SD_SPI_WriteByte(*cmd++);}SD_SPI_ReadByte();do{tmp = SD_SPI_ReadByte();}while((tmp==0xff)&&(retry++ <100));return(tmp);}//****************************************************************************//Routine for Init MMC/SD card(SPI-MODE)uint8 SD_Init(void)//**************************************************************************** {uint8 retry,temp;uint8 i;uint8 CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};SD_Port_Init(); //Init SPI port// for (i = 0; i < 200; i++) asm("nop"); //Wait MMC/SD ready...for (i = 0; i < 200; i++){_nop_();}//Active SPI bus at low speed// SPCR=0x53; //SPI Master,MSB First// SPSR=0x00; //double speed disable,Fsck=Fosc/128for (i = 0; i < 16; i++)SPI_TransferByte(0xff); //send 74 clock at least!!!//Send Command CMD0 to MMC/SD CardSD_Enable();retry = 0;do{ //retry 200 times to send CMD0 commandtemp = Write_Command_SD(CMD);if (retry++ == 200)return INIT_CMD0_ERROR;//CMD0 Error!}while (temp != 1);//Send Command CMD1 to MMC/SD-CardCMD[0] = 0x41; //Command 1CMD[5] = 0xFF;retry = 0;do{ //retry 100 times to send CMD1 commandtemp = Write_Command_SD(CMD);if (retry++ == 100)return INIT_CMD1_ERROR;//CMD1 Error!}while (temp != 0);//Active High-speed SPI mode(Fsck=Fosc/2)// SPCR = 0x50;// SPSR = 0x00;SD_Disable(); //set MMC_Chip_Select to highreturn INIT_OK; //All commands have been taken.}uint8 SD_Read_Block(uint8 *CMD,uint8 *Buffer,uint16 Bytes)//**************************************************************************** {uint16 i;uint8 retry, temp;//Send Command CMD to MMC/SD-Cardretry=0;//#if 1do{ //Retry 100 times to send command.// temp=Write_Command_SD(CMD);temp=Write_Command_SD_HighSpeed(CMD);if(retry++ == 100)return READ_BLOCK_ERROR; //block write Error!}while (temp != 0);//Read Start Byte form MMC/SD-Card (FEh/Start Byte)while (SPI_ReadByte() != 0xfe);//#endif//Read blocks(normal 512Bytes) to MMC/SD-Card#if 1for (i = 0; i < Bytes; i++) //int count for loop cost 13 machine cycle{// *Buffer++ = SPI_ReadByte(); //Cost 70 Machine Cycle//When define point is a Xdata point then Cost 62 Machine Cycle*Buffer++ = SD_SPI_ReadByte(); //Cost 70 Machine Cycle// put_c(*Buffer);}#endif/*i = Bytes;while(i--) //When Delete {} 2 Machine Cycle is save.*Buffer++ = SPI_ReadByte(); //Cost 70 Machine Cycle*///CRC-ByteSPI_ReadByte();//CRC - ByteSPI_ReadByte();//CRC - Byte//set MMC_Chip_Select to high (MMC/SD-Card invalid)SD_Disable();return READ_BLOCK_OK;}//**************************************************************************** //Routine for writing a Block(512Byte) to MMC/SD-Card//Return 0 if sector writing is completed.uint8 SD_read_sector(uint32 addr,uint8 *Buffer)//**************************************************************************** {//Command 16 is reading Blocks from MMC/SD-Card uint8 CMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};// asm("cli"); //clear all interrupt.//Address conversation(logic block address-->byte address)addr = addr << 9; //addr = addr * 512CMD[1] = ((addr & 0xFF000000) >>24 );CMD[2] = ((addr & 0x00FF0000) >>16 );CMD[3] = ((addr & 0x0000FF00) >>8 );return SD_Read_Block(CMD, Buffer, 512);}/*uint8 SD_write_sector(uint32 addr,uint8 *Buffer)//**************************************************************************** {uint8 tmp,retry;uint16 i;//Command 24 is a writing blocks command for MMC/SD-Card.uint8 CMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};asm("cli"); //clear all interrupt.addr = addr << 9; //addr = addr * 512CMD[1] = ((addr & 0xFF000000) >>24 );CMD[2] = ((addr & 0x00FF0000) >>16 );CMD[3] = ((addr & 0x0000FF00) >>8 );//Send Command CMD24 to MMC/SD-Card (Write 1 Block/512 Bytes) retry=0;do{ //Retry 100 times to send command.tmp = Write_Command_SD(CMD);if(retry++ == 100)return(tmp); //send commamd Error!}while(tmp != 0);//Before writing,send 100 clock to MMC/SD-Cardfor (i = 0; i < 100; i++)SPI_ReadByte();//Send Start Byte to MMC/SD-CardSPI_TransferByte(0xFE);//Now send real data Bolck (512Bytes) to MMC/SD-Cardfor (i = 0; i < 512; i++)SPI_TransferByte(*Buffer++); //send 512 bytes to Card//CRC-ByteSPI_TransferByte(0xFF); //Dummy CRCSPI_TransferByte(0xFF); //CRC Codetmp=SPI_ReadByte(); // read responseif((tmp & 0x1F) != 0x05) // data block accepted ?{SD_Disable();return WRITE_BLOCK_ERROR; //Error!}//Wait till MMC/SD-Card is not busywhile (SPI_ReadByte() != 0xFF){};//set MMC_Chip_Select to high (MMC/SD-Card Invalid)SD_Disable();return 0;}*/extern unsigned char xdata Page_Buf[512]; //文件缓冲区。