SD卡和FAT文件系統(tǒng)示例
我現(xiàn)在用的多是SPI模式,所以在這里只討論SPI模式。在SPI模式中,所有的指令都要求先將CS腳置0。所以這點,我在后面就不再強調(diào)了。
CMD0,使SD卡從SD模式轉(zhuǎn)到SPI模式。判斷返回值R0,如果不是CARD IS NOT READY,說明硬件上有問題。
CMD8,參數(shù)是0x000001AA,判斷SD卡符合哪個標準。如果返回ILLEGAL COMMAND,說明是ver1.x的卡,否則就是ver2.0的卡。
CMD1,如果是ver2.0的卡,參數(shù)是1<<30,否則就是0,讀取SD卡的狀態(tài),反復,直到CARD IS READY或者超時。這里有一個問題,Spec上建議使用ACMD1,說是通用性比CMD1好,而且CMD1并不是一開始就可以使用的。但是我在實際使用中,發(fā)現(xiàn)一些老卡對這個指令會返回PARAMETER ERROR。搞不懂是為什么,而且實際使用中CMD1也很好用,并沒有出現(xiàn)SD卡不能初始化的問題,所以我現(xiàn)在都直接用CMD1。
到這里基本上SD卡就初始化完畢了。接下來就可以讀取數(shù)據(jù)了。
2. 讀取CID(CMD10),SD卡鑒別信息,這一步不是必須的。
鑒別信息中包括了生產(chǎn)商ID,應用ID,產(chǎn)品名稱,產(chǎn)品版本,產(chǎn)品序列號,生產(chǎn)日期。
3. 讀取CSD(CMD9),SD卡信息。
返回的CSD有兩個版本。
if (CSD[0] & 0x40 == 0x40) // ver2.0的卡
容量 = 1024L*(CSD[8]<<8+CSD[9])
這個數(shù)字就是這張SD卡里面總共有多少個扇區(qū)。
if (CSD[0] & 0x40 != 0x40) // ver1.x的卡
容量 = (((CSD[6]&0x03)<<10) | (CSD[7]<<2) | ((CSD[8]&0xC0)>>6) + 1) * (1 << ((((CSD[9]&0x03)<<1) | ((CSD[10]&0x80)>>7)) + 2))
4. 讀取Partition Table。
讀取SD卡的扇區(qū)0到buf。
如果buf[0]不是0xEB或者0xE9,說明這是一個分區(qū)表。
buf[454]開始的四個byte是該分區(qū)前的扇區(qū)數(shù)。例如63表示在這個分區(qū)前有63個扇區(qū),那么這個分區(qū)的第一個扇區(qū)就是扇區(qū)63。
buf[458]開始的四個byte是該分區(qū)的扇區(qū)數(shù)。例如7990000,不是這個分區(qū)有7990000個扇區(qū)。那么這個分區(qū)的塊地址就是63~7990063。
一個設(shè)備可以最多有四個分區(qū),其他三個分區(qū)的相關(guān)數(shù)據(jù)是在buf[470]/buf[474],buf[486]/buf[490],buf[502]/buf[506]。
注意,讀取buf的時候檢查最好兩位,應該是55AA。
5. 讀取BPB。
好,到這里我們已經(jīng)知道第一個分區(qū)是在什么位置了?,F(xiàn)在需要做的就是讀取這個分區(qū)的0扇區(qū)。也就是SD卡的第36個扇區(qū)。
這個512個byte就是這個分區(qū)的詳細資料了。
檢查buf[0],應該是0xEB或者0xE9。如果是的話,那就是BPB表了。接下來比較重要的幾個數(shù)字是:
buf[13]的Sectors Per Cluster,就是每個簇的扇區(qū)數(shù),也就是你在讀取文件是需要一次讀取的扇區(qū)數(shù)。例如8。
buf[14-15]的Reserved Sectors,保留扇區(qū)數(shù),這個保留扇區(qū)是在分區(qū)第一個扇區(qū)到FAT表之間的扇區(qū)數(shù)。例如38。
buf[28-31]的Hidden Sectors,隱藏扇區(qū)數(shù),這個隱藏扇區(qū)指的是在這個分區(qū)前面有多少個扇區(qū),這個值在分區(qū)表里也有的。就是63。
buf[19-20]和buf[32-35],前者是FAT16格式中的扇區(qū)數(shù),后者是FAT32格式中的扇區(qū)數(shù)。這個值在分區(qū)表里也是有的。就是7990000。
buf[16],F(xiàn)AT表數(shù),一般是2。
buf[22-23],buf[36-39],F(xiàn)AT表占用的扇區(qū)數(shù),前者是FAT16的,后者是FAT32的。例如7793。
好了,到這里我們就可以讀取FAT文件系統(tǒng)中的數(shù)據(jù)了。
6. 讀取FAT表。
在上面的例子中,F(xiàn)AT表的位置應該是分區(qū)的第一個扇區(qū)再偏移隱藏扇區(qū)數(shù),就是63+38,等于101。所以從SD卡的101扇區(qū)開始,就是分區(qū)一的FAT表,一共有7793個扇區(qū)。
7. 讀取根目錄。
在FAT16中,根目錄是單獨的。應該是可以建立512個文件,每個文件占用32byte,所以總共是512*32/512=32個扇區(qū)。
根目錄是跟在FAT表后面的,所以第一個扇區(qū)是在101+7793*2=15687。
對于FAT32系統(tǒng),這段忽略。
8. 讀取數(shù)據(jù)區(qū)。
FAT16中,數(shù)據(jù)區(qū)是在根目錄后面的,所以第一個扇區(qū)是15687+32=15719。就是在SD卡上的第15719個扇區(qū)。
而FAT32中,由于沒有根目錄,所以數(shù)據(jù)區(qū)直接跟在FAT表后面的,所以就是第15687個扇區(qū)。這個扇區(qū)就是LBA=2的地方。所以之后如果上層的文件操作函數(shù),要對LBA=1000寫數(shù)據(jù),那就是對1000+15687=16687扇區(qū)進行寫操作。
到此,我們就得到了整個FAT系統(tǒng)的結(jié)構(gòu)和數(shù)據(jù),接下來就可以開始操作文件了。
評論