SD Card 初始化和讀取 SD Card 程式完成後,這是 SD Card 的底層通訊,便開始要讀寫 SD Card 內資料,筆者剛好是使用 SanDisk 2GB SD Card(格式化後 = 1,943,990,784 Byte)記憶卡,所以便會用 FAT作編程,而且 FAT 也可以使用在一般電腦上,作後期的資料處理是非常方便。
SD Card FAT 檔案系統 |
1. 主引導記錄(Master Boot Record / MBR):
MBR 是放置在 SD Card 物理位址 0 的地方,MBR 是由 512 位元組組成,MBR 只佔用了其中的 446 個位元組,另外 64 個位元組交給了 DPT(Disk Partition Table 硬碟分區表),最後兩個位元組 “55,AA” 是分區的結束標誌。
SanDisk 2GB SD Card 主引導記錄(Master Boot Record / MBR) |
Offset
|
Length
|
Name
|
Description
|
00H
|
446
|
啟動狀態
|
0=not bootable 0x80=bootable
|
0x1BE
|
1
|
啟動狀態
|
0=not bootable 0x80=bootable
|
0x1BF
|
1
|
分區1起始扇區數
|
Partition 1: Start Head
|
0x1C0 ~ 0x1C1
|
2
|
分區1起始扇區數
|
Partition 1: Start Sector / Cylinder
|
0x1C2
|
1
|
檔案系統
|
Partition Type
01h = 12bit FAT 04h = 16bit FAT (<32mb br=""> 05h = Ex MSDOS 06h = 16bit FAT (>32Mb) 0Bh = 32bit FAT (<2gb span="">2gb>32mb> |
0x1C3
|
1
|
分區1結束扇區數
|
Partition 1: End Head
|
0x1C4
|
2
|
分區1結束扇區數
|
Partition 1: End Sector / Cylinder
|
0x1C6 ~ 0x1C9
|
4
|
此分區前扇區數
|
Start Sector Address of Partition 1, LBA Sector Address (Logical Setor
0)
|
0x1CA ~ 0x1CD
|
4
|
分區1總扇區數
|
Partition 1:Partition Length , Total Sectors in Partition
|
0x1CE
|
16
|
分區2扇區
|
Partition 2 Entry, (Defined as above)
|
0x1DE
|
16
|
分區3扇區
|
Partition 3 Entry, (Defined as above)
|
0x1EE
|
16
|
分區4扇區
|
Partition 4 Entry, (Defined as above)
|
0x1F0
|
12
|
保留
|
Reserved
|
01xFE
|
2
|
標籤
|
Signature AA 55
|
計算總扇區
MBR Sector 0:0x1CA ~ 0x1CD = [79 EF 3A 00]
Sector Size = 0x1C6 = 0x003AEF79 = 3862393
Capacity = 3862393 x 512 = 1977545216 = 1.97GB
計算引導扇區(DBR)起始位置
Sector 0:0x1C6 ~ 0x1c9 = [87 00 00 00]
DBR = 0x1C6 = 0x00000087 = 135
2. 引導扇區(DOS Boot Record / DBR):
在 FAT 檔案系統中,檔案系統的資料記錄在引導磁區中(DBR)中。DBR 的放置位址,可以在主引導記錄的 0x1C6 計算出 DBR 的物理位址(扇區=0x87=135),DBR是由 512 位元組組成,DBR 中記錄著檔案系統的起始位置、大小、FAT 表個數及大小等相關資訊,最後兩個位元組 “55,AA” 是分區的結束標誌。
SanDisk 2GB SD Card 引導扇區(DOS Boot Record / DBR) |
偏移
(位元組)
|
長度
|
說明 (DBR)
|
0x00
|
3
|
跳轉指令(跳過開頭一段區域)
|
0x03
|
8
|
OEM名稱(空格補齊)。MS-DOS檢查這個區域,以確定使用啟動記錄中的哪一部份資料 。常見值是IBM 3.3(在「IBM」和「3.3」之間有兩個空格)和MSDOS5.0.
|
0x0B
|
2
|
每個磁區的位元組數。基本輸入輸出系統參數塊從這裡開始。
|
0x0D
|
1
|
每叢集磁區數
|
0x0E
|
2
|
保留磁區數(包括啟動磁區)
|
0x10
|
1
|
FAT檔案分配表數目
|
0x11
|
2
|
最大根目錄條目個數
|
0x13
|
2
|
總磁區數(如果是0,就使用偏移0x20處的4位元組值)
|
0x15
|
1
|
介質描述
|
0xF8 單面、每面80磁軌、每磁軌9磁區
|
||
0xF9 雙面、每面80磁軌、每磁軌9磁區
|
||
0xFA 單面、每面80磁軌、每磁軌8磁區
|
||
0xFB 雙面、每面80磁軌、每磁軌8磁區
|
||
0xFC 單面、每面40磁軌、每磁軌9磁區
|
||
0xFD 雙面、每面40磁軌、每磁軌9磁區
|
||
0xFE 單面、每面40磁軌、每磁軌8磁區
|
||
0xFF 雙面、每面40磁軌、每磁軌8磁區
|
||
同樣的介質描述必須在重複複製到每份FAT的第一個位元組。有些作業系統(MSX-DOS
1.0版)全部忽略啟動磁區參數,而僅僅使用FAT的第一個位元組的介質描述確定檔案系統參數。
|
||
0x16
|
2
|
每個檔案分配表的磁區(FAT16)
|
0x18
|
2
|
每磁軌的磁區
|
0x1A
|
2
|
磁頭數
|
0x1C
|
4
|
隱藏磁區
|
0x20
|
4
|
總磁區數(如果超過65535,參見偏移0x13)
|
0x24
|
4
|
每個檔案分配表的磁區(FAT32)。擴充功能基本輸入輸出系統參數塊從這裡開始。
|
0x25
|
1
|
當前磁頭(FAT16)
|
0x26
|
1
|
簽名(FAT16)
|
0x27
|
4
|
ID(FAT16)
|
0x28
|
2
|
Flags(FAT32)
|
0x2A
|
2
|
版本號(FAT32)
|
0x2C
|
4
|
根目錄啟始叢集(FAT32)
|
0x2B
|
11
|
卷標(非FAT32)
|
0x30
|
2
|
FSInfo扇區(FAT32)
|
0x32
|
2
|
啟動扇區備份(FAT32)
|
0x34
|
12
|
保留未使用(FAT32)
|
0x36
|
8
|
FAT檔案系統類型(如FAT、FAT12、FAT16)
|
0x3E
|
2
|
作業系統自啟動程式碼
|
0x40
|
1
|
BIOS裝置代號(FAT32)
|
0x41
|
1
|
未使用(FAT32)
|
0x42
|
1
|
標記(FAT32)
|
0x43
|
4
|
卷序號(FAT32)
|
0x47
|
11
|
卷標(FAT32)
|
0x52
|
8
|
FAT檔案系統類型(FAT32)
|
0x1FE
|
2
|
磁區結束符(0x55
0xAA)
|
計算檔案配置表(FAT1)起始位置
DBR Sector 135:0x0E ~ 0x0F = [42 18]
Reserved Sector = 0x0E = 0x1842
FAT1起始位置 = 0x87 + 0x1842 = 135 + 6210
FAT1起始位置 = 0x18C9 = 6345
3. 檔案配置表(File Allocation Table / FAT):
FAT 檔案配置表是在 DBR + 保留分區後的位置,有兩個完全相同的 FAT(File Allocation Table, 檔案配置表)表單組成,FAT2 緊跟在 FAT1 之後,FAT 表(File Allocation Table)是一組與資料簇號對應的清單。
FAT 是按簇(2GB FAT32 格式,簇大小 4kB ~ 32kB)來分配記憶體空間,基本單位不是位元組而是簇(Cluster),即使某個檔只有一個位元組,作業系統也會給它分配一個最小單元:即一個簇。對於大檔,需要分配多個簇。同一個檔的資料並不一定完整地存放在磁片中一個連續地區域內,而往往會分若干段,像鏈子一樣存放。這種存儲方式稱為檔的鏈式存儲。為了實現檔的鏈式存儲,檔案系統必須準確地記錄哪些簇已經被檔佔用,還必須為每個已經佔用的簇指明存儲後繼的下一個簇的簇號,對於檔的最後一簇,則要指明本簇無後繼簇。這些都是由 FAT 表來保存的,FAT 表對應表項中記錄著它所代表的簇的有關資訊:諸如是空,是不是壞簇,是否是已經是某個檔的尾簇等。
SanDisk 2GB SD Card 檔案配置表(File Allocation Table / FAT) |
DBR Sector 135: DBR FAT 檔案分配表數目 = 0x10 = [02]
DBR每個 FAT檔案分配表的扇區 0x24 ~ 0x27 = [DF 73 00 00] = 0x000073DF
FAT2 起始位置 = FAT1 起始位置 + 每個 FAT 檔案分配表的扇區
FAT2起始位置 = 0x18C9 + 0x000073DF = 0x8CA8
= 6345 + 29663 = 36008
4. 根目錄(Root Directory):
根目錄(Root Directory)是位於資料區的開始區域,資料區時真正用於存放使用者資料的區域。資料區緊跟在 FAT2 之後,被劃分成一個個的簇。所有的簇從 2 開始進行編號,也就是說,2號簇的起始位置就是資料區的起始位置。目錄所在的磁區,都是以 32 Bytes 劃分為一個單位,每個單位稱為一個目錄項(Directory Entry ),即每個目錄項的長度都是 32 Bytes 。根目錄由若干個目錄項組成,一個目錄項佔用 32 個位元組,可以是長檔名目錄項、檔目錄項、子目錄項等。
SanDisk 2GB SD Card 根目錄(Root Directory) |
位元組偏移
|
長度
|
描述
|
|
0x00
|
8
|
DOS檔名(附加空格)
|
|
第一個位元組可以是下面的特殊數值:
|
|||
0x00
|
這個條目有用並且後面沒有被佔用條目
|
||
0x05
|
最初字元確實是 0xE5
|
||
0x2E
|
'點'條目;'.'或者'..'
|
||
0xE5
|
這個條目曾經被刪除不再有用。取消刪除文件工具作為取消刪除的一步必須使用一個正常的字元取代它。
|
||
0x08
|
3
|
DOS副檔名(空格補齊)
|
|
0x0b
|
1
|
文件內容
|
|
第一個位元組可以是下面一些特殊值:
|
|||
位
|
掩碼 + 描述
|
||
0
|
0x01 = 唯讀
|
||
1
|
0x02 = 隱藏
|
||
2
|
0x04 = 系統
|
||
3
|
0x08 = 卷標
|
||
4
|
0x10 = 子目錄
|
||
5
|
0x20 = 檔案
|
||
6
|
0x40 = 裝置(內部使用,磁碟上看不到)
|
||
7
|
0x80 = 沒有使用
|
||
內容值 0x0F 用來表示長檔名條目。
|
|||
0x0c
|
1
|
保留,NT使用(參見後面)
|
|
0x0d
|
1
|
建立時間,最小時間解析度:10ms單位,數值從 0 到 199。
|
|
0x0e
|
2
|
建立時間。小時、分鐘和秒根據後面的圖示描述進行編碼:
|
|
位
|
描述
|
||
15 - 11
|
小時(0-23)
|
||
10 - 5
|
分鐘(0-59)
|
||
4-0
|
秒/2(0-29)
|
||
注意秒只保存了2秒的解析度。更細解析度的文件建立時間在偏移
0x0d 處。
|
|||
0x10
|
2
|
建立日期。年、月和日根據後面的圖示編碼:
|
|
位
|
描述
|
||
15 - 9
|
年(0 = 1980, 127 = 2107)
|
||
8 - 5
|
月(1 = 1月,12 = 12月)
|
||
4-0
|
日(1 - 31)
|
||
0x12
|
2
|
最近存取時間;參見偏移0x0e處的描述。
|
|
0x14
|
2
|
FAT12 和 FAT16
中的 EA-Index(OS/2 和 NT使用),FAT32 中第一個叢集的兩個高位元組
|
|
0x16
|
2
|
最後更改時間;參見偏移 0x0e 處的描述。
|
|
0x18
|
2
|
最後更改日期; 參見偏移 0x10 處的描述。
|
|
0x1a
|
2
|
FAT12 和
FAT16 中的第一個叢集。FAT32 中第一個叢集的兩個低位元組。
|
|
0x1c
|
4
|
文件大小
|
計算根目錄(Root Directory)起始位置
DBR Sector 135: DBR FAT檔案分配表數目 = 0x10 = [02]
DBR每個 FAT 檔案分配表的扇區 0x24 ~ 0x27 = [DF 73 00 00] = 0x000073DF
根目錄起始位置 = FAT2 起始位置 + 每個 FAT 檔案分配表的扇區
根目錄起始位置 = 0x8CA8 + 0x000073DF = 0x10087
= 36008 + 29663 = 65671
2017年 11月 29日 天氣報告
氣溫:22.5度 @ 22:30
相對濕度:百分之 85%
天氣:大致多雲