2) 初始化
SD卡的初始化是非常重要的,只有进行了正确的初始化,才能进行后面的各项操作。在初始化过程中,SPI的时钟不能太快,否则会造初始化失败。在初始化成功后,应尽量提高SPI的速率。在刚开始要先发送至少74个时钟信号,这是必须的。在很多读者的实验中,很多是因为疏忽了这一点,而使初始化不成功。随后就是写入两个命令CMD0与CMD1,使SD卡进入SPI模式
初始化时序图:
初始化例程:
//--------------------------------------------------------------------------
初始化SD卡到SPI模式
//--------------------------------------------------------------------------
unsigned char SD_Init()
{
unsigned char retry,temp;
unsigned char i;
unsigned char CMD[] = {0x40,0x00,0x00,0x00,0x00,0x95};
SD_Port_Init(); //初始化驱动端口
Init_Flag=1; //将初始化标志置1
for (i=0;i<0x0f;i++)
{
Write_Byte_SD(0xff); //发送至少74个时钟信号
}
//向SD卡发送CMD0
retry=0;
do
{ //为了能够成功写入CMD0,在这里写200次
temp=Write_Command_SD(CMD);
retry++;
if(retry==200)
{ //超过200次
return(INIT_CMD0_ERROR);//CMD0 Error!
}
}
while(temp!=1); //回应01h,停止写入
//发送CMD1到SD卡
CMD[0] = 0x41; //CMD1
CMD[5] = 0xFF;
retry=0;
do
{ //为了能成功写入CMD1,写100次
temp=Write_Command_SD(CMD);
retry++;
if(retry==100)
{ //超过100次
return(INIT_CMD1_ERROR);//CMD1 Error!
}
}
while(temp!=0);//回应00h停止写入
Init_Flag=0; //初始化完毕,初始化标志清零
SPI_CS=1; //片选无效
return(0); //初始化成功
}
3) 读取CID
CID寄存器存储了SD卡的标识码。每一个卡都有唯一的标识码。
CID寄存器长度为128位。它的寄存器结构如下:
名称
|
域
|
数据宽度
|
CID划分
|
生产标识号
|
MID
|
8
|
[127:120]
|
OEM/应用标识
|
OID
|
16
|
[119:104]
|
产品名称
|
PNM
|
40
|
[103:64]
|
产品版本
|
PRV
|
8
|
[63:56]
|
产品序列号
|
PSN
|
32
|
[55:24]
|
保留
|
-
|
4
|
[23:20]
|
生产日期
|
MDT
|
12
|
[19:8]
|
CRC7校验合
|
CRC
|
7
|
[7:1]
|
未使用,始终为1
|
-
|
1
|
[0:0]
|
它的读取时序如下:
与此时序相对应的程序如下:
//------------------------------------------------------------------------------------
读取SD卡的CID寄存器 16字节 成功返回0
//-------------------------------------------------------------------------------------
unsigned char Read_CID_SD(unsigned char *Buffer)
{
//读取CID寄存器的命令
unsigned char CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
unsigned char temp;
temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes
return(temp);
}
4)读取CSD
CSD(Card-Specific Data)寄存器提供了读写SD卡的一些信息。其中的一些单元可以由用户重新编程。具体的CSD结构如下:
名称
|
域
|
数据宽度
|
单元类型
|
CSD划分
|
CSD结构
|
CSD_STRUCTURE
|
2
|
R
|
[127:126]
|
保留
|
-
|
6
|
R
|
[125:120]
|
数据读取时间1
|
TAAC
|
8
|
R
|
[119:112]
|
数据在CLK周期内读取时间2(NSAC*100)
|
NSAC
|
8
|
R
|
[111:104]
|
最大数据传输率
|
TRAN_SPEED
|
8
|
R
|
[103:96]
|
卡命令集合
|
CCC
|
12
|
R
|
[95:84]
|
最大读取数据块长
|
READ_BL_LEN
|
4
|
R
|
[83:80]
|
允许读的部分块
|
READ_BL_PARTIAL
|
1
|
R
|
[79:79]
|
非线写块
|
WRITE_BLK_MISALIGN
|
1
|
R
|
[78:78]
|
非线读块
|
READ_BLK_MISALIGN
|
1
|
R
|
[77:77]
|
DSR条件
|
DSR_IMP
|
1
|
R
|
[76:76]
|
保留
|
-
|
2
|
R
|
[75:74]
|
设备容量
|
C_SIZE
|
12
|
R
|
[73:62]
|
最大读取电流@VDD min
|
VDD_R_CURR_MIN
|
3
|
R
|
[61:59]
|
最大读取电流@VDD max
|
VDD_R_CURR_MAX
|
3
|
R
|
[58:56]
|
最大写电流@VDD min
|
VDD_W_CURR_MIN
|
3
|
R
|
[55:53]
|
最大写电流@VDD max
|
VDD_W_CURR_MAX
|
3
|
R
|
[52:50]
|
设备容量乘子
|
C_SIZE_MULT
|
3
|
R
|
[49:47]
|
擦除单块使能
|
ERASE_BLK_EN
|
1
|
R
|
[46:46]
|
擦除扇区大小
|
SECTOR_SIZE
|
7
|
R
|
[45:39]
|
写保护群大小
|
WP_GRP_SIZE
|
7
|
R
|
[38:32]
|
写保护群使能
|
WP_GRP_ENABLE
|
1
|
R
|
[31:31]
|
保留
|
-
|
2
|
R
|
[30:29]
|
写速度因子
|
R2W_FACTOR
|
3
|
R
|
[28:26]
|
最大写数据块长度
|
WRITE_BL_LEN
|
4
|
R
|
[25:22]
|
允许写的部分部
|
WRITE_BL_PARTIAL
|
1
|
R
|
[21:21]
|
保留
|
-
|
5
|
R
|
[20:16]
|
文件系统群
|
FILE_OFRMAT_GRP
|
1
|
R/W
|
[15:15]
|
拷贝标志
|
COPY
|
1
|
R/W
|
[14:14]
|
永久写保护
|
PERM_WRITE_PROTECT
|
1
|
R/W
|
[13:13]
|
暂时写保护
|
TMP_WRITE_PROTECT
|
1
|
R/W
|
[12:12]
|
文件系统
|
FIL_FORMAT
|
2
|
R/W
|
[11:10]
|
保留
|
-
|
2
|
R/W
|
[9:8]
|
CRC
|
CRC
|
7
|
R/W
|
[7:1]
|
未用,始终为1
|
-
|
1
|
|
[0:0]
|
读取CSD 的时序:
相应的程序例程如下:
//-----------------------------------------------------------------------------------------
读SD卡的CSD寄存器 共16字节 返回0说明读取成功
//-----------------------------------------------------------------------------------------
unsigned char Read_CSD_SD(unsigned char *Buffer)
{
//读取CSD寄存器的命令
unsigned char CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
unsigned char temp;
temp=SD_Read_Block(CMD,Buffer,16); //read 16 bytes
return(temp);
}
2/3 首页 上一页 1 2 3 下一页 尾页 |