搜索
bottom↓
回复: 5

凌阳61读写SD卡程序,

[复制链接]

出0入0汤圆

发表于 2009-7-17 11:49:27 | 显示全部楼层 |阅读模式
今天有点小高兴,SD卡终于可以读写了,但是读写的速度慢的可怜。代码在下面,高手看下主要的原因,告诉下吧。
//#ifdef  _SDDRIVE_H
//#define _SDDRIVE_H
//
#include "SPCE061A.H"
#define uchar unsigned char
#define uint  unsigned int


#define CMD0        (0x40|0)        /* GO_IDLE_STATE */
#define CMD1        (0x40|1)        /* SEND_OP_COND */
#define ACMD41        (0xC0|41)        /* SEND_OP_COND */
#define CMD8        (0x40|8)        /* SEND_IF_COND */
#define CMD9        (0x40|9)        /* SEND_CSD */
#define CMD10        (0x40|10)        /* SEND_CID */
#define CMD12        (0x40|12)        /* STOP_TRANSMISSION */
#define ACMD13        (0xC0|13)        /* SD_STATUS */
#define CMD16        (0x40|16)        /* SET_BLOCKLEN */
#define CMD17        (0x40|17)        /* READ_SINGLE_BLOCK */
#define CMD18        (0x40|18)        /* READ_MULTIPLE_BLOCK */
#define ACMD23        (0xC0|23)        /* SET_WR_BLK_ERASE_COUNT */
#define CMD24        (0x40|24)        /* WRITE_BLOCK */
#define CMD25        (0x40|25)        /* WRITE_MULTIPLE_BLOCK */
#define CMD32        (0x40|32)        /* ERASE_BLOCK_START_ADDR */
#define CMD33        (0x40|33)        /* ERASE_BLOCK_END_ADDR */
#define CMD38        (0x40|38)        /* ERASE_SELECTED_BLOCKS */
#define CMD55        (0x40|55)        /* APP_CMD */
#define CMD58        (0x40|58)        /* READ_OCR */
#define SingleBlock  1
#define MuiltiBlock  0


#define CS_High()   (*P_IOB_Data|=0x0800)
#define CS_Low()    (*P_IOB_Data&=0xf7ff)
#define CLK_High()  (*P_IOB_Data|=0x0100)
#define CLK_Low()   (*P_IOB_Data&=0xfeff)
#define DO_High()   (*P_IOB_Data|=0x4000)
#define DO_Low()    (*P_IOB_Data&=0xbfff)
//#define DI_High()   (*P_IOB_Data|=0x0200)
//#define DI_Low()    (*P_IOB_Data&=0xfdff)

void SD_IOInit(void)
{
*P_IOB_Attrib=0xFD00;
*P_IOB_Dir=0xff00;
*P_IOB_Data=0xff00;
}

void Delayus(unsigned int n)
{
while(n--)
{ *P_Watchdog_Clear=0x0001;}
}

void SPI_Send(uchar d)
{
  uchar i;
  for(i=0;i<8;i++)
  {
          if(d&0x0080)
                  DO_High();
          else
              DO_Low();
          CLK_Low();
    Delayus(1);
          CLK_High();  
           Delayus(1);  
          d<<=1;      //先传高位
  }
  DO_High();//不使用时将输出线置1
}

uchar SPI_Receive(void)
{
uchar d,i;
for(i=0;i<8;i++)
{
        CLK_Low();
        Delayus(1);
        CLK_High();
        Delayus(1);
        d<<=1;   //先接高位
        if(*P_IOB_Data&0x0200)
                d++;
}
return (d&0x00ff);
}  

uchar SD_CMDWrite(uchar CMDx,unsigned long CMDArg)
{
uchar res=0xff; uchar retry=0; uchar  CRC=0xff;
if(CMDx==0x40) CRC=0x95;

CS_High();
SPI_Send(0xff);//8个时钟脉冲
CS_Low();
SPI_Send(CMDx);//发送命令索引,前两位是01
SPI_Send(CMDArg>>24);
SPI_Send(CMDArg>>16);
SPI_Send(CMDArg>>8);
SPI_Send(CMDArg);
SPI_Send(CRC);
//SPI_Send(0x40);
//SPI_Send(00);
//SPI_Send(00);
//SPI_Send(00);
//SPI_Send(00);
//SPI_Send(0x95);       

SPI_Send(0xff);   //8个附加时钟

do{
//        res=SPI_Receive();  //读前8位
    res=SPI_Receive(); //读取SD回应(后8位)
    retry++;
    *P_Watchdog_Clear=0x0001;
    if(retry>100)
              break;   // 超时
   } while((res&0xff)==0xff);           
CS_High();
SPI_Send(0xff); //附加8个额外时钟  
return (res);       
}

uchar SD_Init(void)
{
uchar res=0xff; uchar i,retry=0;
//SD_IOInit();   //管脚初始化
CS_High();
*P_SystemClock=0x06;//375KHZ
Delayus(200);
for(i=0;i<0x0f;i++) //发送多于74个时钟
        SPI_Send(0xff);
do{
        res=SD_CMDWrite(CMD0,0);//复位
        retry++;
        *P_Watchdog_Clear=0x0001;
        if(retry>0x100)
                break;
   }while((res&0x00ff)!=0x01);
retry=0;
do{
        res=SD_CMDWrite(CMD1,0);//激活SD卡
        res=SD_CMDWrite(CMD1,0);//激活SD卡
  //  res=SD_CMDWrite(CMD55,0);
  //  res=SD_CMDWrite(ACMD41,0);
        retry++;
    *P_Watchdog_Clear=0x0001;
    if(retry>0x100)
            break;
   }while((res&0x00ff)!=0);
   
    *P_SystemClock=0x0080;
   return res;
}

