#includereg52.h>#includeintrins.h>#define uint unsigned int#define uchar unsigned char//錯(cuò)誤碼定義//#define cmd0_error 0x01#define cmd1_error 0x02#define write_error 0x03#define read_error 0x04/*位定義*/sbit so=P1^0; //定義主機(jī)接收位sbit clk=P1^1; //定義時(shí)鐘位sbit si=P1^2; //定義主機(jī)發(fā)送數(shù)據(jù)位sbit cs=P1^3; //定義片選位uchar xdata shuju[512]={0}; //定義數(shù)據(jù)緩沖數(shù)組uchar flag_time; //定義標(biāo)志時(shí)間,因?yàn)楫?dāng)sd卡進(jìn)行初始化時(shí)需要降低//通信速度,所以通過該標(biāo)志來寫1來降低速度void delay(uint x) //通信延時(shí)函數(shù){while(x--)_nop_();}void delay1(uint a) {uint i,j;for(i=0;ia;i++)for(j=0;j120;j++);}//寫一字節(jié)數(shù)據(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口數(shù)據(jù)更穩(wěn)定,也可以省略clk=1;_nop_();if(flag_time==1)delay(10);}}//讀取sd卡一個(gè)字節(jié)數(shù)據(jù)//uchar read_sd() {uchar i,temp=0;so=1; //一定要先將其置1否則會(huì)出現(xiàn)錯(cuò)誤//因?yàn)槿绻戎?單片機(jī)io口寄存器相應(yīng)位電平為低當(dāng)//當(dāng)接收到高電平后可能sd卡電平不足使其io變?yōu)楦唠娖絚lk=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++) //發(fā)送六字節(jié)命令{write_sd(cmd[i]);}time=0;do{ temp=read_sd();time++;}while((temp==0xff)(time100));//判斷命令是否寫入成功,當(dāng)讀取到so不為0xff時(shí)命令寫入成功//當(dāng)temp==0xff時(shí)為真且沒發(fā)送100次為真繼續(xù)執(zhí)行//但是又不能無限制等待所以讓命令寫入100次結(jié)束return temp; //返回讀取的數(shù)據(jù)}//復(fù)位函數(shù)//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++) //復(fù)位時(shí)最少寫入74個(gè)時(shí)鐘周期{write_sd(0xff);} cs=0;time=0;//打開片選do{temp=write_cmd(table); //寫入cmd0time++;if(time==100)return(cmd0_error);}while(temp!=0x01); //等待命令CMD0的響應(yīng)cs=1; //關(guān)閉片選write_sd(0xff); //補(bǔ)償8個(gè)時(shí)鐘return 0;}//初始化函數(shù)此函數(shù)決定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響應(yīng)flag_time=0;cs=1;write_sd(0xff); //補(bǔ)償8個(gè)時(shí)鐘return 0;}//寫sd卡扇區(qū)//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卡操作一次性只能寫一個(gè)扇區(qū)也就是512個(gè)字節(jié)//所以這里通過將長(zhǎng)整型地址左移九位來將地址乘上512//用于地址操作table[1]=((add0xff000000)>>24);table[2]=((add0x00ff0000)>>16);table[3]=((add0x0000ff00)>>8);cs=0;time=0;do{temp=write_cmd(table); //寫入寫扇區(qū)命令time++;if(time==100){return(write_error);}}while(temp!=0x00); //判斷命令是否寫入成功成功時(shí)返回0x00for(i=0;i20;i++) //補(bǔ)充若干時(shí)鐘{write_sd(0xff);}write_sd(0xfe); //寫入開始字節(jié)0xfe,后面要寫入512字節(jié)數(shù)據(jù)for(i=0;i512;i++){write_sd(buffer[i]);}write_sd(0xff); write_sd(0xff); //兩字節(jié)奇偶校驗(yàn)temp=read_sd(); //讀取返回值if((temp0x1f)!=0x05) //如果返回值是 xxx00101 說明數(shù)據(jù)已經(jīng)被寫入{cs=1;return(write_error);}while(read_sd()!=0xff); //等待sd卡不忙 數(shù)據(jù)寫入成功cs=1; //關(guān)閉片選write_sd(0xff); //補(bǔ)償8 個(gè)時(shí)鐘return 0;}//讀取sd卡扇區(qū)//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); //補(bǔ)償8個(gè)時(shí)鐘while(read_sd()!=0xfe); //一直讀取等待0xfefor(i=0;i512;i++){buffer[i]=read_sd();}write_sd(0xff); //兩字節(jié)奇偶校驗(yàn)位write_sd(0xff);cs=1;write_sd(0xff); //補(bǔ)償8個(gè)時(shí)鐘return 0;}/*在P0上接八個(gè)發(fā)光二極管用來顯示讀取到的數(shù)據(jù)首先在數(shù)組(shuju)里面放入i用于顯示,再將其寫入SD卡扇區(qū),然后在讀取出SD卡里的數(shù)據(jù)*/void main(){uint i=0;P2=0x00;P0=0xff;sd_reset(); sd_init(); ///初始化sd卡for(i=0;i512;i++){shuju[i]=i; //向數(shù)據(jù)數(shù)組里面寫入數(shù)據(jù)}for(i=0;i512;i++){xie_sd_shanqu(1,shuju); //將數(shù)據(jù)數(shù)組里面的數(shù)據(jù)寫入sd卡}for(i=0;i2;i++){shuju[i]=0; //清零數(shù)據(jù)數(shù)組用來存儲(chǔ)從sd卡讀取到的數(shù)據(jù)} duqushanqu(1,shuju); //讀取扇區(qū)數(shù)據(jù)while(1){for(i=0;i512;i++){P0=shuju[i]; //顯示扇區(qū)數(shù)據(jù)delay1(200);}}}
評(píng)論