|
|
呵呵!今天晚上真是走運(yùn)啊,我12月8日開始的做SD讀實(shí)驗(yàn),到今天晚上11:00才做出來啊,其中寫片115次,變過四次程序,連著三晚上沒睡好覺,兩天偷偷的沒去上班在宿舍做實(shí)驗(yàn),終于搞定讀邏輯0扇區(qū)了!我算是受夠了,但是這幾天每天晚上都在找資料,請(qǐng)老師,可是真是那句話,靠誰也不如靠自己,別人是不了解你的實(shí)際情況的,在這里我真的很感謝網(wǎng)絡(luò),有了它,我在千千萬萬的資料中找到了最有用的幾分,然我得意找到鑰匙。
接下來說下SD卡(microsd)讀DBR:
SD卡作為一種存儲(chǔ)設(shè)備早在應(yīng)用了,但是關(guān)于SD卡我還是在做完12864顯示以后才發(fā)現(xiàn),光顯示圖片有啥意思?不如來點(diǎn)動(dòng)畫,呵呵殊不知存儲(chǔ)空間收到限制了,一幅BMP圖片要1KB的存儲(chǔ)空間,我的存儲(chǔ)容量是8K,呵呵,很顯然是不行的,有沒有一種大容量小體積便攜,便于PC操作的存儲(chǔ)設(shè)備那?指向了SD卡,一代的可以最大存儲(chǔ)4GB,這是相當(dāng)海量的,也是很理想的,決定后看了關(guān)于FAT32的文件系統(tǒng),感覺真是很難,不過,也大抵能找到根目錄,F(xiàn)AT表和數(shù)據(jù)區(qū),接下來是做實(shí)驗(yàn)搭模塊,開始看了關(guān)于SD卡的資料,網(wǎng)上資料很多,我看了大多泛泛而談,沒做過的,即使看了還是無處下手,我經(jīng)驗(yàn)如下:1.首先要了解SPI通信,因?yàn)樗腔A(chǔ),要靠他來完成數(shù)據(jù)交換,其實(shí)SPI也沒什么,個(gè)人感覺比異步簡單老鼻子了,關(guān)鍵是SD卡中數(shù)據(jù)發(fā)送時(shí)上升沿,數(shù)據(jù)接收是下降沿,記好了,期間一定要保證數(shù)據(jù)的穩(wěn)定,且在寫時(shí)MISO線要保持高電平,讀時(shí)MOSI要保持高電平,2,寫命令是公六字節(jié),最先發(fā)送的是指令代碼(高位先發(fā))然后是參數(shù),對(duì)于參數(shù)是地址的則按地址字節(jié)最高字節(jié)在前,以此類推,例如:ADD=0x01020304,那么先要發(fā)送01,在發(fā)02,在發(fā)03在發(fā)04;最后發(fā)CRC效驗(yàn),當(dāng)然這里默認(rèn)為FF,不用管它;3,先調(diào)復(fù)位SD卡,然后再調(diào)初始化,在調(diào)讀,這里注意,當(dāng)你初始化復(fù)位時(shí),時(shí)鐘一定要慢,當(dāng)要讀扇區(qū)是一定要提高時(shí)鐘頻率,要不非得操蛋不可,當(dāng)調(diào)好復(fù)位初始化后,先做個(gè)試驗(yàn),讀取0扇區(qū)的值,當(dāng)然這里指的是讀物理扇區(qū),如果讀到扇區(qū)的最后兩個(gè)字節(jié)是55AA,那恭喜你,你的程序沒問題了,但是FAT文件系統(tǒng)要的是邏輯0扇區(qū)的BPB(系統(tǒng)引導(dǎo)記錄),所以你要用軟件打開磁盤找到PHYSICALL SECTOR NO:和LOGICAL SECTOR NO:即物理扇區(qū)和邏輯扇區(qū),例如我的是253 0:表示什么呢?表示邏輯扇區(qū)0在物理253扇區(qū),所以找到253扇區(qū)就找到邏輯0扇區(qū)了,那怎樣找?又要注意了,SD卡的讀操作的尋址是按字節(jié)一扇區(qū)來的,所以要吧扇區(qū)轉(zhuǎn)換成字節(jié),一扇區(qū)是512字節(jié),那么邏輯0扇區(qū)的物理地址為253*512=129536;吧這個(gè)值寫入SD卡然后讀出來就是邏輯0扇區(qū)的值;一個(gè)也不搭茬;找到了邏輯0扇區(qū)就找到了進(jìn)入FAT32文件系統(tǒng)的第一步,也是一把非常重要的鑰匙,但是離最終的文件尋址還差的遠(yuǎn),要是沒這一步,文件尋址是不可能的!還證明了,WINheBUbub不能顯示物理0扇區(qū),只能顯示邏輯0扇區(qū),嘻嘻!
下面是源碼、、、我用的是手機(jī)內(nèi)存卡1GB
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit p1_7=P1^7;
- sbit CS=P2^0; //片選信號(hào)(低電平有效)
- sbit DATEIN =P2^1;//主-從數(shù)據(jù)輸入
- sbit SCLK=P2^2;//時(shí)鐘信號(hào)
- sbit DATEOUT=P2^3;//從-主數(shù)據(jù)輸出
- uint btime;
- uchar c;
- sbit led4=P1^0;
- sbit led3=P1^1; //2010年12月14日與天津開發(fā)區(qū)
- sbit led2=P1^2;
- sbit led1=P1^3;
- uchar g=0,s=0,bw=0,q=0; //顯示單元 個(gè)位、十位、百位、千位
- uchar code tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//不帶小數(shù)點(diǎn)顯示0~9
- unsigned char bdata dat;
- sbit dat_0=dat^0;
- sbit dat_1=dat^1;
- sbit dat_2=dat^2;
- sbit dat_3=dat^3;
- sbit dat_4=dat^4;
- sbit dat_5=dat^5;
- sbit dat_6=dat^6;
- sbit dat_7=dat^7;
- bit is_init;//決定是否延時(shí);
- uchar lpp;
- unsigned char fhz;//返回值
- uchar fhz_buff; //讀返回值中間量
- unsigned char xdata tab[512];
- void delay(uint time)
- { while(time)
- time--;
- }
- //**********************************************
- /*讀sd卡子程序,無返回值,有參函數(shù),參數(shù)為要寫入DATEIN數(shù)據(jù)線的字節(jié)*/
- void write(unsigned char wr_)// 寫入一個(gè)字節(jié)SD卡
- {
- dat=wr_;
- DATEIN=dat_7;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
-
- DATEIN=dat_6;
-
- SCLK=0;
- if(!is_init)delay(2);
- if(is_init)delay(200);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- DATEIN=dat_5;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- DATEIN=dat_4;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- DATEIN=dat_3;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- DATEIN=dat_2;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- DATEIN=dat_1;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- DATEIN=dat_0;
-
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=1;
- if(is_init) delay(200);
- if(!is_init)delay(2);
- }
- unsigned char read()// 讀取一個(gè)字節(jié)SD卡
- {
- DATEOUT=1;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_7=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_6=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_5=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_4=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_3=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_2=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_1=DATEOUT;
- SCLK=1;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- SCLK=0;
- if(is_init)delay(200);
- if(!is_init)delay(2);
- dat_0=DATEOUT;
- return (dat);
- }
- void restsd()//復(fù)位SD卡
- { uchar i;
- uchar pcmd[6]={0x40,0x00,0x00,0x00,0x00,0x95};
- is_init=1;
-
- CS=1;
- for(i=0;i<15;i++)
- {
- //120時(shí)鐘
- write(0xff);
- }
-
-
- CS=1;
- write(0xff);//據(jù)說是提高兼容性
- CS=0;//片選開
- write( pcmd[0]);
- write( pcmd[1]);
- write( pcmd[2]);
- write( pcmd[3]);
- write( pcmd[4]);
- write( pcmd[5]);
- fhz=read();
- for(;;)
- {
- fhz=read();
- if(fhz==0x01)break;
-
-
- }
-
- CS=1;
- write(0xff);
- }
-
- void initsd()//初始化
- {
- //
- uchar pcmd[6]={0x41,0x00,0x00,0x00,0x00,0xff};//
- //
-
- CS=1;
- write(0xff);//據(jù)說是提高兼容性
- CS=0;//片選開
- write( pcmd[0]);
- write( pcmd[1]);
- write( pcmd[2]);
- write( pcmd[3]);
- write( pcmd[4]);
- write( pcmd[5]);
-
-
- fhz=read();
- for(;;)
- {
- fhz=read();
- if(fhz==0x00)break;
-
-
- }
-
- CS=1;
- write(0xff);
-
-
-
- }
- void readsd()//讀SD卡物理扇區(qū)
- {
- uchar pcmd[6]={0x51,0x00,0x01,0xfa,0x00,0xff};//原來這里是高地址字節(jié)在前地地址在后啊201012月14日
- uint j,n;
-
- CS=1;
- write(0xff);//據(jù)說是提高兼容性
- CS=0;//片選開
- write( pcmd[0]);
- write( pcmd[1]);
- write( pcmd[2]);
- write( pcmd[3]);
- write( pcmd[4]);
- write( pcmd[5]);
- DATEOUT=1;
-
- for(;;)
- {
- fhz=read();
- if(fhz==0x00)break;
-
-
- }
- DATEOUT=1;
- for(;;)
- {
- fhz=read();
- if(fhz==0xfe)break;
-
-
- }
- DATEOUT=1;
- n=0;
- for(j=512;j;j--)
- {
- tab[n]=read();
- n++;
-
- }
- fhz=read();
- fhz=read();
- CS=1;
- write(0xff);
-
-
-
- }
- /*void writesd()
- {
- uchar pcmd[6]={0x58,0x00,0x00,0x00,0x00,0xff};
- uint j,k;
-
- CS=1;
- write(0xff);//據(jù)說是提高兼容性
- CS=0;//片選開
- write( pcmd[0]);
- write( pcmd[1]);
- write( pcmd[2]);
- write( pcmd[3]);
- write( pcmd[4]);
- write( pcmd[5]);
-
- DATEOUT=1;
- for(;;)
- {
- fhz=read();
- if(fhz==0x00)break;
-
-
- }
- DATEOUT=1;
- for(j=20;j;j--)
- {
- write(0xff);
-
-
- }
- write(0xfe);
- for(j=512;j;j--)
- { k=tab[j];
- write(k);
-
-
- }
- write(0xff);
- write(0xff);
- DATEOUT=1;
- for(;;)
- {
- fhz=read();
- if((fhz&0x0f)==0x05)break;
- }
-
-
- if(!DATEOUT);
- {
- write(0xff);
- }
- CS=1;
- write(0xff);
-
-
-
- }
- */
- void delay1(uint z) //延時(shí)程序
- {
- uint x,a,b;
- for (x=0;x<z;x++)
-
- {
- for(b=120;b>0;b--)
- {
- for(a=3;a>0;a--);
-
- }
- }
- }
- void display(uchar sd) //顯示程序
- {
- c=sd;
- g=(sd&0x0f);
-
- c=(c>>4);
- s=(c&0x0f);
- led1=0;
- P0=tab1[g]; //個(gè)
- delay1(2);
- led1=1;
- led2=0;
- P0=tab1[s];//十
- delay1(2);
- led2=1;
- led3=0;
- P0=tab1[0]; //百
- delay1(2);
- led3=1;
- led4=0;
- P0=tab1[0]; //千
- delay1(2);
- led4=1;
- }
- void delay2(void) //誤差 -0.00000000025us
- {
- unsigned char a,b,c,n;
- for(c=217;c>0;c--)
- for(b=225;b>0;b--)
- for(a=225;a>0;a--);
- for(n=10;n>0;n--);
- }
- void main()
- { uint ad;
- uchar v;
- is_init=1;
- restsd();
- initsd();
- is_init=0;//提高始終頻率
- p1_7=0;
- //writesd();
- readsd();//讀物理扇區(qū)
- p1_7=1;
- btime=65536;
- while(1)
- { btime=300;
- delay2();
-
- for(;;)
- {
- v=tab[ad];
- display(v);
- btime--;
- if(btime==0)break;
- }
- ad++;
- if(ad==512)ad=0;
- }
-
-
- }
復(fù)制代碼 以上程序僅在本人試驗(yàn)?zāi)K中通過,不知兼容咋樣!用LED顯示512字節(jié)的碼形!
2015年12月14日-12月8日歷時(shí)一星期終于讀出BPB,加油啊,離文件系統(tǒng)還差的遠(yuǎn)。
|
評(píng)分
-
查看全部評(píng)分
|