將會使用 Microchip PIC18F4550 的 SPI 模式,在 SPI 模式中,所有的指令都要求先將 CS 腳置 0 (低電位)。命令格式是個一個字節的命令格式為 01xx xxxx 後六位是 CMD 後面的數字的二進制值,如 CMD1=0100 0001=0x41。需要註意初始化時SPI速率不能超過 400K。
▲SD 記憶卡初始化程式流程圖 |
▲Secure Digital 卡內的存儲器 |
▲Secure Digital 卡的 CMD指令 |
CMD8 — 參數是 0x000001AA,判斷 SD 卡符合哪個標準。如果返回 ILLEGAL COMMAND,說明是 ver1.x 的卡,否則就是 ver2.0 的卡。
CMD1 — 如果是 ver2.0 的卡,參數是 1<<30,否則就是 0,讀取 SD 卡的狀態,反復,直到 CARD IS READY 或者超時。這裏有一個問題,Spec上建議使用 ACMD1,說是通用性比 CMD1 好,而且 CMD1 並不是一開始就可以使用的。但是我在實際使用中,發現一些老卡對這個指令會返回 PARAMETER ERROR。搞不懂是為什麼,而且實際使用中 CMD1 也很好用,並沒有出現 SD 卡不能初始化的問題,所以我現在都直接用 CMD1。
▲Secure Digital 卡識別模式的狀態圖 |
2. 讀取CID(CMD10)
SD 卡鑒別資訊,這一步不是必須的。鑒別資訊中包括了生產商 ID,應用 ID,產品名稱,產品版本,產品序列號,生產日期。
名稱 | 域 | 數據寬度 | CID劃分 |
生產標識號 | MID | 8 | [127:120] |
OEM/應用標識 | OID | 16 | [119:104] |
產品名稱 | PNM | 40 | [103:64] |
產品版本 | PRV | 8 | [63:56] |
產品序列號 | PSN | 32 | [55:24] |
保留 | - | 4 | [23:20] |
生產日期 | MDT | 12 | [19:8] |
CRC7校驗合 | CRC | 7 | [7:1] |
未使用,始終為1 | - | 1 | [0:0] |
3. 讀取CSD(CMD9),SD卡信息
返回的 CSD 有兩個版本。
名稱 | 域 | 數據寬度 | 單元類型 | CSD劃分 |
CSD結構 | CSD_STRUCTURE | 2 | R | [127:126] |
保留 | - | 6 | R | [125:120] |
資料讀取時間1 | TAAC | 8 | R | [119:112] |
資料在CLK週期內讀取時間2(NSAC*100) | NSAC | 8 | R | [111:104] |
最大資料傳輸率 | TRAN_SPEED | 8 | R | [103:96] |
卡命令集合 | CCC | 12 | R | [95:84] |
最大讀取資料塊長 | READ_BL_LEN | 4 | R | [83:80] |
允許讀的部分塊 | READ_BL_PARTIAL | 1 | R | [79:79] |
非線寫塊 | WRITE_BLK_MISALIGN | 1 | R | [78:78] |
非線讀塊 | READ_BLK_MISALIGN | 1 | R | [77:77] |
DSR條件 | DSR_IMP | 1 | R | [76:76] |
保留 | - | 2 | R | [75:74] |
設備容量 | C_SIZE | 12 | R | [73:62] |
最大讀取電流@VDD min | VDD_R_CURR_MIN | 3 | R | [61:59] |
最大讀取電流@VDD max | VDD_R_CURR_MAX | 3 | R | [58:56] |
最大寫電流@VDD min | VDD_W_CURR_MIN | 3 | R | [55:53] |
最大寫電流@VDD max | VDD_W_CURR_MAX | 3 | R | [52:50] |
設備容量乘子 | C_SIZE_MULT | 3 | R | [49:47] |
擦除單塊使能 | ERASE_BLK_EN | 1 | R | [46:46] |
擦除磁區大小 | SECTOR_SIZE | 7 | R | [45:39] |
防寫群大小 | WP_GRP_SIZE | 7 | R | [38:32] |
防寫群使能 | WP_GRP_ENABLE | 1 | R | [31:31] |
保留 | - | 2 | R | [30:29] |
寫速度因數 | R2W_FACTOR | 3 | R | [28:26] |
最大寫資料塊長度 | WRITE_BL_LEN | 4 | R | [25:22] |
允許寫的部分部 | WRITE_BL_PARTIAL | 1 | R | [21:21] |
保留 | - | 5 | R | [20:16] |
檔系統群 | FILE_OFRMAT_GRP | 1 | R/W | [15:15] |
拷貝標誌 | COPY | 1 | R/W | [14:14] |
永久防寫 | PERM_WRITE_PROTECT | 1 | R/W | [13:13] |
暫時防寫 | TMP_WRITE_PROTECT | 1 | R/W | [12:12] |
檔系統 | FIL_FORMAT | 2 | R/W | [11:10] |
保留 | - | 2 | R/W | [9:8] |
CRC | CRC | 7 | R/W | [7:1] |
未用,始終為1 | - | 1 | [0:0] |
if (CSD[0] & 0x40 == 0x40) // ver2.0的卡容量 = 1024L*(CSD[8]<<8+CSD[9])這個數字就是這張SD卡裏面總共有多少個磁區。
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 卡的磁區0到buffer如果buf[0] 不是 0xEB 或者 0xE9,說明這是一個分區表。buf[454] 開始的四個 byte是該分區前的磁區數。例如 63 表示在這個分區前有 63 個磁區,那麼這個分區的第一個磁區就是磁區 63。buf[458] 開始的四個 byte 是該分區的磁區數。例如 7990000,不是這個分區有 7990000 個磁區。那麼這個分區的塊位址就是 63~7990063。一個設備可以最多有四個分區,其他三個分區的相關資料是在buf[470]/buf[474],buf[486]/buf[490],buf[502]/buf[506]。注意,讀取 buf 的時候檢查最好兩位,應該是 55AA。
5. 讀取BPB
已經知道第一個分區是在什麼位置了,現在需要做的就是讀取這個分區的 0 磁區。也就是 SD 卡的第 36 個磁區。這個 512 個 byte 就是這個分區的詳細資料了。檢查buf[0],應該是 0xEB 或者 0xE9。如果是的話,那就是 BPB 表了。接下來比較重要的幾個數字是:
buf[13]的Sectors Per Cluster,就是每個簇的磁區數,也就是你在讀取檔是需要一次讀取的磁區數。例如 8。
buf[14-15] 的 Reserved Sectors,保留磁區數,這個保留磁區是在分區第一個磁區到 FAT 表之間的磁區數。例如38。
buf[16],FAT表數,一般是2。
buf[19-20] 和 buf[32-35],前者是 FAT16 格式中的磁區數,後者是 FAT32 格式中的磁區數。這個值在分區表裏也是有的。就是 7990000。
buf[22-23],buf[36-39],FAT 表佔用的磁區數,前者是 FAT16 的,後者是 FAT32 的。例如 7793。
buf[28-31] 的 Hidden Sectors,隱藏磁區數,這個隱藏磁區指的是在這個分區前面有多少個磁區,這個值在分區表裏也有的。就是 63。
好了,到這裏我們就可以讀取 FAT 檔系統中的資料了。
6. 讀取FAT表
在上面的例子中,FAT 表的位置應該是分區的第一個磁區再偏移隱藏磁區數,就是63+38,等於 101。所以從 SD 卡的 101 磁區開始,就是分區一的 FAT 表,一共有 7793 個磁區。
7. 讀取根目錄
在 FAT16 中,根目錄是單獨的。應該是可以建立 512 個檔,每個檔佔用 32byte,所以總共是 512*32/512=32 個磁區。
根目錄是跟在 FAT 表後面的,所以第一個磁區是在 101+7793*2=15687。對於 FAT32 系統,這段忽略。
8. 讀取數據區
FAT16 中,資料區是在根目錄後面的,所以第一個磁區是 15687+32=15719。就是在SD 卡上的第 15719 個磁區。
而 FAT32 中,由於沒有根目錄,所以資料區直接跟在FAT表後面的,所以就是第 15687 個磁區。這個磁區就是 LBA=2 的地方。所以之後如果上層的檔操作函數,要對 LBA=1000 寫資料,那就是對 1000+15687=16687 磁區進行寫操作。到此,我們就得到了整個 FAT 系統的結構和資料,接下來就可以開始操作檔了。
參考網址:http://blog.sina.com.cn/s/blog_44153f8f0100eq0u.html
相關網址:
※ DIY - PIC:SD 記憶卡規格 (七十)
※ DIY - PIC: FAT 表檔案配置表種類 (七十一)
※ DIY - PIC:SD 記憶卡 FAT 表 (七十二)
※ DIY - PIC:SD 記憶卡初始化 (七十三)
※ DIY - PIC:PIC18F4550 SD 記憶卡電路 (七十四)
※ DIY - PIC:PIC18F4550 SD 記憶卡穩壓電路 (七十五)
※ DIY - PIC:PIC18F4550 SD 記憶卡程式 (七十六)
※ DIY - PIC:PIC18F4550 MCHPMSD 實驗板 (七十七)
※ DIY - PIC:PIC18F4550 MCHPMSD 程式介紹 (七十八)
※ DIY - PIC:PIC18F4550 MCHPMSD 編程開始 (七十九)
※ DIY - PIC:PIC18F4550 MCHPMSD 初始化 (八十)
※ DIY - PIC:PIC18F4550 MCHPMSD 讀取 SD 記憶卡程式 (八十一)
※ DIY - PIC:PIC18F4550 MCHPMSD 寫入 SD 記憶卡程式 (八十二)
※ DIY - PIC:PIC18F4550 MCHPMSD SD 記憶卡程式 (八十三)
相關網址:
※ SD 記憶卡
※ SDHC 記憶卡
※ SDXC 記憶卡
2011年 5月 21日 天氣報告
氣溫:24.5 度 @ 22:00
相對濕度:百分之96%
天氣:微雨
沒有留言:
張貼留言