求帮看代码,SPI驱动SD卡,调了两天了。。

2019-07-20 18:39发布

    找了很多F4的例程,都是SDIO驱动SD卡的,手上这块板又做成了SPI驱动的,找到战舰107的SPI驱动SD卡例程,移植过来,却不成功,不知道哪错了,感觉片选这部分有问题,自己试着改了,还是不行。。求帮忙看看代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
13条回答
JAMES
1楼-- · 2019-07-20 23:00
已搞定
JAMES
2楼-- · 2019-07-21 01:18
调了两天了,烦死了,求大神支援啊~~
JAMES
3楼-- · 2019-07-21 02:30
 精彩回答 2  元偷偷看……
mygod
4楼-- · 2019-07-21 05:28
要想有进步就自己调试出来,动不动找这个源码找那个代码,你自己问题根源没找到。下次还来做这个,你还是要蒙。
先从硬件上排除,这个简单就不说了。
然后再软件上,把连接SD的 IO都同时拉高,拉低,看有没动作,然后继续 调试,设置断点,看看哪个地方错误。
yyx112358
5楼-- · 2019-07-21 10:41
 精彩回答 2  元偷偷看……
yyx112358
6楼-- · 2019-07-21 15:44
C源文件[mw_shl_code=c,true]#include "sys.h"
#include "spi.h"
#include "mmc_sd.h"                          

#include "usart.h"       
                                                                             
u8  SD_Type=0;//SD卡的类型
static u32 CSD_Tab[4],CID_Tab[4];                                        //SD卡CSD,CID以及相对地址(RCA)数据
SD_CardInfo SDCardInfo;                                                                        //SD卡信息
//static DMA_InitTypeDef SD_DMAInitStructure;
////////////////////////////////////移植修改区///////////////////////////////////
//移植时候的接口
//data:要写入的数据
//返回值:读到的数据
u8 SD_SPI_ReadWriteByte(u8 data)
{
        return SPI5_ReadWriteByte(data);
}          
//SD卡初始化的时候,需要低速
void SD_SPI_SpeedLow(void)
{
        SPI5_SetSpeed(SPI_BaudRatePrescaler_256);
}
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{
        SPI5_SetSpeed(SPI_BaudRatePrescaler_4);//【如果出现错误应改为16分频】
}
//SPI硬件层初始化
void SD_SPI_Init(void)
{
          GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOA时钟

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOF, &GPIO_InitStructure);
        SD_CS=1;

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_Init(GPIOC, &GPIO_InitStructure);
        L3GD20_CS=1;//其件片选引脚置为高以免影响
       
        SPI5_Init();
}

u8 SD_Deinit(void)
{
        SPI_DeInit(SPI5);
        return 1;
}

