You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

854 lines
36 KiB

#include "asp_sdx1.h"
///#include "myfun.h"
////#include "sd_type.h"
#include "bsp_sd1_iospi.h"
/*★★★★★★★★★★★★★★★★★★★★★★★★
znFAT--FAT32文件系统设计与实现
[]
3
FAT32文件系统SD卡等嵌入式存储技术的
znFAT
ZN-X开发板51AVRSTM32(M0/M3/M4)
CPU
www.znmcu.cn
*/
/***************************************************************************************
ZN-X开发板SD卡1 STC51部分:STC15L2K60S2
SD卡的扇区读写
SD卡MMC/SD/SDHC
znFAT--FAT32文件系统设计与实验 11SD卡物理驱动
SD卡专辑
****************************************************************************************/
//变量定义
//--------------------------------------------------------------
extern UINT8 Low_or_High1; //在IOSPI中定义
UINT8 SD1_Addr_Mode=0; //SD1的寻址方式,1为块寻址,0为字节寻址
UINT8 SD1_Ver=SD_VER_ERR; //SD卡1的版本
//---------------------------------------------------------------
#define SD1_SPI_SPEED_HIGH() Low_or_High1=0
#define SD1_SPI_SPEED_LOW() Low_or_High1=1
#define SD1_SPI_WByte(x) SD1_IOSPI_RWByte(x)
#define SD1_SPI_RByte() SD1_IOSPI_RWByte(0XFF)
/********************************************************************
- ZN-X开发板SD卡1SPI接口初始化
-
- 0
- SPI接口初始化后SD卡在初始化的过程中要求
SPI速度要比较低400KHZ240KHZ
SD卡初始化不成功SPI速度SD
********************************************************************/
UINT8 SD1_SPI_Init(void)
{
SD1_IOSPI_Init(); //SPI接口初始化
return 0;
}
/******************************************************************
- SD卡写命令
- SD卡的命令是6个字节pcmd是指向命令字节序列的指针
- 0xff
******************************************************************/
UINT8 SD1_Write_Cmd(UINT8 *pcmd)
{
UINT8 r=0,time=0;
SET_SD1_CS_PIN(1);
SD1_SPI_WByte(0xFF); //发送8个时钟,提高兼容性,如果没有这里,有些SD卡可能不支持
SET_SD1_CS_PIN(0);
while(0XFF!=SD1_SPI_RByte())
{/// add by cc for没有SD卡应退出
; //等待SD卡准备好,再向其发送命令
time++;
L0_uart0_uc(0x30+time);
if(time>=200)
{
L0_uart0_uc('E');
L0_uart0_0d0a();
SET_SD1_CS_PIN(1);
return(INIT_CMD0_ERROR);//CMD0写入失败
}
}
//将6字节的命令序列写入SD卡
SD1_SPI_WByte(pcmd[0]);
SD1_SPI_WByte(pcmd[1]);
SD1_SPI_WByte(pcmd[2]);
SD1_SPI_WByte(pcmd[3]);
SD1_SPI_WByte(pcmd[4]);
SD1_SPI_WByte(pcmd[5]);
if(pcmd[0]==0X1C) SD1_SPI_RByte(); //如果是停止命令,跳过多余的字节
do
{
r=SD1_SPI_RByte();
time++;
}while((r&0X80)&&(time<TRY_TIME)); //如果重试次数超过TRY_TIME则返回错误
return r;
}
/******************************************************************
block和读多块block
SD卡读单块和多块的命令分别为CMD17和CMD18
SD卡的读写要求地址对齐
512Byte
0011<<9(512
22<<9(1024
- SD卡初始化SD卡MMCSD或SDHC
-
- 0x00
******************************************************************/
UINT8 SD1_Init(void)
{
UINT8 time=0,r=0,i=0;
UINT8 rbuf[4]={0};
UINT8 pCMD0[6] ={0x40,0x00,0x00,0x00,0x00,0x95}; //CMD0,将SD卡从默认上电后的SD模式切换到SPI模式,使SD卡进入IDLE状态
UINT8 pCMD1[6] ={0x41,0x00,0x00,0x00,0x00,0x01}; //CMD1,MMC卡使用CMD1命令进行初始化
UINT8 pCMD8[6] ={0x48,0x00,0x00,0x01,0xAA,0x87}; //CMD8,用于鉴别SD卡的版本,并可从应答得知SD卡的工作电压
UINT8 pCMD16[6]={0x50,0x00,0x00,0x02,0x00,0x01}; //CMD16,设置扇区大小为512字节,此命令用于在初始化完成之后进行试探性的操作,
//如果操作成功,说明初始化确实成功
UINT8 pCMD55[6]={0x77,0x00,0x00,0x00,0x00,0x01}; //CMD55,用于告知SD卡后面是ACMD,即应用层命令 CMD55+ACMD41配合使用
//MMC卡使用CMD1来进行初始化,而SD卡则使用CMD55+ACMD41来进行初始化
UINT8 pACMD41H[6]={0x69,0x40,0x00,0x00,0x00,0x01}; //ACMD41,此命令用于检测SD卡是否初始化完成,MMC卡,不适用此命令,针对2.0的SD卡
UINT8 pACMD41S[6]={0x69,0x00,0x00,0x00,0x00,0x01}; //ACMD41,此命令用于检测SD卡是否初始化完成,MMC卡,不适用此命令,针对1.0的SD卡
UINT8 pCMD58[6]={0x7A,0x00,0x00,0x00,0x00,0x01}; //CMD58,用于鉴别SD2.0到底是SDHC,还是普通的SD卡,二者对扇区地址的寻址方式不同
SD1_SPI_Init(); //SPI接口相关初始化
SD1_SPI_SPEED_LOW(); //首先将SPI切为低速
SET_SD1_CS_PIN(1);
for(i=0;i<0x0f;i++) //首先要发送最少74个时钟信号,这是必须的!激活SD卡
{
SD1_SPI_WByte(0xff); //120个时钟
}
L0_uart0_uc('5'); L0_uart0_uc(0x09); L0_uart0_uc('5'); L0_uart0_uc(0x09);
time=0;
do
{
r=SD1_Write_Cmd(pCMD0);//写入CMD0
time++;
if(time>= TRY_TIME2)
{
L0_uart0_uc(0x09);
L0_uart0_uc('R');
L0_uart0_uc(0x09);
return(INIT_CMD0_ERROR);//CMD0写入失败
}
}while(r!=0x01);
L0_uart0_uc(0x09);
L0_uart0_uc('6');
L0_uart0_uc(0x09);
if(1==SD1_Write_Cmd(pCMD8))//写入CMD8,如果返回值为1,则SD卡版本为2.0
{
L0_uart0_sendstr("SDver:2.0\r\n");/////4g卡
rbuf[0]=SD1_SPI_RByte(); rbuf[1]=SD1_SPI_RByte(); //读取4个字节的R7回应,通过它可知此SD卡是否支持2.7~3.6V的工作电压
rbuf[2]=SD1_SPI_RByte(); rbuf[3]=SD1_SPI_RByte();
if(rbuf[2]==0X01 && rbuf[3]==0XAA)//SD卡是否支持2.7~3.6V
{
L0_uart0_sendstr("2.7~3.6V=");/////4g卡
time=0;
do
{
SD1_Write_Cmd(pCMD55);//写入CMD55
r=SD1_Write_Cmd(pACMD41H);//写入ACMD41,针对SD2.0
time++;
if(time>=TRY_TIME)
{
return(INIT_SDV2_ACMD41_ERROR);//对SD2.0使用ACMD41进行初始化时产生错误
}
}while(r!=0);
if(0==SD1_Write_Cmd(pCMD58)) //写入CMD58,开始鉴别SD2.0
{
rbuf[0]=SD1_SPI_RByte(); rbuf[1]=SD1_SPI_RByte(); //读取4个字节的OCR,其中CCS指明了是SDHC还是普通的SD
rbuf[2]=SD1_SPI_RByte(); rbuf[3]=SD1_SPI_RByte();
if(rbuf[0]&0x40)
{
SD1_Ver=SD_VER_V2HC; //SDHC卡
SD1_Addr_Mode=1; //SDHC卡的扇区寻址方式是扇区地址
}
else SD1_Ver=SD_VER_V2; //普通的SD卡,2.0的卡包含SDHC和一些普通的卡
}
if(!SD1_Addr_Mode)
{
//addr = addr * 512 将块地址(扇区地址)转为字节地址
L0_uart0_uc(0x30+SD1_Addr_Mode);
L0_uart0_sendstr("<<9 \r\n");/////4g卡
}
else
{
L0_uart0_uc(0x30+SD1_Addr_Mode);
L0_uart0_sendstr("1 mass adr \r\n");/////4g卡
}
}
}
else //SD V1.0或MMC
{
L0_uart0_sendstr("SD V1.0 or MMC \r\n");
//SD卡使用ACMD41进行初始化,而MMC使用CMD1来进行初始化,依此来进一步判断是SD还是MMC
SD1_Write_Cmd(pCMD55);//写入CMD55
r=SD1_Write_Cmd(pACMD41S);//写入ACMD41,针对SD1.0
if(r<=1) //检查返回值是否正确,如果正确,说明ACMD41命令被接受,即为SD卡
{
SD1_Ver=SD_VER_V1; //普通的SD1.0卡,一般来说容量不会超过2G
time=0;
do
{
SD1_Write_Cmd(pCMD55);//写入CMD55
r=SD1_Write_Cmd(pACMD41S);//写入ACMD41,针对SD1.0
time++;
if(time>=TRY_TIME)
{
return(INIT_SDV1_ACMD41_ERROR);//对SD1.0使用ACMD41进行初始化时产生错误
}
}while(r!=0);
}
else //否则为MMC
{
SD1_Ver=SD_VER_MMC; //MMC卡,它不支持ACMD41命令,而是使用CMD1进行初始化
time=0;
do
{
r=SD1_Write_Cmd(pCMD1);//写入CMD1
time++;
if(time>=TRY_TIME)
{
return(INIT_CMD1_ERROR);//MMC卡使用CMD1命令进行初始化中产生错误
}
}while(r!=0);
}
}
if(0!=SD1_Write_Cmd(pCMD16)) //SD卡的块大小必须为512字节
{
SD1_Ver=SD_VER_ERR; //如果不成功,则此卡为无法识别的卡
return INIT_ERROR;
}
SET_SD1_CS_PIN(1);
SD1_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
SD1_SPI_SPEED_HIGH(); //SPI切到高速
return 0;//返回0,说明复位操作成功
}
/******************************************************************
- SD卡若干个扇区进行擦除
00XFF使
- addr_sta addr_end
- 0x00
add by cc addr_sta=addr_end
CMD32 ERASE_WR_BLK_START Mandatory
CMD33 ERASE_WR_BLK_END Mandatory
CMD38 ERASE Mandatory
Class5 ():
CMD32:.
CMD33:.
CMD38: .
******************************************************************/
UINT8 SD1_Erase_nSector(UINT32 addr_sta,UINT32 addr_end)
{
UINT8 r,time;
UINT8 i=0;
UINT8 pCMD32[]={0x60,0x00,0x00,0x00,0x00,0xff}; //设置擦除的开始扇区地址
UINT8 pCMD33[]={0x61,0x00,0x00,0x00,0x00,0xff}; //设置擦除的结束扇区地址
UINT8 pCMD38[]={0x66,0x00,0x00,0x00,0x00,0xff}; //擦除扇区
if(!SD1_Addr_Mode)
{
addr_sta<<=9;addr_end<<=9;
//addr = addr * 512 将块地址(扇区地址)转为字节地址
}
pCMD32[1]=addr_sta>>24; //将开始地址写入到CMD32字节序列中
pCMD32[2]=addr_sta>>16;
pCMD32[3]=addr_sta>>8;
pCMD32[4]=addr_sta;
pCMD33[1]=addr_end>>24; //将开始地址写入到CMD32字节序列中
pCMD33[2]=addr_end>>16;
pCMD33[3]=addr_end>>8;
pCMD33[4]=addr_end;
time=0;
do
{
r=SD1_Write_Cmd(pCMD32);
time++;
if(time==TRY_TIME)
{
return(r); //命令写入失败
}
}while(r!=0);
time=0;
do
{
r=SD1_Write_Cmd(pCMD33);
time++;
if(time==TRY_TIME)
{
return(r); //命令写入失败
}
}while(r!=0);
time=0;
do
{
r=SD1_Write_Cmd(pCMD38);
time++;
if(time==TRY_TIME)
{
return(r); //命令写入失败
}
}while(r!=0);
return 0;
}
/****************************************************************************
- buffer指向的512个字节的数据写入到SD卡的addr扇区中
- addr:
buffer:
- 0x00
- SD卡初始化成功后SPI速度提上来
cc modify :tf卡的读写次数是10W次13600s 36000
****************************************************************************/
UINT8 L1_SD_Wsector(UINT32 addr,UINT8 *buffer) //向SD卡中的指定地址的扇区写入512个字节,使用CMD24(24号命令)
{
UINT8 r,time;
UINT16 i=0;
UINT8 pCMD24[]={0x58,0x00,0x00,0x00,0x00,0xff}; //向SD卡中单个块(512字节,一个扇区)写入数据,用CMD24
if(!SD1_Addr_Mode)
{
addr<<=9; //addr = addr * 512 将块地址(扇区地址)转为字节地址
}
pCMD24[1]=addr>>24; //将字节地址写入到CMD24字节序列中
pCMD24[2]=addr>>16;
pCMD24[3]=addr>>8;
pCMD24[4]=addr;
time=0;
do
{
r=SD1_Write_Cmd(pCMD24);
time++;
if(time==TRY_TIME)
{
SET_SD1_CS_PIN(1);
return(r); //命令写入失败
}
}while(r!=0);
while(0XFF!=SD1_SPI_RByte()); //等待SD卡准备好,再向其发送命令及后续的数据
SD1_SPI_WByte(0xFE);//写入开始字节 0xfe,后面就是要写入的512个字节的数据
for(i=0;i<512;i++) //将缓冲区中要写入的512个字节写入SD1卡,减少循环次数,提高数据写入速度
{
SD1_SPI_WByte(*(buffer++));
/**SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));**/
}
SD1_SPI_WByte(0xFF);
SD1_SPI_WByte(0xFF); //两个字节的CRC校验码,不用关心
r=SD1_SPI_RByte(); //读取返回值
if((r & 0x1F)!=0x05) //如果返回值是 XXX00101 说明数据已经被SD卡接受了
{
return(WRITE_BLOCK_ERROR); //写块数据失败
}
while(0xFF!=SD1_SPI_RByte());//等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到自身的FLASH中,需要一个时间)
//忙时,读回来的值为0x00,不忙时,为0xff
SET_SD1_CS_PIN(1);
SD1_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
return(0); //返回0,说明写扇区操作成功
}
UINT8 L2_SD_Rsector(UINT16 addr,UINT8 *buffer)//从SD卡的指定扇区中读出512个字节,使用CMD17(17号命令)
{
UINT32 addr32 = D_FILE_SECTOR;
addr32 += (UINT32)addr;
return L1_SD_Rsector(addr32,buffer);
}
UINT8 L2_SD_Wsector(UINT16 addr,UINT8 *buffer) //向SD卡中的指定地址的扇区写入512个字节,使用CMD24(24号命令)
{
UINT32 addr32 = D_FILE_SECTOR;
addr32 += (UINT32)addr;
return L1_SD_Wsector(addr32,buffer);
}
UINT8 L2_SD_Erase_nSector(UINT16 addr_sta,UINT16 addr_end)
{
UINT32 addr32= D_FILE_SECTOR,addr32end= D_FILE_SECTOR;
addr32 += (UINT32)addr_sta;
addr32end += (UINT32)addr_end;
return SD1_Erase_nSector(addr32,addr32end);
}
/****************************************************************************
- addr扇区的512个字节到buffer指向的数据缓冲区
- addr:
buffer:
- 0x00
- SD卡初始化成功后SPI速度提上来
****************************************************************************/
UINT8 L1_SD_Rsector(UINT32 addr,UINT8 *buffer)//从SD卡的指定扇区中读出512个字节,使用CMD17(17号命令)
{
UINT16 i;
UINT8 time,r;
UINT8 pCMD17[]={0x51,0x00,0x00,0x00,0x00,0x01}; //CMD17的字节序列
if(!SD1_Addr_Mode)
{
addr<<=9; //sector = sector * 512 将块地址(扇区地址)转为字节地址
}
pCMD17[1]=addr>>24; //将字节地址写入到CMD17字节序列中
pCMD17[2]=addr>>16;
pCMD17[3]=addr>>8;
pCMD17[4]=addr;
L0_uart0_uc('Q');
time=0;
do
{
r=SD1_Write_Cmd(pCMD17); //写入CMD17
time++;
///L0_uart0_uc(0x30+time);
if(time==TRY_TIME)
{
L0_uart0_uc('T');
SET_SD1_CS_PIN(1);
return(READ_BLOCK_ERROR); //读块失败
}
}while(r!=0);
L0_uart0_uc('A');
time = 0;
while(SD1_SPI_RByte()!= 0xFE)
{ //一直读,当读到0xfe时,说明后面的是512字节的数据了
time++;
///L0_uart0_uc(0x30+time);
if(time==TRY_TIME)
{
L0_uart0_uc('F');
SET_SD1_CS_PIN(1);
return(READ_BLOCK_ERROR); //读块失败
}
}
//L0_uart0_uc('i');
for(i=0;i<512;i++) //将数据写入到数据缓冲区中
{
*(buffer++)=SD1_SPI_RByte();
/**
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
**/
}
SD1_SPI_RByte();
SD1_SPI_RByte();//读取两个字节的CRC校验码,不用关心它们
SET_SD1_CS_PIN(1);
SD1_SPI_WByte(0xFF); //按照SD1卡的操作时序在这里补8个时钟
return 0;
}
#if 0
/****************************************************************************
- addr扇区开始的nsec个扇区写入数据
- nsec:
addr:
buffer:
- 0x00
- SD卡初始化成功后SPI速度提上来
****************************************************************************/
UINT8 SD1_Write_nSector(UINT32 nsec,UINT32 addr,UINT8 *buffer)
{
UINT8 r,time;
UINT32 i=0,j=0,m=0;
UINT8 pCMD25[6]={0x59,0x00,0x00,0x00,0x00,0x01}; //CMD25用于完成多块连续写
UINT8 pCMD55[6]={0x77,0x00,0x00,0x00,0x00,0x01}; //CMD55,用于告知SD卡后面是ACMD,CMD55+ACMD23
UINT8 pACMD23[6]={0x57,0x00,0x00,0x00,0x00,0x01};//CMD23,多块连续预擦除
if(!SD1_Addr_Mode) addr<<=9;
pCMD25[1]=addr>>24;
pCMD25[2]=addr>>16;
pCMD25[3]=addr>>8;
pCMD25[4]=addr;
pACMD23[1]=nsec>>24;
pACMD23[2]=nsec>>16;
pACMD23[3]=nsec>>8;
pACMD23[4]=nsec;
if(SD1_Ver!=SD_VER_MMC) //如果不是MMC卡,则首先写入预擦除命令,CMD55+ACMD23,这样后面的连续块写的速度会更快
{
SD1_Write_Cmd(pCMD55);
SD1_Write_Cmd(pACMD23);
}
time=0;
do
{
r=SD1_Write_Cmd(pCMD25);
time++;
if(time==TRY_TIME)
{
return(WRITE_CMD25_ERROR); //命令写入失败
}
}while(r!=0);
while(0XFF!=SD1_SPI_RByte()); //等待SD卡准备好,再向其发送命令及后续的数据
for(j=0;j<nsec;j++)
{
SD1_SPI_WByte(0xFC);//写入开始字节 0xfc,后面就是要写入的512个字节的数据
for(i=0;i<4;i++) //将缓冲区中要写入的512个字节写入SD卡
{
for(m=0;m<32*4;m++) //将缓冲区中要写入的512个字节写入SD卡
{
SD1_SPI_WByte(*(buffer+m));
}
/***
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));SD1_SPI_WByte(*(buffer++));
**/
}
SD1_SPI_WByte(0xFF);
SD1_SPI_WByte(0xFF); //两个字节的CRC校验码,不用关心
r=SD1_SPI_RByte(); //读取返回值
if((r & 0x1F)!=0x05) //如果返回值是 XXX00DELAY_TIME1 说明数据已经被SD卡接受了
{
return(WRITE_NBLOCK_ERROR); //写块数据失败
}
while(0xFF!=SD1_SPI_RByte());//等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到自身的FLASH中,需要一个时间)
//忙时,读回来的值为0x00,不忙时,为0xff
}
SD1_SPI_WByte(0xFD);
while(0xFF!=SD1_SPI_RByte());
SET_SD1_CS_PIN(1);//关闭片选
SD1_SPI_WByte(0xFF);//按照SD卡的操作时序在这里补8个时钟
return(0); //返回0,说明写扇区操作成功
}
/****************************************************************************
- addr扇区开始的nsec个扇区的数据
- nsec:
addr:
buffer:
- 0x00
- SD卡初始化成功后SPI速度提上来
****************************************************************************/
UINT8 SD_Read_nSector(UINT32 nsec,UINT32 addr,UINT8 *buffer)
{
UINT8 r,time;
UINT32 i=0,j=0;
UINT8 pCMD18[6]={0x52,0x00,0x00,0x00,0x00,0x01}; //CMD18的字节序列
UINT8 pCMD12[6]={0x1C,0x00,0x00,0x00,0x00,0x01}; //CMD12,强制停止命令
if(!SD1_Addr_Mode) addr<<=9; //sector = sector * 512 将块地址(扇区地址)转为字节地址
pCMD18[1]=addr>>24; //将字节地址写入到CMD17字节序列中
pCMD18[2]=addr>>16;
pCMD18[3]=addr>>8;
pCMD18[4]=addr;
time=0;
do
{
r=SD1_Write_Cmd(pCMD18); //写入CMD18
time++;
if(time==TRY_TIME)
{
return(READ_CMD18_ERROR); //写入CMD18失败
}
}while(r!=0);
for(j=0;j<nsec;j++)
{
while(SD1_SPI_RByte()!= 0xFE); //一直读,当读到0xfe时,说明后面的是512字节的数据了
for(i=0;i<4;i++) //将数据写入到数据缓冲区中
{
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();*(buffer++)=SD1_SPI_RByte();
}
SD1_SPI_RByte();
SD1_SPI_RByte();//读取两个字节的CRC校验码,不用关心它们
}
SD1_Write_Cmd(pCMD12); //写入CMD12命令,停止数据读取
SET_SD1_CS_PIN(1);
SD1_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
return 0;
}
/****************************************************************************
- SD卡的总扇区数SD卡的CSD寄器组计算得到总扇区数
-
- SD卡的总扇区数
-
****************************************************************************/
UINT32 SD1_GetTotalSec(void)
{
UINT8 pCSD[16];
UINT32 Capacity;
UINT8 n,i;
UINT16 csize;
UINT8 pCMD9[6]={0x49,0x00,0x00,0x00,0x00,0x01}; //CMD9
if(SD1_Write_Cmd(pCMD9)!=0) //写入CMD9命令
{
return GET_CSD_ERROR; //获取CSD时产生错误
}
while(SD1_SPI_RByte()!= 0xFE); //一直读,当读到0xfe时,说明后面的是16字节的CSD数据
for(i=0;i<16;i++) pCSD[i]=SD1_SPI_RByte(); //读取CSD数据
SD1_SPI_RByte();
SD1_SPI_RByte(); //读取两个字节的CRC校验码,不用关心它们
SET_SD1_CS_PIN(1);
SD1_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
//如果为SDHC卡,即大容量卡,按照下面方式计算
if((pCSD[0]&0xC0)==0x40) //SD2.0的卡
{
csize=pCSD[9]+(((UINT16)(pCSD[8]))<<8)+1;
Capacity=((UINT32)csize)<<10;//得到扇区数
}
else //SD1.0的卡
{
n=(pCSD[5]&0x0F)+((pCSD[10]&0x80)>>7)+((pCSD[9]&0x03)<<1)+2;
csize=(pCSD[8]>>6)+((UINT16)pCSD[7]<<2)+((UINT16)(pCSD[6]&0x03)<<0x0A)+1;
Capacity=(UINT32)csize<<(n-9);//得到扇区数
}
return Capacity;
}
#endif