SD卡在单片机上的应用
与此时序相对应的程序如下:
//------------------------------------------------------------
读取SD卡的CID寄存器 16字节 成功返回0
//------------------------------------------------------------
unsignedcharRead_CID_SD(unsignedchar*Buffer)
{
//读取CID寄存器的命令
unsignedcharCMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF};
unsignedchartemp;
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说明读取成功
//-------------------------------------------------------------------
unsignedcharRead_CSD_SD(unsignedchar*Buffer)
{
//读取CSD寄存器的命令
unsignedcharCMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
unsignedchartemp;
temp=SD_Read_Block(CMD,Buffer,16);//read 16 bytes
return(temp);
}
4) 读取SD卡信息
综合上面对CID与CSD寄存器的读取,可以知道很多关于SD卡的信息,以下程序可以获取这些信息。如下:
//----------------------------------------------------------------------
//返回
// SD卡的容量,单位为M
// sector count and multiplier MB are in
u08 == C_SIZE / (2^(9-C_SIZE_MULT))
// SD卡的名称
//----------------------------------------------------------------------
voidSD_get_volume_info()
{
unsignedchari;
unsignedcharc_temp[5];
VOLUME_INFO_TYPE SD_volume_Info,*vinf;
vinf=SD_volume_Info;//Init the pointoer;
/读取CSD寄存器
Read_CSD_SD(sectorBuffer.dat);
//获取总扇区数
vinf->sector_count = sectorBuffer.dat[6] 0x03;
vinf->sector_count = 8;
vinf->sector_count += sectorBuffer.dat[7];
vinf->sector_count = 2;
vinf->sector_count += (sectorBuffer.dat[8] 0xc0) >> 6;
// 获取multiplier
vinf->sector_multiply = sectorBuffer.dat[9] 0x03;
vinf->sector_multiply = 1;
vinf->sector_multiply += (sectorBuffer.dat[10] 0x80) >> 7;
//获取SD卡的容量
vinf->size_MB = vinf->sector_count >> (9-vinf->sector_multiply);
// get the name of the card
Read_CID_SD(sectorBuffer.dat);
vinf->name[0] = sectorBuffer.dat[3];
vinf->name[1] = sectorBuffer.dat[4];
vinf->name[2] = sectorBuffer.dat[5];
vinf->name[3] = sectorBuffer.dat[6];
vinf->name[4] = sectorBuffer.dat[7];
vinf->name[5] = 0x00;//end flag
}
以上程序将信息装载到一个结构体中,这个结构体的定义如下:
typedefstructSD_VOLUME_INFO
{//SD/SD Card info
unsignedintsize_MB;
unsignedcharsector_multiply;
unsignedintsector_count;
unsignedcharname[6];
} VOLUME_INFO_TYPE;
5) 扇区读
扇区读是对SD卡驱动的目的之一。SD卡的每一个扇区中有512个字节,一次扇区读操作将把某一个扇区内的512个字节全部读出。过程很简单,先写入命令,在得到相应的回应后,开始数据读取。
扇区读的时序:
扇区读的程序例程:
unsignedcharSD_Read_Sector(unsignedlongsector,unsignedchar*buffer)
{
unsignedcharretry;
//命令16
unsignedcharCMD[] = {0x51,0x00,0x00,0x00,0x00,0xFF};
unsignedchartemp;
//地址变换 由逻辑块地址转为字节地址
sector = sector 9;//sector = sector * 512
CMD[1] = ((sector 0xFF000000) >>24 );
CMD[2] = ((sector 0x00FF0000) >>16 );
CMD[3] = ((sector 0x0000FF00) >>8 );
//将命令16写入SD卡
retry=0;
do
{//为了保证写入命令 一共写100次
temp=Write_Command_MMC(CMD);
retry++;
if(retry==100)
{
return(READ_BLOCK_ERROR);//block write Error!
}
}
while(temp!=0);
//Read Start Byte form MMC/SD-Card (FEh/Start Byte)
//Now data is ready,you can read it out.
while(Read_Byte_MMC() != 0xfe);
readPos=0;
SD_get_data(512,buffer) ;//512字节被读出到buffer中
return0;
}
其中SD_get_data函数如下:
//---------------------------------------------------------
获取数据到buffer中
//---------------------------------------------------------
voidSD_get_data(unsignedintBytes,unsignedchar*buffer)
{
unsignedintj;
for(j=0;jBytes;j++)
*buffer++ = Read_Byte_SD();
}
6) 扇区写
扇区写是SD卡驱动的另一目的。每次扇区写操作将向SD卡的某个扇区中写入512个字节。过程与扇区读相似,只是数据的方向相反与写入命令不同而已。
扇区写的时序:
扇区写的程序例程:
//-----------------------------------------------------------------
写512个字节到SD卡的某一个扇区中去 返回0说明写入成功
//-----------------------------------------------------------------
unsignedcharSD_write_sector(unsignedlongaddr,unsignedchar*Buffer)
{
unsignedchartmp,retry;
unsignedinti;
//命令24
unsignedcharCMD[] = {0x58,0x00,0x00,0x00,0x00,0xFF};
addr = addr 9;//addr = addr * 512
CMD[1] = ((addr 0xFF000000) >>24 );
CMD[2] = ((addr 0x00FF0000) >>16 );
CMD[3] = ((addr 0x0000FF00) >>8 );
//写命令24到SD卡中去
retry=0;
do
{//为了可靠写入,写100次
tmp=Write_Command_SD(CMD);
retry++;
if(retry==100)
{
return(tmp);//send commamd Error!
}
}
while(tmp!=0);
//在写之前先产生100个时钟信号
for(i=0;i100;i++)
{
Read_Byte_SD();
}
//写入开始字节
Write_Byte_MMC(0xFE);
//现在可以写入512个字节
for(i=0;i512;i++)
{
Write_Byte_MMC(*Buffer++);
}
//CRC-Byte
Write_Byte_MMC(0xFF);//Dummy CRC
Write_Byte_MMC(0xFF);//CRC Code
tmp=Read_Byte_MMC();// read response
if((tmp 0x1F)!=0x05)// 写入的512个字节是未被接受
{
SPI_CS=1;
return(WRITE_BLOCK_ERROR);//Error!
}
//等到SD卡不忙为止
//因为数据被接受后,SD卡在向储存阵列中编程数据
while(Read_Byte_MMC()!=0xff){};
//禁止SD卡
SPI_CS=1;
return(0);//写入成功
}
此上内容在笔者的实验中都已调试通过。单片机采用STC89LE单片机(SD卡的初始化电压为2.0V~3.6V,操作电压为3.1V~3.5V,因此不能用5V单片机,或进行分压处理),工作于22.1184M的时钟下,由于所采用的单片机中没硬件SPI,采用软件模拟SPI,因此读写速率都较慢。如果要半SD卡应用于音频、视频等要求高速场合,则需要选用有硬件SPI的控制器,或使用SD模式,当然这就需要各位读者对SD模式加以研究,有了SPI模式的基础,SD模式应该不是什么难事。
51单片机相关文章:51单片机教程
单片机相关文章:单片机教程
单片机相关文章:单片机视频教程
单片机相关文章:单片机工作原理
评论