新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 自编基于51单片机的sD卡程序

自编基于51单片机的sD卡程序

作者:时间:2012-08-10来源:网络收藏
#includereg52.h>#includeintrins.h>#define uint unsigned int#define uchar unsigned char//错误码定义//#define cmd0_error 0x01#define cmd1_error 0x02#define write_error 0x03#define read_error 0x04/*位定义*/sbit so=P1^0; //定义主机接收位sbit clk=P1^1;    //定义时钟位sbit si=P1^2; //定义主机发送数据位sbit cs=P1^3; //定义片选位uchar xdata shuju[512]={0};     //定义数据缓冲数组uchar flag_time;         //定义标志时间,因为当sd卡进行时需要降低//通信速度,所以通过该标志来写1来降低速度void delay(uint x)       //通信延时函数{while(x--)_nop_();}void delay1(uint a)     {uint i,j;for(i=0;ia;i++)for(j=0;j120;j++);}//写一字节数据//void write_sd(uchar date)  {uchar i;CY=0;clk=1;for(i=0;i8;i++){clk=0;date=date1;si=CY;if(flag_time==1)  //用来判断是否处于,如果是降低通信速度delay(10);_nop_();   //用来让io口数据更稳定,也可以省略clk=1;_nop_();if(flag_time==1)delay(10);}}//读取sd卡一个字节数据//uchar read_sd()      {uchar i,temp=0;so=1;          //一定要先将其置1否则会出现错误//因为如果先置0单片机io口寄存器相应位电平为低当//当接收到高电平后可能sd卡电平不足使其io变为高电平clk=1;for(i=0;i8;i++){clk=0;if(flag_time==1)delay(10);temp=1;temp=temp|so;_nop_();clk=1;_nop_();if(flag_time==1)delay(10);}return temp;}//向sd卡写命令//uchar write_cmd(uchar *cmd){uchar i,time,temp;  si=1;for(i=0;i6;i++)  //发送六字节命令{write_sd(cmd[i]);}time=0;do{  temp=read_sd();time++;}while((temp==0xff)(time100));//判断命令是否写入成功,当读取到so不为0xff时命令写入成功//当temp==0xff时为真且没发送100次为真继续执行//但是又不能无限制等待所以让命令写入100次结束return temp;      //返回读取的数据}//复位函数//uchar sd_reset(){uchar i,temp=0xff,time;uchar table[]={0x40,0x00,0x00,0x00,0x00,0x95};flag_time=1;cs=1;for(i=0;i0x0f;i++)      //复位时最少写入74个时钟周期{write_sd(0xff);}  cs=0;time=0;//打开片选do{temp=write_cmd(table);   //写入cmd0time++;if(time==100)return(cmd0_error);}while(temp!=0x01);       //等待命令CMD0的响应cs=1;                  //关闭片选write_sd(0xff);           //补偿8个时钟return 0;}//函数此函数决定SD卡的工作模式 选择SPI还是SD模式//uchar sd_init(){uchar time=0,temp=0xff;uchar table[]={0x41,0x00,0x00,0x00,0x00,0xff};       //命令码flag_time=1;cs=0;time=0;do{temp=write_cmd(table);time++;if(time==100)return 0x02;}while(temp!=0x00);       //等待命令CMD1响应flag_time=0;cs=1;write_sd(0xff);           //补偿8个时钟return 0;}//写sd卡扇区//uchar xie_sd_shanqu(unsigned long int add,uchar *buffer){uchar temp,time;uint i;uchar table[]={0x58,0x00,0x00,0x00,0x00,0xff};add=add9;       //add=add*512//由于sd卡操作一次性只能写一个扇区也就是512个字节//所以这里通过将长整型地址左移九位来将地址乘上512//用于地址操作table[1]=((add0xff000000)>>24);table[2]=((add0x00ff0000)>>16);table[3]=((add0x0000ff00)>>8);cs=0;time=0;do{temp=write_cmd(table);       //写入写扇区命令time++;if(time==100){return(write_error);}}while(temp!=0x00);               //判断命令是否写入成功成功时返回0x00for(i=0;i20;i++)     //补充若干时钟{write_sd(0xff);}write_sd(0xfe);       //写入开始字节0xfe,后面要写入512字节数据for(i=0;i512;i++){write_sd(buffer[i]);}write_sd(0xff);  write_sd(0xff);           //两字节奇偶校验temp=read_sd();           //读取返回值if((temp0x1f)!=0x05)        //如果返回值是 xxx00101 说明数据已经被写入{cs=1;return(write_error);}while(read_sd()!=0xff);          //等待sd卡不忙 数据写入成功cs=1;                  //关闭片选write_sd(0xff);           //补偿8 个时钟return 0;}//读取sd卡扇区//uchar duqushanqu(unsigned long add,uchar *buffer){uchar temp,time=0;uint i;uchar  table[]={0x51,0x00,0x00,0x00,0x00,0xff};add=add9;table[1]=((add0xff000000)>>24);table[2]=((add0x00ff0000)>>16);table[3]=((add0x0000ff00)>>8);cs=0;                          //打开片选do{temp=write_cmd(table);       //写命令time++;if(time==100){return read_error;}}while(temp!=0);write_sd(0xff);               //补偿8个时钟while(read_sd()!=0xfe);      //一直读取等待0xfefor(i=0;i512;i++){buffer[i]=read_sd();}write_sd(0xff);           //两字节奇偶校验位write_sd(0xff);cs=1;write_sd(0xff);           //补偿8个时钟return 0;}/*在P0上接八个发光二极管用来显示读取到的数据首先在数组(shuju)里面放入i用于显示,再将其写入SD卡扇区,然后在读取出SD卡里的数据*/void main(){uint i=0;P2=0x00;P0=0xff;sd_reset();  sd_init();     ///初始化sd卡for(i=0;i512;i++){shuju[i]=i;           //向数据数组里面写入数据}for(i=0;i512;i++){xie_sd_shanqu(1,shuju);      //将数据数组里面的数据写入sd卡}for(i=0;i2;i++){shuju[i]=0;           //清零数据数组用来存储从sd卡读取到的数据}         duqushanqu(1,shuju);     //读取扇区数据while(1){for(i=0;i512;i++){P0=shuju[i];      //显示扇区数据delay1(200);}}}


评论


相关推荐

技术专区

关闭