<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > SD卡FAT16文件系統(tǒng)的學習筆記

          SD卡FAT16文件系統(tǒng)的學習筆記

          作者: 時間:2016-07-18 來源:網絡 收藏

            一、 讀文件的流程

          本文引用地址:http://www.ex-cimer.com/article/201607/294155.htm

            讀物理扇區(qū)0,得到引導扇(邏輯扇區(qū)0)的偏移地址。

            讀引導扇的內容,得到文件系統(tǒng)基本配置信息。

            根據文件系統(tǒng)的基本配置信息計算FAT,FDT,數據簇的起始地址和大小。

            根據要讀的文件名搜索FDT表,找到要讀文件的起始數據簇編號,大小。

            根據文件的起始數據簇編號在FAT表中查找所有該文件占用的數據簇及數據簇訪問的先后關系。

            讀取該文件的起始數據簇的內容,及下一數據簇內容(有需要時)。

            二、 讀取物理扇區(qū)0

            先讀取的第一個扇區(qū)(512字節(jié)),即扇區(qū)0,然后該扇區(qū)最后部分的數據如下圖所示

            

           

            正常的話,該扇區(qū)最后兩個字節(jié)如上圖所示為55 AA,如果不是則證明是讀錯了,或者該SD沒有被格式化。

            該扇區(qū)有兩個重要信息:

            一、 在0x1ca開始的四個字節(jié)9f c9 03 00,即0x3c99f=248223,代表該友248223個扇區(qū),因為每個扇區(qū)有512字節(jié),所以該容量為248223*512/1024/1024=121.2MByte

            二、在0x1c6開始的四個字節(jié)61 00 00 00,即0x61=97,它表示引導扇區(qū)在扇區(qū)97。那我們就接著讀扇區(qū)97,獲取SD卡里更詳細的信息,這個扇區(qū)0就可以不用管了。

            三、 讀取引導扇區(qū)

            以下是扇區(qū)97前64Byte的內容。因為97*512=0xc200,所以可以下圖左邊的偏移地址為c200

            

           

            首先第0x3到0xA的內容為ASCII碼的“MSDOS5.0”,不是重要信息

            第0xb開始的兩個字節(jié)00 02,即0x2000=512,代表每個扇區(qū)(sector)有512個字節(jié)(byte)

            接下來的04代表每個簇(cluster)有4個扇區(qū)

            接下來的04 00 即0x4代表有4-1個保留扇區(qū),即是第一個FAT表所在扇區(qū)為引導扇區(qū)(97)+4=扇區(qū)101

            接下來的02 代表有兩個FAT表

            接下來的00 02,即0x2000=512,代表FDT(目錄區(qū))有512登記項

            第0x16開始的兩個字節(jié)f2 00,即0xf2=242,代表每個FAT表占242個扇區(qū)

            第0x36到0x3d代表的就是“ ”的ASCII碼,說明這SD卡是的格式

            四、 文件系統(tǒng)的結構

            知道以上的信息之后我們就可以根據以上信息計算出FAT1,FAT2,FDT和數據簇的首地址和結束地址,但在計算之前,我有必要介紹一下整個FAT16文件系統(tǒng)的結構和各個區(qū)的含義與作用。

            

           

            五、 獲取文件系統(tǒng)基本配置信息

            現在既然已經大概了解了引導扇,FAT1,FAT2,FDT和數據簇的作用,接下來就說一下怎么計算它們的起始地址和結束地址。我們用扇區(qū)來作為地址單位。

            我們首先定義兩個結構體

            typedef struct

            {

            U16 BytesPerSector; //每個扇區(qū)多少字節(jié)

            U8 SectorsPerCluster; //每個簇有多少個扇區(qū)

            U16 ReserveSectors; //保留扇區(qū)數

            U8 FatTableNums; //有多少個FAT表

            U16 RootDirRegNums; //根目錄允許的登記項數目

            U16 SectorsPerFat; //每個FAT表有多少個扇區(qū)

            U32 SectorNums; //總的扇區(qū)數

            U8 FileType[7]; //文件系統(tǒng)類型

            }FAT_PARA;

            typedef struct

            {

            U32 Logic; //引導扇(邏輯扇區(qū)0)對物理0扇區(qū)里的偏移地址

            U32 FAT1;

            U32 FAT2;

            U32 FDT;

            U32 Cluster; //數據簇的偏移地址

            }FAT_OFFSET;

            FAT_PARA SD_para; //聲明兩個結構體變量

            FAT_OFFSET SD_offset;

            由之前的知識可以知道,我們首先從物理扇區(qū)0知道SD_offset.Logic的地址,然后就可以找到引導扇.然后再在引導扇里找到SD_para里面所有變量的值。

            U8 buffer[512];

            Read_Single_Block(0, buffer);//把物理扇區(qū)0的512個字節(jié)的數據讀到buffer里

            SD_offset.Logic = (* (U16 *) (buffer + 0x1c6)) + ((* (U16 *) (buffer + 0x1c8)) << 16); //得到引導扇的偏移地址

            Read_Single_Block(SD_offset.Logic, buffer) ; //讀引導扇的數據

            //獲取參數,以便計算各個區(qū)的偏移地址

            SD_para.BytesPerSector = (* (U8 *) (buffer + 0xb)) + ((* (U8 *) (buffer + 0xc)) << 8);

            SD_para.SectorsPerCluster = * (buffer + 0x0d);

            SD_para.ReserveSectors = * (U16 *) (buffer + 0x0e);

            SD_para.FatTableNums = * (buffer + 0x10);

            SD_para.RootDirRegNums = (* (U8 *) (buffer + 0x11)) + ((* (U8 *) (buffer + 0x12)) << 8);

            SD_para.SectorsPerFat = * (U16 *) (buffer + 0x16);

            SD_para.SectorNums = * (U32 *) (buffer + 0x20);

            for(i = 0; i < 6; i++)

            SD_para.FileType[i] = *(buffer+0x36+i);

            SD_para.FileType[6] = 0;

            六、 計算各重要區(qū)域的大小與起始地址

            //計算各個區(qū)的偏移地址

            //FAT1地址=引導扇地址+保留扇區(qū)數,大小為SD_para.SectorsPerFat

            SD_offset.FAT1 = SD_offset.Logic + SD_para.ReserveSectors;

            //如果存在兩個FAT表,一般不是1就是2

            if (SD_para.FatTableNums == 2)

            //FAT2地址=FAT1地址+ SD_para.SectorsPerFat

            SD_offset.FAT2 = SD_offset.FAT1 + SD_para.SectorsPerFat;

            else SD_offset.FAT2 = 0;

            //FDT地址=FAT1+FAT表數*FAT表大小

            SD_offset.FDT=SD_offset.FAT1+SD_para.FatTableNums*SD_para.SectorsPerFat;

            //因為數據簇2緊跟在FDT后,所以數據簇0易求得

            SD_offset.Cluster = SD_offset.FDT + 32 - 2 * SD_para.SectorsPerCluster;

            七、 FDT與FAT表的簡單介紹

            讀取文件之前要先詳細了解一下FDT,和FAT表的內容

            一個FDT表占32個扇區(qū),共有512個文件登記信息,所以每個文件登記信息的大小為32*512/512=32Byte

            每個文件登記信息如下圖所示

           

            對于我們來說,這個文件記錄信息最重要的就是最后六個字節(jié)

            最后四個字節(jié)代表文件大小,由文件大小可以推算出該文件占用多少個數據簇

            第0x1a到0x1b個字節(jié)道標文件開始的首簇號,知道文件的首簇號我們就可以查看FAT表的相應信息,就可得到該文件所占用的所有數據簇的簇號。

            以下是FAT表的結構

            

           

            上表中,06、07單元映射了磁盤3號簇區(qū)。有之前的介紹中可以知道,我這張SD卡1個簇包含4個扇區(qū)。也就是說在寫數據時,只有寫完了3號簇的4個扇后,將FAT表的06,07單元填寫04,00;才可繼續(xù)在04號簇上寫數據。如果數據寫完后還沒有寫滿3號簇,則在FAT表的06,07單元填寫FF,FF.

            也就是說在FAT表中記錄著每個數據簇的狀態(tài),且每個數據簇的狀態(tài)占用兩個字節(jié)。如果這兩個字節(jié)等于0xffff,則代表該數據簇以被占用,且文件在該數據簇中結束。如果這兩個字節(jié)等于0x0001~0xfffe,則代表該數據簇已被占用,且該文件沒有結束,而該文件存放的下一數據簇的簇號就等于這兩個字節(jié)的大小。

            八、 讀取一個文件

            下面以我的SD卡為例子,向大家介紹讀寫SD的FAT文件系統(tǒng)的文件(最好先安裝一個叫做winhex的軟件)。

            首先我的SD卡存放著這樣一個文件

            

           

            要打開我這個名為lqz.txt的文件的,我們先查找FDT表中關于lqz.txt這個文件的登記信息。

            因為之前已經知道了FDT的首地址是第585扇區(qū),我們來到585扇區(qū),開始搜索LQZ.TXT(必須先轉換成大寫字母)

            最后在地址為0x4a310(也就是第0x4a310/512=593扇區(qū))的地方搜索到LQZ.TXT的文件登記信息,在最后四個字節(jié)得知該文件大小為0x00002c89=11401Byte,占用11401/512/4=6個數據簇,從倒數第5,6個字節(jié)可以知道文件的首簇號為0x2fe4,然后在FAT表根據文件的首簇號查找接下來文件占用的五個數據簇簇號,數據簇0x2fe4在FAT的登記位置=FAT地址+0xfe4*2=0xca00+0x2fe4*2=0x129c8,我們來到0x129c8這個地址

            數據簇0x2fe4的信息就存放在0x129c8,和0x129c9這個字節(jié)里,從上圖可以看出這兩個字節(jié)等于0x46F4,也就是說LQZ.TXT存放的下一個數據簇的簇號為0x46F4,由于該文件占用6個數據簇,所以我們必須繼續(xù)查找剩下的4個數據簇的簇號。我們繼續(xù)查找簇號為0x46f4的數據簇在FAT表的信息,地址為0xca00+0x46f4*2=0x157e8

            由上圖可以下一數據簇的簇號為0x46f5。然后按照上訴方法查找剩余三個簇號分別為0x46f6,0x46f7,0x46f8,最后在0x46f8對應的地方存放著0xffff,代表文件到此結束。

            經過上訴步驟我們知道我lqz.txt文件依次存放在0x2fe4,0x46f4,0x46f5,0x46f6,0x46f7,0x46f8這6個數據簇,接下來我們就讀取這6個數據簇的內容即可。

            比如說:數據簇0x2fe4的地址=數據簇0地址+0x2fe4*4*512=0x4c200+0x2fe4*4*512=0x183e200,0x183e200/512=49649,也就是在物理扇區(qū)49649~49652這個四個扇區(qū)都是數據簇0x2fe4的內容。



          關鍵詞: FAT16 SD卡

          評論


          相關推薦

          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();