STC12C5A60S2 SD卡测试失败
SD卡的初始化是正常的,就是读写操作说什么数据对不上,找了很就也没找到原因,#include "sdx.h"
#include "myfun.h"
#include "iospi.h"
//变量定义
//--------------------------------------------------------------
extern unsigned char Low_or_High; //在IOSPI中定义
unsigned char Addr_Mode=0; //寻址方式,1为块寻址,0为字节寻址
unsigned char SD_Ver=SD_VER_ERR; //SD卡的版本
//---------------------------------------------------------------
/********************************************************************
- 功能描述:SPI切换到高速模式
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:无
- 返回说明:无
********************************************************************/
#define SD_SPI_SPEED_HIGH() Low_or_High=0
/********************************************************************
- 功能描述:SPI切换到低速模式
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:无
- 返回说明:无
********************************************************************/
#define SD_SPI_SPEED_LOW()Low_or_High=1
/********************************************************************
- 功能描述:SPI发送一个字节
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:x是要发送的字节
- 返回说明:读到的SPI返回值
********************************************************************/
#define SD_SPI_WByte(x) IO_SPI_RW_Byte(x)
/******************************************************************
- 功能描述:SPI读取一个字节
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:无
- 返回说明:返回读到的字节
******************************************************************/
#define SD_SPI_RByte() IO_SPI_RW_Byte(0XFF)
/********************************************************************
- 功能描述:SPI接口初始化
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:x是要发送的字节
- 返回说明:0
- 注:SPI接口初始化后,首先工作在低速模式。SD卡在初始化的过程中要求
SPI速度要比较低,原则上不高于400KHZ,经验值为240KHZ。如果发现
SD卡初始化不成功,还可继续降低SPI速度。
********************************************************************/
int SD_SPI_Init(void)
{
unsigned char i=0;
IO_SPI_Init();
SD_SPI_SPEED_LOW();
SET_SD_CS_PIN(1);
for(i=0;i<0x0f;i++) //首先要发送最少74个时钟信号,这是必须的!激活SD卡
{
SD_SPI_WByte(0xff); //120个时钟
}
return 0;
}
/******************************************************************
- 功能描述:向SD卡写命令
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:SD卡的命令是6个字节,pcmd是指向命令字节序列的指针
- 返回说明:命令写入后,SD卡的回应值,调用不成功,将返回0xff
******************************************************************/
unsigned char SD_Write_Cmd(unsigned char *pcmd)
{
unsigned char r=0,time=0;
SET_SD_CS_PIN(1);
SD_SPI_WByte(0xFF); //提高兼容性,如果没有这里,有些SD卡可能不支持
SET_SD_CS_PIN(0);
while(0XFF!=SD_SPI_RByte()); //等待SD卡准备好,再向其发送命令
SD_SPI_WByte(pcmd);
SD_SPI_WByte(pcmd);
SD_SPI_WByte(pcmd);
SD_SPI_WByte(pcmd);
SD_SPI_WByte(pcmd);
SD_SPI_WByte(pcmd);
if(pcmd==0X1C) SD_SPI_RByte(); //如果是停止命令,跳过多余的字节
do
{
r=SD_SPI_RByte();
time++;
}while((r&0X80)&&(time<TRY_TIME));
return r;
}
/******************************************************************
- 功能描述:复位SD卡,用到CMD0,使用SD卡从SD模式切换到SPI模式
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:无
- 返回说明:调用成功,返回0x00,否则返回INIT_CMD0_ERROR (sdx.h中有定义)
- 注:成功之后,SD卡处于IDLE空闲状态,等待进一步的初始化
******************************************************************/
unsigned char SD_Init(void)
{
unsigned char time=0,r=0,i=0;
unsigned char rbuf={0};
unsigned char pCMD0 ={0x40,0x00,0x00,0x00,0x00,0x95}; //CMD0,将SD卡从默认上电后的SD模式切换到SPI模式,使SD卡进入IDLE状态
unsigned char pCMD1 ={0x41,0x00,0x00,0x00,0x00,0x01}; //CMD1,MMC卡使用CMD1命令进行初始化
unsigned char pCMD8 ={0x48,0x00,0x00,0x01,0xAA,0x87}; //CMD8,用于鉴别SD卡的版本,并可从应答得知SD卡的工作电压
unsigned char pCMD16={0x50,0x00,0x00,0x02,0x00,0x01}; //CMD16,设置扇区大小为512字节,此命令用于在初始化完成之后进行试探性的操作,
//如果操作成功,说明初始化确实成功
unsigned char pCMD55={0x77,0x00,0x00,0x00,0x00,0x01}; //CMD55,用于告知SD卡后面是ACMD,即应用层命令 CMD55+ACMD41配合使用
//MMC卡使用CMD1来进行初始化,而SD卡则使用CMD55+ACMD41来进行初始化
unsigned char pACMD41H={0x69,0x40,0x00,0x00,0x00,0x01}; //ACMD41,此命令用于检测SD卡是否初始化完成,MMC卡,不适用此命令,针对2.0的SD卡
unsigned char pACMD41S={0x69,0x00,0x00,0x00,0x00,0x01}; //ACMD41,此命令用于检测SD卡是否初始化完成,MMC卡,不适用此命令,针对1.0的SD卡
unsigned char pCMD58={0x7A,0x00,0x00,0x00,0x00,0x01}; //CMD58,用于鉴别SD2.0到底是SDHC,还是普通的SD卡,二者对扇区地址的寻址方式不同
SD_SPI_Init(); //SPI相关初始化,SPI工作在低速模式
time=0;
do
{
r=SD_Write_Cmd(pCMD0);//写入CMD0
time++;
if(time>=TRY_TIME)
{
return(INIT_CMD0_ERROR);//CMD0写入失败
}
}while(r!=0x01);
if(1==SD_Write_Cmd(pCMD8))//写入CMD8,如果返回值为1,则SD卡版本为2.0
{
rbuf=SD_SPI_RByte(); rbuf=SD_SPI_RByte(); //读取4个字节的R7回应,通过它可知此SD卡是否支持2.7~3.6V的工作电压
rbuf=SD_SPI_RByte(); rbuf=SD_SPI_RByte();
if(rbuf==0X01 && rbuf==0XAA)//SD卡是否支持2.7~3.6V
{
time=0;
do
{
SD_Write_Cmd(pCMD55);//写入CMD55
r=SD_Write_Cmd(pACMD41H);//写入ACMD41,针对SD2.0
time++;
if(time>=TRY_TIME)
{
return(INIT_SDV2_ACMD41_ERROR);//对SD2.0使用ACMD41进行初始化时产生错误
}
}while(r!=0);
if(0==SD_Write_Cmd(pCMD58)) //写入CMD58,开始鉴别SD2.0
{
rbuf=SD_SPI_RByte(); rbuf=SD_SPI_RByte(); //读取4个字节的OCR,其中CCS指明了是SDHC还是普通的SD
rbuf=SD_SPI_RByte(); rbuf=SD_SPI_RByte();
if(rbuf&0x40)
{
SD_Ver=SD_VER_V2HC; //SDHC卡
Addr_Mode=1; //SDHC卡的扇区寻址方式是扇区地址
}
else SD_Ver=SD_VER_V2; //普通的SD卡,2.0的卡包含SDHC和一些普通的卡
}
}
}
else //SD V1.0或MMC
{
//SD卡使用ACMD41进行初始化,而MMC使用CMD1来进行初始化,依此来进一步判断是SD还是MMC
SD_Write_Cmd(pCMD55);//写入CMD55
r=SD_Write_Cmd(pACMD41S);//写入ACMD41,针对SD1.0
if(r<=1) //检查返回值是否正确,如果正确,说明ACMD41命令被接受,即为SD卡
{
SD_Ver=SD_VER_V1; //普通的SD1.0卡,一般来说容量不会超过2G
time=0;
do
{
SD_Write_Cmd(pCMD55);//写入CMD55
r=SD_Write_Cmd(pACMD41S);//写入ACMD41,针对SD1.0
time++;
if(time>=TRY_TIME)
{
return(INIT_SDV1_ACMD41_ERROR);//对SD1.0使用ACMD41进行初始化时产生错误
}
}while(r!=0);
}
else //否则为MMC
{
SD_Ver=SD_VER_MMC; //MMC卡,它不支持ACMD41命令,而是使用CMD1进行初始化
time=0;
do
{
r=SD_Write_Cmd(pCMD1);//写入CMD1
time++;
if(time>=TRY_TIME)
{
return(INIT_CMD1_ERROR);//MMC卡使用CMD1命令进行初始化中产生错误
}
}while(r!=0);
}
}
if(0!=SD_Write_Cmd(pCMD16)) //SD卡的块大小必须为512字节
{
SD_Ver=SD_VER_ERR; //如果不成功,则此卡为无法识别的卡
return INIT_ERROR;
}
SET_SD_CS_PIN(1);
SD_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
SD_SPI_SPEED_HIGH(); //SPI切到高速
return 0;//返回0,说明复位操作成功
}
/****************************************************************************
- 功能描述:将buffer指向的512个字节的数据写入到SD卡的addr扇区中
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:addr:扇区地址
buffer:指向数据缓冲区的指针
- 返回说明:调用成功,返回0x00,否则返回WRITE_BLOCK_ERROR (sd.h中有定义)
- 注:SD卡初始化成功后,读写扇区时,尽量将SPI速度提上来,提高效率
****************************************************************************/
unsigned char SD_Write_Sector(unsigned long addr,unsigned char *buffer) //向SD卡中的指定地址的扇区写入512个字节,使用CMD24(24号命令)
{
unsigned char r,time;
unsigned char i=0;
unsigned char pCMD24[]={0x58,0x00,0x00,0x00,0x00,0xff}; //向SD卡中单个块(512字节,一个扇区)写入数据,用CMD24
if(!Addr_Mode) addr<<=9; //addr = addr * 512 将块地址(扇区地址)转为字节地址
pCMD24=addr>>24; //将字节地址写入到CMD24字节序列中
pCMD24=addr>>16;
pCMD24=addr>>8;
pCMD24=addr;
time=0;
do
{
r=SD_Write_Cmd(pCMD24);
time++;
if(time==TRY_TIME)
{
return(r); //命令写入失败
}
}while(r!=0);
while(0XFF!=SD_SPI_RByte()); //等待SD卡准备好,再向其发送命令及后续的数据
SD_SPI_WByte(0xFE);//写入开始字节 0xfe,后面就是要写入的512个字节的数据
for(i=0;i<4;i++) //将缓冲区中要写入的512个字节写入SD卡,减少循环次数,提高数据写入速度
{
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
}
SD_SPI_WByte(0xFF);
SD_SPI_WByte(0xFF); //两个字节的CRC校验码,不用关心
r=SD_SPI_RByte(); //读取返回值
if((r & 0x1F)!=0x05) //如果返回值是 XXX00101 说明数据已经被SD卡接受了
{
return(WRITE_BLOCK_ERROR); //写块数据失败
}
while(0xFF!=SD_SPI_RByte());//等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到自身的FLASH中,需要一个时间)
//忙时,读回来的值为0x00,不忙时,为0xff
SET_SD_CS_PIN(1);
SD_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
return(0); //返回0,说明写扇区操作成功
}
/****************************************************************************
- 功能描述:读取addr扇区的512个字节到buffer指向的数据缓冲区
- 隶属模块:SD/SDHC模块
- 函数属性:内部
- 参数说明:addr:扇区地址
buffer:指向数据缓冲区的指针
- 返回说明:调用成功,返回0x00,否则返回READ_BLOCK_ERROR (sd.h中有定义)
- 注:SD卡初始化成功后,读写扇区时,尽量将SPI速度提上来,提高效率
****************************************************************************/
unsigned char SD_Read_Sector(unsigned long addr,unsigned char *buffer)//从SD卡的指定扇区中读出512个字节,使用CMD17(17号命令)
{
unsigned char i;
unsigned char time,r;
unsigned char pCMD17[]={0x51,0x00,0x00,0x00,0x00,0x01}; //CMD17的字节序列
if(!Addr_Mode) addr<<=9; //sector = sector * 512 将块地址(扇区地址)转为字节地址
pCMD17=addr>>24; //将字节地址写入到CMD17字节序列中
pCMD17=addr>>16;
pCMD17=addr>>8;
pCMD17=addr;
time=0;
do
{
r=SD_Write_Cmd(pCMD17); //写入CMD17
time++;
if(time==TRY_TIME)
{
return(READ_BLOCK_ERROR); //读块失败
}
}while(r!=0);
while(SD_SPI_RByte()!= 0xFE); //一直读,当读到0xfe时,说明后面的是512字节的数据了
for(i=0;i<4;i++) //将数据写入到数据缓冲区中
{
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
}
SD_SPI_RByte();
SD_SPI_RByte();//读取两个字节的CRC校验码,不用关心它们
SET_SD_CS_PIN(1);
SD_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
return 0;
}
unsigned char SD_Write_nSector(unsigned long nsec,unsigned long addr,unsigned char *buffer)
{
unsigned char r,time;
unsigned long i=0,j=0;
unsigned char pCMD25={0x59,0x00,0x00,0x00,0x00,0x01}; //CMD25用于完成多块连续写
unsigned char pCMD55={0x77,0x00,0x00,0x00,0x00,0x01}; //CMD55,用于告知SD卡后面是ACMD,CMD55+ACMD23
unsigned char pACMD23={0x57,0x00,0x00,0x00,0x00,0x01};//CMD23,多块连续预擦除
if(!Addr_Mode) addr<<=9;
pCMD25=addr>>24;
pCMD25=addr>>16;
pCMD25=addr>>8;
pCMD25=addr;
pACMD23=nsec>>24;
pACMD23=nsec>>16;
pACMD23=nsec>>8;
pACMD23=nsec;
if(SD_Ver!=SD_VER_MMC) //如果不是MMC卡,则首先写入预擦除命令,CMD55+ACMD23,这样后面的连续块写的速度会更快
{
SD_Write_Cmd(pCMD55);
SD_Write_Cmd(pACMD23);
}
time=0;
do
{
r=SD_Write_Cmd(pCMD25);
time++;
if(time==TRY_TIME)
{
return(WRITE_CMD25_ERROR); //命令写入失败
}
}while(r!=0);
while(0XFF!=SD_SPI_RByte()); //等待SD卡准备好,再向其发送命令及后续的数据
for(j=0;j<nsec;j++)
{
SD_SPI_WByte(0xFC);//写入开始字节 0xfc,后面就是要写入的512个字节的数据
for(i=0;i<4;i++) //将缓冲区中要写入的512个字节写入SD卡
{
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));SD_SPI_WByte(*(buffer++));
}
SD_SPI_WByte(0xFF);
SD_SPI_WByte(0xFF); //两个字节的CRC校验码,不用关心
r=SD_SPI_RByte(); //读取返回值
if((r & 0x1F)!=0x05) //如果返回值是 XXX00DELAY_TIME1 说明数据已经被SD卡接受了
{
return(WRITE_NBLOCK_ERROR); //写块数据失败
}
while(0xFF!=SD_SPI_RByte());//等到SD卡不忙(数据被接受以后,SD卡要将这些数据写入到自身的FLASH中,需要一个时间)
//忙时,读回来的值为0x00,不忙时,为0xff
}
SD_SPI_WByte(0xFD);
while(0xFF!=SD_SPI_RByte());
SET_SD_CS_PIN(1);//关闭片选
SD_SPI_WByte(0xFF);//按照SD卡的操作时序在这里补8个时钟
return(0); //返回0,说明写扇区操作成功
}
unsigned char SD_Read_nSector(unsigned long nsec,unsigned long addr,unsigned char *buffer)
{
unsigned char r,time;
unsigned long i=0,j=0;
unsigned char pCMD18={0x52,0x00,0x00,0x00,0x00,0x01}; //CMD18的字节序列
unsigned char pCMD12={0x1C,0x00,0x00,0x00,0x00,0x01}; //CMD12,强制停止命令
if(!Addr_Mode) addr<<=9; //sector = sector * 512 将块地址(扇区地址)转为字节地址
pCMD18=addr>>24; //将字节地址写入到CMD17字节序列中
pCMD18=addr>>16;
pCMD18=addr>>8;
pCMD18=addr;
time=0;
do
{
r=SD_Write_Cmd(pCMD18); //写入CMD18
time++;
if(time==TRY_TIME)
{
return(READ_CMD18_ERROR); //写入CMD18失败
}
}while(r!=0);
for(j=0;j<nsec;j++)
{
while(SD_SPI_RByte()!= 0xFE); //一直读,当读到0xfe时,说明后面的是512字节的数据了
for(i=0;i<4;i++) //将数据写入到数据缓冲区中
{
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();*(buffer++)=SD_SPI_RByte();
}
SD_SPI_RByte();
SD_SPI_RByte();//读取两个字节的CRC校验码,不用关心它们
}
SD_Write_Cmd(pCMD12); //写入CMD12命令,停止数据读取
SET_SD_CS_PIN(1);
SD_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
return 0;
}
unsigned long SD_GetTotalSec(void)
{
unsigned char pCSD;
unsigned long Capacity;
unsigned char n,i;
unsigned short csize;
unsigned char pCMD9={0x49,0x00,0x00,0x00,0x00,0x01}; //CMD9
if(SD_Write_Cmd(pCMD9)!=0) //写入CMD9命令
{
return GET_CSD_ERROR; //获取CSD时产生错误
}
while(SD_SPI_RByte()!= 0xFE); //一直读,当读到0xfe时,说明后面的是16字节的CSD数据
for(i=0;i<16;i++) pCSD=SD_SPI_RByte(); //读取CSD数据
SD_SPI_RByte();
SD_SPI_RByte(); //读取两个字节的CRC校验码,不用关心它们
SET_SD_CS_PIN(1);
SD_SPI_WByte(0xFF); //按照SD卡的操作时序在这里补8个时钟
//如果为SDHC卡,即大容量卡,按照下面方式计算
if((pCSD&0xC0)==0x40) //SD2.0的卡
{
csize=pCSD+(((unsigned short)(pCSD))<<8)+1;
Capacity=((unsigned long)csize)<<10;//得到扇区数
}
else //SD1.0的卡
{
n=(pCSD&0x0F)+((pCSD&0x80)>>7)+((pCSD&0x03)<<1)+2;
csize=(pCSD>>6)+((unsigned short)pCSD<<2)+((unsigned short)(pCSD&0x03)<<0x0A)+1;
Capacity=(unsigned long)csize<<(n-9);//得到扇区数
}
return Capacity;
}
3.3V和5V处理好了吗 你还是编辑一下,用代码形式插入,这样能看到几行几行。
我前几天用这相似的代码读取SD卡,1G,8G SDHC都试过没问题,还移植了FATFS,和U盘,不过我用的是STM32.
你看看 一些指令等待时间 循环次数够不够,我试过几张卡,有些次数要多很多。 68336016 发表于 2013-8-20 00:49 static/image/common/back.gif
你还是编辑一下,用代码形式插入,这样能看到几行几行。
我前几天用这相似的代码读取SD卡,1G,8G SDHC都试 ...
STM32我试过的,可以用,就是fat没仔细玩过,现在转这款单片机就不行了,所以郁闷啊
页:
[1]