|
今天有点小高兴,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) |
|