uchar SD_WriteBlcok(uchar S_M,uchar len,uchar *buffer)
{
uchar i;
uchar res=0xff;
uchar retry=0;
CS_Low();
SPI_Send(0xff);  //开始发送数据之前发送8个时钟脉冲
if(S_M==SingleBlock)//写单块
        SPI_Send(0xfe);  //发送写单块令牌
else
    SPI_Send(0xfc); // 发送写多块令牌
  for(i=0;i<len;i++)
  {
    SPI_Send(*buffer++);   // 开始写数据
  }
  SPI_Send(0xff);  //发送2个字节CRC
  SPI_Send(0xff);
  res=SPI_Receive();//接收回应
  if((res&0x05)!=0x05)        //res= 0bXXX0AAA1 ; AAA='010' - data accepted,AAA='101'-data rejected due to CRC error*/
         {                 //AAA='110'-data rejected due to write error*/
            SPI_Send(0xff); //发送8个时钟脉冲
             CS_High();  
             *P_Watchdog_Clear=0x0001;   
                return 0xff;
     }   
  //CS_High();
  do{
     res=SPI_Receive();                      
        if(retry++>0xfffe)
        {
                CS_High();  //等待SD卡忙完
                return 0xff;
        }
     }while(res!=0xff);
    retry=0;   
   CS_High();
   SPI_Send(0xff);//额外的8个时钟         
   return  0;
  }
uchar SD_ReadBlock(uchar len, uchar *buffer)
{
  uchar i;
uchar res=0xff;
uchar retry=0;
CS_Low();
  do{   
              res=SPI_Receive();         //接收令牌  
             *P_Watchdog_Clear=0x0001;
             if(retry++>0xfffe)
                     return 0xff;
     }while(res!=0xfe);
            
     for(i=0;i<len;i++)
       *buffer++=SPI_Receive();//接收512字节数据
      
     SPI_Receive();//接收2字节CRC
     SPI_Receive();
     SPI_Send(0xff);
     CS_High();
     return 0;
}  
  
uchar SD_WriteSingleBlock(unsigned long int BlockAddr,uchar *buffer)
{
uchar res=0xff;
uchar retry=0;
do{
        res=SD_CMDWrite(CMD24,(BlockAddr<<9));
        retry++;
        *P_Watchdog_Clear=0x0001;
        if(retry>100)
                return 0xff; //超时,返回错误  
    }while(res!=0x00);
   
   res=SD_WriteBlcok(SingleBlock,512,buffer);
   return  res;
}

uchar SD_ReadSingleBlock(unsigned long int BlockAddr , uchar *buffer)
{
uchar res=0xff;
uchar retry=0;

do{
        res=SD_CMDWrite(CMD17,(BlockAddr<<9));
        retry++;
        if(retry>100)
                return 0xff;
   }while(res!=0x00);
  res=SD_ReadBlock(512,buffer);
  return res;      
}

uchar SD_Erase(unsigned long int StartBlock,unsigned long int EndBlock)
{
uchar res=0xff;
uchar retry=0;
do{
    res=SD_CMDWrite(CMD32,StartBlock<<9);//发送擦除开始块
    if(retry++>100)
            return 0xff;
   }while(res!=0) ;
   
do{
    res=SD_CMDWrite(CMD33,EndBlock<<9);//发送擦除结束快
    if(retry++>100)
            return 0xff;
   }while(res!=0) ;
          
  do{
    res=SD_CMDWrite(CMD32,0);//发送擦除命令
    if(retry++>100)
            return 0xff;
   }while(res!=0) ;
   
   return 0;
}










int main(void)
{
char resp=0xff;
uchar i;
uchar buffer1[512];
uchar buffer2[512];
  *P_SystemClock=0x0080; //49M
  *P_DAC_Ctrl=C_DAC1_DIRECT;//直接所存
  SD_IOInit();   //管脚初始化
do{
    resp=SD_Init();
    *P_Watchdog_Clear=0x0001;
   }while((resp&0x00ff)!=0);
   *P_SystemClock=C_Fosc_49M;
  for(i=0;i<512;i++)
  {
    buffer1=i*2;
    buffer2=0;
  }

  while(1)
  {
    for(i=0;i<200;i++)
  {
           SD_WriteSingleBlock(0x100+i,buffer1);
   SD_ReadSingleBlock(0x100+i,buffer2);
  }
  *P_DAC1=0xff00;
  Delayus(10000);
   *P_Watchdog_Clear=0x0001;
  }
  
  return 0;
}

//#endif



点击此处下载 ourdev_462022.rar(文件大小:2K) (原文件名:SDdrive.rar)

出0入0汤圆

发表于 2009-8-20 19:18:38 | 显示全部楼层
请问你读SD的卡座是买的还是自己焊的????

出0入0汤圆

发表于 2009-8-21 14:33:20 | 显示全部楼层
先支持

出0入0汤圆

 楼主| 发表于 2009-9-15 14:10:14 | 显示全部楼层
自己焊的

出0入0汤圆

发表于 2009-9-15 19:32:01 | 显示全部楼层
还是 第一次看到有人发凌阳
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-4 11:13

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表