2011-05-12 15:32 682人阅读 评论(0) 收藏 举报
SD卡引脚定义: 针脚 名称 类型 描述
1 CD DAT3 I/O/PP 卡监测数据位3 2 CMD PP 命令/回复 3 Vss S 地 4 Vcc S 供电电压 5 CLK I 时钟 6 Css2 S 地 7 DAT0 I/O/PP 数据位0 8 DAT1 I/O/PP 数据位1 9 DAT2 I/O/PP 数据位2
SD卡接口标准规范
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,循环冗余校验)校验位,最后一位为停止位0
2.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 bits
class7:卡的锁定,解锁功能命令集 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,DATA2 2,CD/DATA3 3,CMD 4,VCC 5,CLK 6,GND 7,DATA0 8,DATA1 sd卡: 一、SD MODE 1、CD/DATA3 2、CMD 3、VSS1 4、VDD 5、CLK 6、VSS2 7、DATA0 8、DATA1 9、DATA2 二、SPI MODE 1、CS 2、DI 3、VSS 4、VDD 5、SCLK 6、VSS2 7、DO 8、RSV 9、RSV
CF卡
一、PC CARD MEMORY MODE 1、GND 2、D3 3、D4 4、D5 5、D6 6、D7 7、CE1 8、A10 9、OE 10、A9 11、A8 12、A7 13、VCC 14、A6 15、A5 16、A4 17、A3 18、A2 19、A1 20、A0 21、D0 22、D1 23、D2 24、WP 25、CD2 26、CD1 27、D11 28、D12 29、D13 30、D14 31、D15 32、CE2
33、VS1 34、IORD 35、IOWR 36、WE 37、RDY/BSY 38、VCC 39、CSEL 40、VS2 41、RESET 42、WAIT 43、INPACK 44、REG 45、BVD2 46、BVD1 47、D8 48、D9 49、D10 50、GND CF卡
二、PC I/O CARD MODE 1、GND 2、D3 3、D4 4、D5 5、D6 6、D7 7、CE1 8、A10 9、OE 10、A9 11、A8 12、A7 13、VCC 14、A6 15、A5
16、A4 17、A3 18、A2 19、A1 20、A0 21、D0 22、D1 23、D2 24、IOIS16 25、CD2 26、CD1 27、D11 28、D12 29、D13 30、D14 31、D15 32、CE2 33、VS1 34、IORD 35、IOWR 36、WE 37、RDY/BSY 38、VCC 39、CSEL 40、VS2 41、RESET 42、WAIT 43、INPACK 44、REG 45、SPKR 46、STSCHG 47、D8 48、D9 49、D10 50、GND
CF卡
三、TRUE IDE MODE 1、GND 2、D3 3、D4 4、D5 5、D6 6、D7 7、CS0 8、A10 9、ATA SEL 10、A9 11、A8 12、A7 13、VCC 14、A6 15、A5 16、A4 17、A3 18、A2 19、A1 20、A0 21、D0 22、D1 23、D2 24、IOIS16 25、CD2 26、CD1 27、D11 28、D12 29、D13 30、D14 31、D15 32、CS1 33、VS1
34、IORD 35、IOWR 36、WE 37、INTRQ 38、VCC 39、CSEL 40、VS2 41、RESET 42、IORDY 43、INPACK 44、REG 45、DASP 46、PDIAG 47、D8 48、D9 49、D10 50、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 = 0
sbit 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< 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< //**************************************************************************** { 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/128 for (i = 0; i < 16; i++) SPI_TransferByte(0xff); //send 74 clock at least!!! //Send Command CMD0 to MMC/SD Card SD_Enable(); retry = 0; do { //retry 200 times to send CMD0 command temp = Write_Command_SD(CMD); if (retry++ == 200) return INIT_CMD0_ERROR;//CMD0 Error! } while (temp != 1); //Send Command CMD1 to MMC/SD-Card CMD[0] = 0x41; //Command 1 CMD[5] = 0xFF; retry = 0; do { //retry 100 times to send CMD1 command temp = 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 high return 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-Card retry=0; //#if 1 do { //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 1 for (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-Byte SPI_ReadByte();//CRC - Byte SPI_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 * 512 CMD[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 * 512 CMD[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-Card for (i = 0; i < 100; i++) SPI_ReadByte(); //Send Start Byte to MMC/SD-Card SPI_TransferByte(0xFE); //Now send real data Bolck (512Bytes) to MMC/SD-Card for (i = 0; i < 512; i++) SPI_TransferByte(*Buffer++); //send 512 bytes to Card //CRC-Byte SPI_TransferByte(0xFF); //Dummy CRC SPI_TransferByte(0xFF); //CRC Code tmp=SPI_ReadByte(); // read response if((tmp & 0x1F) != 0x05) // data block accepted ? { SD_Disable(); return WRITE_BLOCK_ERROR; //Error! } //Wait till MMC/SD-Card is not busy while (SPI_ReadByte() != 0xFF){}; //set MMC_Chip_Select to high (MMC/SD-Card Invalid) SD_Disable(); return 0; } */ extern unsigned char xdata Page_Buf[512]; //文件缓冲区。 void SD_SPI_WriteByte(uint8 ucSendData); //测试SD卡SPI接口性能 void TestSD_SPIFunc(void) { uchar ucCount; uchar ucReadData; ucCount = 0; //开始 for(ucCount=0; ucCount<10; ucCount++) { // SPI_TransferByte(0x88); //用C语言实现的写字节机器周期数为188 SD_SPI_WriteByte(0x88); //用C51的bData变量,采用位指令直接传送操作,共用机器机器49 } for(ucCount=0; ucCount<50; ucCount++) { ucReadData = SPI_ReadByte(); //用C语言实现的SPI读字节机器赌周期为154 //自用C51的bData变量,采用位指令操作读字节机器周期为49 } ucCount= 88; //结束 SD_read_sector(0,Page_Buf); } sd卡封装 分类: ARM_其他接口 2011-06-02 11:32 432人阅读 评论(0) 收藏 举报 有些SD卡封装不仅有原来的SD卡的1~9输出接口还有检查是否插入SD卡的(nCD Card Detection)以及检测SD卡是否写保护的(WP Write Protection)引脚 如图:10脚既是检测是否插入SD卡的nCD(CD)低电平表示插入,高电平表示是未插入。高电平需要上拉产生,插入式该脚在卡座设计上连接到地因此低电平表示插入。 同理11脚是SD卡写保护检测脚,未写保护此脚为低电平,写保护则此脚为高电平(这个要看卡座的设计)。 因篇幅问题不能全部显示,请点此查看更多更全内容