晓毕8 发表于 2013-8-19 11:04:32

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;
}

ttb2008 发表于 2013-8-20 00:39:21

3.3V和5V处理好了吗

68336016 发表于 2013-8-20 00:49:16

你还是编辑一下,用代码形式插入,这样能看到几行几行。
我前几天用这相似的代码读取SD卡,1G,8G SDHC都试过没问题,还移植了FATFS,和U盘,不过我用的是STM32.

你看看 一些指令等待时间 循环次数够不够,我试过几张卡,有些次数要多很多。

晓毕8 发表于 2013-8-20 22:16:52

68336016 发表于 2013-8-20 00:49 static/image/common/back.gif
你还是编辑一下,用代码形式插入,这样能看到几行几行。
我前几天用这相似的代码读取SD卡,1G,8G SDHC都试 ...

STM32我试过的,可以用,就是fat没仔细玩过,现在转这款单片机就不行了,所以郁闷啊
页: [1]
查看完整版本: STC12C5A60S2 SD卡测试失败