自编基于51单片机的sD卡程序
时间: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);}}}
- 关于RTX51 TINY的分析与探讨(05-30)
- 浅析8051模块化编程技巧(05-28)
- 基于DSP和单片机通信的液晶显示设计方案(07-20)
- 锁相环控制及初始化简析(08-27)
- 基于MSP430自动胀管控制器的研究(09-07)
- 嵌入式C实现延时程序的不同变量的区别(03-01)