u32 SD_UserCallBack(void)
{
        SD_Deinit();
       
        return SD_Init();
}
///////////////////////////////////////////////////////////////////////////////////
//取消选择,释放SPI总线
void SD_DisSelect(void)
{
        SD_CS=1;
        SD_SPI_ReadWriteByte(DUMMYBYTE);//提供额外的8个时钟
}
//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SD_Select(void)
{
        SD_CS=0;
        if(SD_WaitReady()==0)return 0;//等待成功
        SD_DisSelect();
        return 1;//等待失败
}
//等待卡准备好
//返回值:0,准备好了;其他,错误代码
u8 SD_WaitReady(void)
{
        u32 t=0;
        do
        {
                if(SD_SPI_ReadWriteByte(0XFF)==0XFF)return 0;//OK
                t++;                         
        }while(t<0XFFFFF);//等待
        return SD_UserCallBack();
}
//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
//    其他,得到回应值失败
u8 SD_GetResponse(u8 Response)
{
        u16 Count=0x1000  ;//等待次数                                                             
        while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应            
        if (Count==0)return SD_RESPONSE_FAILURE;//得到回应失败   
        else return SD_RESPONSE_NO_ERROR;//正确回应
}
//向SD卡发送一个命令
//输入: u8 cmd   命令
//      u32 arg  命令参数
//      u8 crc   crc校验值          
//返回值:SD卡返回的响应                                                                                                                          
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{
  u8 r1;       
        u8 Retry=0;
#if SD_SPI_USE_CRC///SD卡SPI模式下是否使用CRC
        //SPI模式下,一般只需要初始化时用于进入SPI模式的CMD0需要CRC,除非使用CMD59打开SPI的CRC
        do
        {
                SD_DisSelect();//取消上次片选
                if(SD_Select())return SD_RESPONSE_FAILURE;//片选失效
                //发送
                        SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
                        SD_SPI_ReadWriteByte(arg >> 24);
                        SD_SPI_ReadWriteByte(arg >> 16);
                        SD_SPI_ReadWriteByte(arg >> 8);
                        SD_SPI_ReadWriteByte(arg);          
                        SD_SPI_ReadWriteByte(crc);
                if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
                        //等待响应,或超时退出
                Retry=0X1F;
                do
                {
                        r1=SD_SPI_ReadWriteByte(0xFF);
                }while((r1&0X80) && Retry--);         
                crc++;
        }while(r1&SD_COM_CRC_ERROR);
        #if        MY_DEBUG
        printf("cmd:%d,arg:%x,crc:%x ",cmd,arg,crc-1);
        #endif
#else //不使用CRC
        SD_DisSelect();//取消上次片选
        if(SD_Select())return SD_RESPONSE_FAILURE;//片选失效
        //发送
                SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令
                SD_SPI_ReadWriteByte(arg >> 24);
                SD_SPI_ReadWriteByte(arg >> 16);
                SD_SPI_ReadWriteByte(arg >> 8);
                SD_SPI_ReadWriteByte(arg);          
                SD_SPI_ReadWriteByte(crc);
        if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
                //等待响应,或超时退出
        Retry=0X1F;
        do
        {
                r1=SD_SPI_ReadWriteByte(0xFF);
        }while((r1&0X80) && Retry--);         
#endif
        //返回状态值
  return r1;
}
//初始化SD卡
u8 SD_Initialize(void)
{
  u8 r1;      // 存放SD卡的返回值
  u16 retry;  // 用来进行超时计数
  u8 buf[4];  
        u16 i;

        SD_SPI_Init();                //初始化IO
        SD_SPI_SpeedLow();        //设置到低速模式
        for(i=0;i<10;i++)
                SD_SPI_ReadWriteByte(0XFF);//发送最少74个脉冲
       
        retry=20;
        do
        {
                r1=SD_SendCmd(CMD0,0,0x95);////低电平时发送CMD0进入SPI模式
        }while((r1!=SD_IN_IDLE_STATE) && retry--);
        SD_Type=0;//默认无卡
       
        if(r1!=SD_ILLEGAL_COMMAND)//R1未返回非法命令,说明支持SD2.0标准
        {
                if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
                {
                        for(i=0;i<4;i++)
                                buf=SD_SPI_ReadWriteByte(0XFF);        //Get trailing return value of R7 resp
                       
                        if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
                        {
                                retry=0XFFFE;
                                do
                                {
                                        SD_SendCmd(CMD55,0,0X64);        //发送CMD55
                                        r1=SD_SendCmd(CMD41,0x40000000,0X77);//发送CMD41
                                }while(r1&&retry--);
                                if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
                                {
                                        for(i=0;i<4;i++)buf=SD_SPI_ReadWriteByte(0XFF);//得到OCR值
                                        if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC;    //检查CCS
                                        else SD_Type=SD_TYPE_V2;   
                                }
                        }
                }
                else//SD V1.x/ MMC        V3
                {
                        SD_SendCmd(CMD55,0,0X64);                //发送CMD55
                        r1=SD_SendCmd(CMD55,0,0X77);        //发送CMD41
                        if(r1<=1)
                        {               
                                SD_Type=SD_TYPE_V1;
                                retry=0XFFFE;
                                do //等待退出IDLE模式
                                {
                                        SD_SendCmd(CMD55,0,0X64);        //发送CMD55
                                        r1=SD_SendCmd(CMD55,0,0X77);//发送CMD41
                                }while(r1&&retry--);
                        }else
                        {
                                SD_Type=SD_TYPE_MMC;//MMC V3
                                retry=0X1000;
                                do //等待退出IDLE模式
                                {                                                                                            
                                        r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
                                }while(r1&&retry--);  
                        }
                        if(retry==-1||SD_SendCmd(CMD16,512,0X14)!=0)SD_Type=SD_TYPE_ERR;//错误的卡
                }
                r1=SD_SendCmd(CMD59,0,0x95);
        }
        SD_DisSelect();//取消片选
        SD_SPI_SpeedHigh();//高速
        if(SD_Type)return SD_RESPONSE_NO_ERROR;
        else if(r1)return r1;
       
        return 0xaa;//其他错误
}
u8 SD_Init(void)
{
        u8 r1=SD_RESPONSE_NO_ERROR;
       
        SD_Deinit();
        SD_SPI_Init();
        r1=SD_Initialize();
        if(r1!=SD_RESPONSE_NO_ERROR)
                return r1;
       
        r1=SD_GetCID(CID_Tab);
        if(r1!=SD_RESPONSE_NO_ERROR)
                return r1;
       
        r1=SD_GetCSD(CSD_Tab);
        if(r1!=SD_RESPONSE_NO_ERROR)
                return r1;
       
        SD_GetCardInfo(&SDCardInfo);
        return SD_RESPONSE_NO_ERROR;
}

