搜档网
当前位置:搜档网 › 单片机读写SD卡教程

单片机读写SD卡教程

单片机读写SD卡教程
单片机读写SD卡教程

郑重声明:本实验并不是对所有SD卡都能成功运行

第一步:打开winhex软件,用读卡器读SD卡,在winhex中查看SD卡

点这

点击查找(ctrl+F)

输入FAT(找到DBR处)

发现DBR起始于0x11200扇区地址,它必是512整数倍,因为一个扇区含512BYTE,所以在程序中读一个扇区时一定要是512整数倍,否则会出错。11200地址对应的值是0xEB,本程序读一下这个地址的值看看是否正确。注意有的winhex编址是十进制

看看程序吧

#include

#define uchar unsigned char

#define uint unsigned int

//=============================================================

//定义SD卡需要的4根信号线

sbit SD_CLK = P1^1;

sbit SD_DI = P1^2;

sbit SD_DO = P1^0;

sbit SD_CS = P1^3;

sbit Beep=P2^0;//用来调程序标志

//===========================================================

//===========================================================

//定义512字节缓冲区,,89C52直接定义成unsigned char DATA[80];,太大了RAM不够unsigned char xdata DATA[512];

void delay(unsigned int z)

{

unsigned int x,y;

for(x=z;x>0;x--);

for(y=110;y>0;y--);

}

//=========================================================== //写一字节到SD卡,模拟SPI总线方式

void SdWrite(unsigned char n)

{

unsigned char i;

for(i=8;i;i--)

{

SD_CLK=0;

SD_DI=(n&0x80);

n<<=1;

SD_CLK=1;

}

SD_DI=1;

}

//=========================================================== //从SD卡读一字节,模拟SPI总线方式

unsigned char SdRead()

{

unsigned char n,i;

for(i=8;i;i--)

{

SD_CLK=1;

SD_CLK=0;

n<<=1;

if(SD_DO) n|=1;

}

return n;

}

//============================================================ //检测SD卡的响应

unsigned char SdResponse()

{

uchar i=0,response=0;

while(i<=8)

{

response = SdRead();

if(response==0x00)

break;

if(response==0x01)

break;

i++;

}

return response;

}

//================================================================ //发命令到SD卡

void SdCommand(unsigned char command, unsigned long argument, unsigned char CRC) {

SdWrite(command|0x40);

/*SdWrite(((unsigned char *)&argument)[0]);

SdWrite(((unsigned char *)&argument)[1]);

SdWrite(((unsigned char *)&argument)[2]);

SdWrite(((unsigned char *)&argument)[3]);*/

SdWrite(argument>>24);

SdWrite(argument>>16);

SdWrite(argument>>8);

SdWrite(argument);

SdWrite(CRC);

}

//================================================================ //初始化SD卡

unsigned char SdInit(void)

{

unsigned char i;

unsigned char response=0xFF;

P3=0xff;

SD_CS=1;

for(i=0;i<=0xfe;i++)

SdWrite(0xff);

SD_CS=0;

SdCommand(0x00,0,0x95);

SD_DI=1;

response=SdResponse();

if(response!=0x01)

{

return 0;

}

if(response==0x01)

{ //不管什么SD卡都能进入这一步,同时也说明硬件没问题SD_CS=1;

//Beep=0;

//while(1);//用来查看程序能否运行到这一步,去掉//即可

SdWrite(0xff);

SD_CS=0;

while(1)

{

SdCommand(0x01,0,0xff);//SdCommand(0x01,0x00000000,0xff);//进SPI

response=0xff;

SD_DI=1;

for(i=0;i<250;i++)//response!=0x00//等待回复

{

response=SdResponse(); //Beep=0;/

if(response==0) break;

}

if(response==0) {break;}//回复0则通过SPI,只要通过SPI后面的指令才能继//续

// Beep=0;

}

// Beep=0;//看程序能否跳出来,挑不出来则进不了SPI

SD_CS=1;

SdWrite(0xff);

SD_CS=0;

// Beep=0;

return 1;

}

}

//================================================================

//往SD卡指定地址写数据,一次最多512字节最好不要乱写否则fat系统被改掉SD卡打不开

unsigned char SdWriteBlock(unsigned char *Block, unsigned long address,int len)

{

unsigned int count;

unsigned char dataResp;

SD_CS=0;

SdCommand(0x18,address,0xff);

if(SdResponse()==00)

{

SdWrite(0xff);

SdWrite(0xff);

SdWrite(0xff);

//command was a success - now send data

//start with DATA TOKEN = 0xFE

SdWrite(0xfe);

//now send data

for(count=0;count

for(;count<512;count++) SdWrite(0);

//data block sent - now send checksum

SdWrite(0xff); //两字节CRC校验, 为0XFFFF 表示不考虑CRC

SdWrite(0xff);

//Now read in the DA TA RESPONSE token

dataResp=SdRead();

while(SdRead()==0);

dataResp=dataResp&0x0f; //mask the high byte of the DATA RESPONSE token

SD_CS=1;

SdWrite(0xff);

if(dataResp==0x0b)

{

return 0;

}

if(dataResp==0x05)return 1;

return 0;

}

//printf("Command 0x18 (Write) was not received by the SD.\n");

return 0;

}

//===================================================================== ==

//从SD卡指定地址读取数据,一次最多512字节

unsigned char SdReadBlock(unsigned char *Block, unsigned long address,int len)

{

unsigned int count,i;

uchar response;

SD_CS=0;

// while(1)

// {

SdCommand(0x11,address,0xff);

// SD_DO=1;

// P0=SdResponse();

// P0=0xff;

// while(1);

while(response!=0xfe && i<200) {response=SdRead();P0=response;i++;} // if(i>=200) Beep=0;

// P0=0xf0;

// }

// Beep=0;

for(count=0;count<512;count++) *Block++=SdRead();

SdRead();

SdRead();

//Now read in the DA TA RESPONSE token

SD_CS=1;

SdWrite(0xff);

return 1;

}

void main()

{

unsigned int mm;

unsigned long AddTemp=0x11200;//70144;//SD卡地址第一个数据物理地址初始值70144是通过winhex查看,对于你的SD卡肯定要改

//可以用winhex查看,一定要是512整数倍mm=SdInit();

//

SdReadBlock(DATA,AddTemp,1);

delay(10);

// Beep=0;

if(DATA[0]==0xeb) Beep=0;// 看读的对不对

while(1);

}

相关主题