//从sd卡读取一个数据包的内容
//buf:数据缓存区
//len:要读取的数据长度.
//返回值:0,成功;其他,失败;       
u8 SD_RecvData(u8 buf[],u16 len)
{                                    
        if(SD_GetResponse(0xFE))return SD_RESPONSE_FAILURE;//等待SD卡发回数据起始令牌0xFE
       
  while(len--)//开始接收数据
        {
                        *buf=SPI5_ReadWriteByte(DUMMYBYTE);
                        buf++;
        }
        //下面是2个伪CRC(dummy CRC)
        SD_SPI_ReadWriteByte(DUMMYBYTE);
        SD_SPI_ReadWriteByte(DUMMYBYTE);                                                                                                                      
        return 0;//读取成功
}
//向sd卡写入一个数据包的内容 512字节
//buf:数据缓存区
//cmd:指令
//返回值:0,成功;其他,失败;       
u8 SD_SendBlock(u8*buf,u8 cmd)
{       
        u16 t;                            
        if(SD_WaitReady())
                return SD_RESPONSE_FAILURE;//等待准备失效
       
        SD_SPI_ReadWriteByte(cmd);
        if(cmd!=0XFD)//不是结束指令
        {
                for(t=0;t<512;t++)SPI5_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
               
          SD_SPI_ReadWriteByte(DUMMYBYTE);//忽略crc
          SD_SPI_ReadWriteByte(DUMMYBYTE);
                t=SD_SPI_ReadWriteByte(DUMMYBYTE);//接收响应
                if((t&0x1F)!=0x05)return 2;//响应错误                                                                                                                      
        }                                                                                                                                                                       
  return 0;//写入成功
}

                                                                                                                                                                              
//获取SD卡的CID信息,包括制造商信息
//输入: u8 *cid_data(存放CID的内存,至少16Byte)          
//返回值:0:NO_ERR
//                 1:错误                                                                                                                  
u8 SD_GetCID(u32 *cid_data)
{
  u8 r1,temp[16],i=0;          
    //发CMD10命令,读CID
  r1=SD_SendCmd(CMD10,0,0x01);
  if(r1==0||r1==SD_COM_CRC_ERROR)
        {
                r1=SD_RecvData(temp,16);//接收16个字节的数据
  }
        for(i=0;i<4;i++)//小端模式转化为大端
        {
                cid_data=(temp[4*i]<<24)+(temp[4*i+1]<<16)+(temp[4*i+2]<<8)+(temp[4*i+3]);
        }
       
        SD_DisSelect();//取消片选
        if(r1)return r1;
        else return 0;
}                                                                                                                                                                  
//获取SD卡的CSD信息,包括容量和速度信息
//输入:u8 *cid_data(存放CID的内存,至少16Byte)            
//返回值:0:NO_ERR
//                 1:错误                                                                                                                  
u8 SD_GetCSD(u32 *csd_data)
{
  u8 r1,temp[16],i=0;         
       
  r1=SD_SendCmd(CMD9,0,0xAF);//发CMD9命令,读CSD
  if(r1==0||r1==SD_COM_CRC_ERROR)
        {
            r1=SD_RecvData(temp, 16);//接收16个字节的数据
  }
        for(i=0;i<4;i++)//小端模式转化为大端
        {
                csd_data=(temp[4*i]<<24)+(temp[4*i+1]<<16)+(temp[4*i+2]<<8)+(temp[4*i+3]);
        }
        SD_DisSelect();//取消片选
        if(r1)return r1;
        else return 0;
}  
////获取SD卡的总扇区数(扇区数)   
////返回值:0: 取容量出错
////       其他:SD卡的容量(扇区数/512字节)
////每扇区的字节数必为512,因为如果不是512,则初始化不能通过.                                                                                                                  
//u32 SD_GetSectorCount(void)
//{
//        u8 csd[16];
//        u32 Capacity;  
//        u8 n;
//        u16 csize;                                              
//        //取CSD信息,如果期间出错,返回0
//        if(SD_GetCSD(csd)!=0) return 0;            
//        //如果为SDHC卡,按照下面方式计算
//        if((csd[0]&0xC0)==0x40)         //V2.00的卡
//        {       
//                csize = csd[9] + ((u16)csd[8] << 8) + 1;
//                Capacity = (u32)csize << 10;//得到扇区数                           
//        }
//        else//V1.XX的卡
//        {       
//                n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
//                csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;
//                Capacity= (u32)csize << (n - 9);//得到扇区数   
//        }
//        return Capacity;
//}
//得到卡信息
//cardinfo:卡信息存储区
//返回值:错误状态
SD_ERRSTATE SD_GetCardInfo(SD_CardInfo *cardinfo)//这个函数是按照
{
        SD_ERRSTATE errorstatus=SD_RESPONSE_NO_ERROR;
        u8 tmp=0;          
        cardinfo->CardType=(u8)SD_Type;                                 //卡类型
        cardinfo->RCA=(u16)0x01;                                                        //卡RCA值
        tmp=(u8)((CSD_Tab[0]&0xFF000000)>>24);
        cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6;                //CSD结构
        cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2;        //2.0协议还没定义这部分(为保留),应该是后续协议定义的
        cardinfo->SD_csd.Reserved1=tmp&0x03;                        //2个保留位  
        tmp=(u8)((CSD_Tab[0]&0x00FF0000)>>16);                        //第1个字节
        cardinfo->SD_csd.TAAC=tmp;                                                   //数据读时间1
        tmp=(u8)((CSD_Tab[0]&0x0000FF00)>>8);                          //第2个字节
        cardinfo->SD_csd.NSAC=tmp;                                                  //数据读时间2
        tmp=(u8)(CSD_Tab[0]&0x000000FF);                                //第3个字节
        cardinfo->SD_csd.MaxBusClkFrec=tmp;                                  //传输速度          
        tmp=(u8)((CSD_Tab[1]&0xFF000000)>>24);                        //第4个字节
        cardinfo->SD_csd.CardComdClasses=tmp<<4;            //卡指令类高四位
        tmp=(u8)((CSD_Tab[1]&0x00FF0000)>>16);                         //第5个字节
        cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;//卡指令类低四位
        cardinfo->SD_csd.RdBlockLen=tmp&0x0F;                    //最大读取数据长度
        tmp=(u8)((CSD_Tab[1]&0x0000FF00)>>8);                        //第6个字节
        cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7;        //允许分块读
        cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6;        //写块错位
        cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5;        //读块错位
        cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
        cardinfo->SD_csd.Reserved2=0;                                         //保留
        if((cardinfo->CardType==SD_TYPE_V1)||(cardinfo->CardType==SD_TYPE_V2)||(cardinfo->CardType==SD_TYPE_MMC))//标准1.1/2.0卡/MMC卡
        {
                cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10;        //C_SIZE(12位)
                 tmp=(u8)(CSD_Tab[1]&0x000000FF);                         //第7个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
                tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);                //第8个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
                cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
                cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
                tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);                //第9个字节       
                cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
                cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
                cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;//C_SIZE_MULT
                tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);                  //第10个字节       
                cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
                cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);//计算卡容量
                cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
                cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);//块大小
                cardinfo->CardCapacity*=cardinfo->CardBlockSize;
        }
        else if(cardinfo->CardType==SD_TYPE_V2HC)        //高容量卡
        {
                tmp=(u8)(CSD_Tab[1]&0x000000FF);                 //第7个字节       
                cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
                tmp=(u8)((CSD_Tab[2]&0xFF000000)>>24);         //第8个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp<<8);
                tmp=(u8)((CSD_Tab[2]&0x00FF0000)>>16);        //第9个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp);
                tmp=(u8)((CSD_Tab[2]&0x0000FF00)>>8);         //第10个字节       
                cardinfo->CardCapacity=(long long)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
                cardinfo->CardBlockSize=512;                         //块大小固定为512字节
        }          
        cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
        cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;          
        tmp=(u8)(CSD_Tab[2]&0x000000FF);                        //第11个字节       
        cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
        cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
        tmp=(u8)((CSD_Tab[3]&0xFF000000)>>24);                //第12个字节       
        cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
        cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
        cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
        cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;         
        tmp=(u8)((CSD_Tab[3]&0x00FF0000)>>16);                //第13个字节
        cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
        cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
        cardinfo->SD_csd.Reserved3=0;
        cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);  
        tmp=(u8)((CSD_Tab[3]&0x0000FF00)>>8);                //第14个字节
        cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
        cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
        cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
        cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
        cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
        cardinfo->SD_csd.ECC=(tmp&0x03);  
        tmp=(u8)(CSD_Tab[3]&0x000000FF);                        //第15个字节
        cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
        cardinfo->SD_csd.Reserved4=1;                 
        tmp=(u8)((CID_Tab[0]&0xFF000000)>>24);                //第0个字节
        cardinfo->SD_cid.ManufacturerID=tmp;                    
        tmp=(u8)((CID_Tab[0]&0x00FF0000)>>16);                //第1个字节
        cardinfo->SD_cid.OEM_AppliID=tmp<<8;          
        tmp=(u8)((CID_Tab[0]&0x000000FF00)>>8);                //第2个字节
        cardinfo->SD_cid.OEM_AppliID|=tmp;            
        tmp=(u8)(CID_Tab[0]&0x000000FF);                        //第3个字节       
        cardinfo->SD_cid.ProdName1=tmp<<24;                                  
        tmp=(u8)((CID_Tab[1]&0xFF000000)>>24);                 //第4个字节
        cardinfo->SD_cid.ProdName1|=tmp<<16;          
        tmp=(u8)((CID_Tab[1]&0x00FF0000)>>16);                   //第5个字节
        cardinfo->SD_cid.ProdName1|=tmp<<8;                 
        tmp=(u8)((CID_Tab[1]&0x0000FF00)>>8);                //第6个字节
        cardinfo->SD_cid.ProdName1|=tmp;                  
        tmp=(u8)(CID_Tab[1]&0x000000FF);                          //第7个字节
        cardinfo->SD_cid.ProdName2=tmp;                          
        tmp=(u8)((CID_Tab[2]&0xFF000000)>>24);                 //第8个字节
        cardinfo->SD_cid.ProdRev=tmp;                 
        tmp=(u8)((CID_Tab[2]&0x00FF0000)>>16);                //第9个字节
        cardinfo->SD_cid.ProdSN=tmp<<24;          
        tmp=(u8)((CID_Tab[2]&0x0000FF00)>>8);                 //第10个字节
        cardinfo->SD_cid.ProdSN|=tmp<<16;          
        tmp=(u8)(CID_Tab[2]&0x000000FF);                           //第11个字节
        cardinfo->SD_cid.ProdSN|=tmp<<8;                  
        tmp=(u8)((CID_Tab[3]&0xFF000000)>>24);                 //第12个字节
        cardinfo->SD_cid.ProdSN|=tmp;                             
        tmp=(u8)((CID_Tab[3]&0x00FF0000)>>16);                 //第13个字节
        cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
        cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;   
        tmp=(u8)((CID_Tab[3]&0x0000FF00)>>8);                //第14个字节
        cardinfo->SD_cid.ManufactDate|=tmp;                           
        tmp=(u8)(CID_Tab[3]&0x000000FF);                        //第15个字节
        cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
        cardinfo->SD_cid.Reserved2=1;         
        return errorstatus;
}
//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
//SPI无DMA下                多块读:约1047K/S                单块读:约623K/S
u8 SD_ReadDisk(u8*buf,u32 sector,u32 cnt)
{
        u8 r1;
        if((sector+cnt)>(SDCardInfo.SD_csd.DeviceSize+1)*1024)        return SD_PARAMETER_ERROR;//超出最大扇区数
        if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址(每扇区512B)
       
        if(cnt==1)
        {
                r1=SD_SendCmd(CMD17,sector,0X01);//读命令
                if(r1==0||r1==SD_COM_CRC_ERROR)//指令发送成功【由于未进行CRC计算,故R1可能为SD_COM_CRC_ERROR】
                {
                        r1=SD_RecvData(buf,512);//接收512个字节          
                }
        }
        else
        {
                r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令
                do
                {
                        r1=SD_RecvData(buf,512);//接收512个字节         
                        buf+=512;
                }while(--cnt && (r1==0||r1==SD_COM_CRC_ERROR));        
                SD_SendCmd(CMD12,0,0X60);        //发送停止命令
        }
        SD_DisSelect();//取消片选
        return r1;//
}
//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u32 cnt)
{
        u8 r1;
        if(buf==NULL)        return SD_PARAMETER_ERROR;//空指针
        if((sector+cnt)>(SDCardInfo.SD_csd.DeviceSize+1)*1024)        return SD_PARAMETER_ERROR;//超出最大扇区数
       
        if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
        if(cnt==1)
        {
                r1=SD_SendCmd(CMD24,sector,0X01);//写命令
                if(r1==0||r1==SD_COM_CRC_ERROR)//指令发送成功【由于未进行CRC计算,故R1可能为SD_COM_CRC_ERROR】
                {
                        r1=SD_SendBlock(buf,0xFE);//写512个字节          
                }
        }else
        {
                if(SD_Type!=SD_TYPE_MMC)
                {
                        SD_SendCmd(CMD55,0,0X64);       
                        SD_SendCmd(CMD23,cnt,0X01);//发送指令       
                }
                r1=SD_SendCmd(CMD25,sector,0X01);//连续写命令
                if(r1==0||r1==SD_COM_CRC_ERROR)
                {
                        do
                        {
                                r1=SD_SendBlock(buf,0xFC);//接收512个字节         
                                buf+=512;  
                        }while(--cnt && (r1==0||r1==SD_COM_CRC_ERROR));
                        r1=SD_SendBlock(0,0xFD);//接收512个字节
                }
        }   
        SD_DisSelect();//取消片选
        return r1;//
}          
//擦除指定区间的块
//写之前预先擦除会加快写SD卡速度
u8 SD_EraseDisk(u32 startsector,u32 endsector)
{
        u8 r1;
        if(SD_Type!=SD_TYPE_V2HC)
        {
                startsector <<= 9;//转换为字节地址(每扇区512B)
                endsector                <<=9;
        }
       
        r1=SD_SendCmd(CMD32,startsector,0x01);
        if(r1!=0&&r1!=SD_COM_CRC_ERROR)
                return r1;
       
        r1=SD_SendCmd(CMD33,endsector,0x01);
        if(r1!=0&&r1!=SD_COM_CRC_ERROR)
                return r1;
       
        r1=SD_SendCmd(CMD33,endsector,0x01);
        if(r1!=0&&r1!=SD_COM_CRC_ERROR)
                return r1;
       
        return r1;
}


[/mw_shl_code]

一周热门 更多>