//Logo Image
作者:鄭智銘(2005-03-11);推薦:吳昌暉、徐業良(2005-04-28)

PIC_SERVER教材(11)-使用MMC記憶卡

本文介紹PIC_SERVER如何將資料寫入MMC記憶卡,以及讀取MMC卡中數據資料的方式。MMC記憶卡可以視為PIC_SERVER系統中的小硬碟,市售MMC記憶卡可以達到1GB甚至更高的儲存容量。

1.     MMC簡介

MMC(MultiMediaCard)記憶卡是目前市售標準化的記憶卡之一,外觀如圖1所示,背面共有7 pin接腳控制資料的讀取與寫入,外型尺寸為32mm×24mm×1.4mm1998114家公司聯合成立了MMC協會(MultiMediaCard Association, MMCA),規範了MMC的各項性能規格,如MMCA2003年公布的“Multi MediaCard System Specification Version 3.31”,內容定義MMC各項規格、使用方式與傳輸協定等,本文所描述的各項MMC資料均節錄自此標準中。

1. MMC卡外觀

1.1 MMC內部結構

2MMC內部構造示意圖,可以發現MMC記憶卡中,不但包含了記憶單元,連控制器也包含於記憶卡中,因此使用者不需要瞭解MMC內部通訊與儲存的機制,僅需要控制外部的7pin腳,給於符合MMC記憶卡可以接受的通訊協定,便能進行資料的寫入或讀取。也就是說,就算你手上只有一片MMC記憶卡,不需要其他裝置與設備,只要能在pin腳上依據MMC記憶卡可以接受的通訊協定輸入電壓訊號,便能控制MMC卡。

2. MMC內部構造示意圖

1.2 MMC/SPI通訊協定與接腳定義

MMC記憶卡在Version 3.31標準中載明所接受的傳輸協定有MMC模式與SPI模式兩種,表1MMCSPI模式中接腳定義的比較。

1. MMCSPI模式的接腳定義

MMCSPI模式相同之處為346號接腳均為電源,5號均為時脈訊號。而不同之處在於SPI模式中2號接腳固定為資料輸入,7號接腳固定為資料輸出,但在MMC模式中2號為命令與回應,7號為資料訊號。此外1號接腳MMC模式中不需使用,而SPI模式中則必須使用來選擇記憶卡(選定該卡工作時CS為低電位)。

在功能上MMC模式可以定址64,000MMC卡位置,且能多重區塊讀寫,而SPI模式僅能靠CS訊號線選擇使用少量MMC卡、單一區塊讀寫。雖然MMC模式功能較強大,但是對PIC_SERVER而言僅需一片或少量的MMC記憶卡數目與單一區塊讀寫,且SPI模式的通訊協定較MMC模式簡單,因此目前PIC_SERVER所使用的模式為SPI模式。

2.     PIC_SERVER使用MMC的硬體裝置

2.1 MMC記憶卡的外部接腳

MMC記憶卡外部的7個接腳順序如圖3所示,從MMC記憶卡缺口處開始依序為編號1~7MMC卡腳位所對應的PIC_SERVER接腳如表2所示,對應接腳的相關資訊在pic_SERVER_mmc.c檔案中可以看到其設定。特別要提醒的是,MMC_Dout(編號7資料輸出接腳)與PIC接腳間要串連2kW電阻隔離,才能與LCDRTL8019 共存,而5VGND地線之間,建議可以加上一個電容防止干擾。另外值得注意的是,MMC記憶卡上編號36原本就是相通的(可以用電表試著檢查看看),因此使用時僅需接通其中一個接腳便可以。

3. MMC接腳順序

2. MMC卡接腳定義與所對應的PIC_SERVER接腳位置

編號

MMC卡接腳定義

PIC_SERVER所對應接腳位置

1

CS

RC5

2

DI

RD0

3

VSS

GND

4

VDD

5V

5

SCLK

RB2

6

VSS2

GND

7

DO

RD1

2.2 MMC卡插槽模組與固定板

目前PIC_SERVER擴充MMC功能的硬體介面是市售可抽換MMC卡的插槽模組,以及3425實驗室所設計的固定板。圖4(a)是在一般電子材料行均可以買到MMC的插槽模組,插槽模組以金屬片接觸方式導通MMC卡上7個訊號接腳,並導引至後部方便焊接與固定。圖4(b)3425實驗室所設計的MMC插槽固定板,針對MMC插槽模組尺寸與外觀設計,兩者結合後如圖5所示,將MMC各接腳導通至CN1排針孔上,可以焊接上適當的排針,方便焊接與固定於電路板上。

4. MMC插槽模組(a)與固定板(b)

5. MMC插槽模組與固定板組合後排針定義(最後一個GND不需使用)

如前所述,MMC卡上編號3與排針編號6為相通的GND,僅需連接其中一個接腳。為了使用方便,MMC接腳導引至固定板上後,將MMC接腳編號6與編號7的順序交換,因此固定板上僅需使用CN1(1)~(6)排針孔便可以了。固定板上排針孔所對應PIC_SERVER接腳如表3與圖5所示。

3. 固定板排針與PIC_SERVER對應接腳

固定板排針編號

(1)

(2)

(3)

(4)

(5)

(6)

(7)

PIC_SERVER所對應接腳位置

RC5

RD0

GND

5V

RB2

RD1

GND(x)

2.3 PIC_SERVER上所對應的接腳

6所示為PIC_SERVER使用MMC模組固定板時所對應的接腳位置,僅需使用(1)~(6)的排針孔,位置如圖6中所示。使用時建議可以將MMC模組固定板固定在PIC_SERVER所預留的空位處,如圖7所示,所需的訊號線則在電路板背面走線,儘量不影響PIC_SERVER正面其他功能的使用。

6. PIC_SERVER 使用MMC模組所對應接腳位置

7. PIC_SERVER搭配MMC插槽模組

3.     MMC記憶卡基本讀寫方式

3.1 MMC的基本記憶單位

MMC記憶卡最基本的儲存單位為8 bit(0~255)的位元組,若超過255的數字則必須佔用兩個儲存單位以16 bit(0~65536)來表示,這裡先以最基本的8 bit位元組說明。

MMC卡中每512個位元組構成一個sector1024個位元組檔案大小為1k byte,故1Mb大小的記憶卡可以儲存1×1024×1024=1,048,576個位元組。圖8所示為512個位元組構成的一個sector,一個1MbMMC記憶卡會有2048個如圖8大小的sector,依序排列下去。

MMC卡中每次讀∕寫時會處理一整個sector512個位元組)的資料,此為MMC讀∕寫的基本單位。圖8為一個全新的MMC卡,內部512個初始值全都為0,圖9則為我們寫入一個數字9時,可以發現雖然只有第一個數字被寫入9,但是sector中其他的位元組全都被塗寫成FF(十六進位,代表255),而下一個sector則不受影響,使用時必須謹記這一項特點,不然所記憶的數字會被搞亂。

8. MMC卡中一個sector的記憶區塊大小示意圖

9. 讀∕寫MMC卡時,以一個sector為基本單位

3.2 MMC讀取∕寫入步驟與相關指令

10PIC_SERVER使用MMC基礎程式,功能為寫入一個數字至特定位置,並從特定位置讀出一個數字。PIC_SERVER使用使用MMC功能時在前端標頭檔必須要定義“I_WANT_MMC_MEMORY  1”,啟動MMC功能。而在主程式中必須使用內建函式mmc_init_spi()進行MMC功能初始化的工作,並指定使用SPI模式進行MMC卡的傳輸協定。

10. PIC_SERVER使用MMC基礎程式

PIC_SERVER使用MMC時,以一個32bit的整數表示在MMC卡中的記憶體位置,然後下達讀出或寫入的指令。圖10程式定義mmc_write_addr以及mmc_read_addr兩個32bit的整數變數,作為寫入與讀出的起始位置,並定義一個8bit的整數變數mmc_data為讀寫的資料。寫入MMC卡的步驟如下:

(1)   開啟寫入位置(使用int32的參數,只能指定512的倍數作為寫入的起始點);

(2)   依序寫入數字(可以一直連續寫入,大量資料寫入橫跨數個sector也可以);

(3)   關閉。

讀取MMC卡的步驟為:

(1)   指定讀出位置(只能指定512的倍數);

(2)   依序讀出數字(可以一直連續讀出,就算讀取大量橫跨數個sector也可以);

(3)   關閉。

10主程式中首先使用內建函式mmc_check_error()檢查MMC是否正常工作,若有錯誤便停止。接著指定寫入一個數值100MMC中記憶體位置81920處,隨後指定從81920位置讀出一個數值,並定義此數值給mmc_data,最後印出此數值至終端機。PIC_SERVER使用MMC功能各項指令說明詳如表4,各項指令功能可以在pic_SERVER_mmc.c裡面查詢,表5MMC錯誤代碼(mmc.error_code)意義。

特別注意MMC卡讀取或寫入的起始位置,必須為512的倍數,然後依序讀出或寫入。舉例來說,有一串資料從81920的記憶位置開始為1, 2, 3, 4, 5, 6, 7, 8, 9, 10…,想讀取第三個位置的數字時無法直接開啟mmc_open(81922, 'r'),只能從mmc_open(81920, 'r')位置開啟,並且依序讀出x1=read_mmc()x2=read_mmc()x3=read_mmc(),最後變數x3所讀出的數字則為我們想要的數值。

4. MMC各項功能指令

指令

說明

int8 mmc_open (int32 addr, int8 mode)

setup address for read / write

mmc_open(0x00030000,'w') for write

mmc_open(0x00030000,'r') for read

address must be a multiple of 512 !

int32數值表示開啟位置,必須為512的倍數。後面mode填入’w’代表寫入、’r’代表讀出。

int8 mmc_write(int8 data)

write a byte to   MMC

寫入一個byte的數值至MMC,如:mmc_write(100)

int8 mmc_write_int16(int16 x)

write 2 byte to MMC, low byte first

若數值大於255,使用int16格式,會被拆解成兩個部分佔用兩個位置,寫入2byte進入MMC

int8 read_mmc(void)

read a byte from MMC

讀出一個byte的數值,若要讀取int16的數值必須連續讀出兩個byte,再加以組合成int16數值

int8 mmc_close(void)

close 512 byte block read/write  with  auto flush when needed。關閉MMC

void mmc_check_error();

檢查MMC狀態是否有錯誤,若有錯誤,printf(" MMC_Error_%u ", mmc.error_code )。除了讀出指令read_mmc()之外,其他MMC功能指令執行時若有錯誤均會回傳錯誤代碼

mmc.error_code

MMC錯誤代碼,各代碼意義如表5所示

5. MMC錯誤代碼意義

mmc.error_code

錯誤代碼意義

0

正常

1

初始化發生錯誤

2

開啟寫入位置時發生錯誤

3

開啟讀出位置時發生錯誤

4

寫入位置沒有正常開啟

5

讀出位置沒有正常開啟

6

寫入時發生錯誤

4.     MMC記憶卡檔案管理

4.1 MMC記憶卡FAT格式化

PIC_SERVER使用MMC卡時,可以將MMC卡視為“序列式的讀寫(sequential read/write)”的儲存媒體,像錄音帶一樣。例如8Mb大小的MMC卡裡面有8×1024×1024=8,388,608個位元組可以儲存,儲存時就是依序填入此連續空格。使用者可以指定從某個位置開始記錄或讀取,只要這個起始位置是512的倍數,但此種方式對於資料管理並不方便,使用者可能希望能像一般電腦作業系統將資料分成不同檔案管理,且能用一般個人電腦讀取所儲存資料。

一般電腦Windows作業系統只能認得FAT檔案格式與NTFS檔案格式的儲存媒體,其中FAT檔案格式是沿用自DOS時代、廣為採用的檔案格式。如果PIC_SERVER不考慮使用FAT格式的MMC卡,也就是說,此張MMC卡的儲存資料僅能被PIC_SERVER讀取與寫入、不考慮使用電腦讀取的情況下,MMC卡的規劃是最單純的。例如8MbMMC卡,從0~8,388,608的位置都可以任意寫入或讀出(只要指定寫入或讀取起始位置為512的倍數)。

若希望PIC_SERVER所寫入MMC卡的資料能夠被Windows作業系統讀出,則必須要使用市售的讀卡機先將MMC卡格式化為FAT16的格式。在此要特別注意的是,格式化成FAT16格式後,MMC卡會規劃出一個區間放置FAT16檔案配置表的內容,此區間的大小隨著格式化所使用的作業系統而不同,經過測試Windows 2000系統會佔用80384字元,而Windows XP系統會佔用81920字元。如圖11所示為以Windows XP所格式化的MMC卡,前端81920字元區間規劃為FAT檔案配置表。

FAT格式化的目的只是為了可以在Windows作業系統中可以讀出,PIC_SERVER寫入與讀出與MMC卡有沒有經過FAT格式化以及FAT配置表完全無關,均是以指定底層記憶體位置的方式。要特別注意的是,PIC_SERVER在經過FAT格式化的MMC卡寫入資料時,一定要避開前面FAT檔案配置表的記憶體區塊,如果不小心寫入,會讓整個FAT配置表錯亂,Windows系統便無法讀取裡面的檔案(但是對PIC_SERVER的讀取與寫入仍然沒有任何影響)。

11. MMC格式化為FAT16格式(使用Windows XP

4.2 MMC卡中放入空白預建檔

格式化MMC卡後,隨後便能依序放入空白預建檔,注意要“依序放入”檔案才會使各檔案所佔用的記憶體空間是依序排列下去。如圖12所示,依序放入檔名為01.DAT02.DAT03.DAT04.DAT05.DAT516kb大小的空白預建檔案,所佔用的空間便會依據排列下去。使用者可以放入所需任意大小的空白預建檔,每個預建檔會依照放入的順序佔用記憶體空間。

12. MMC卡內各檔案所使用的記憶體位置

使用者可以建立一個批次檔(bat)自動執行上述MMC卡格式化與依序置入檔案的步驟。建立方式僅需以windows內建的筆記本,建立內容如圖13txt文件檔,完成後將附檔名更改為.bat檔,便可以以滑鼠按下執行。例如圖13批次檔的內容,便是將電腦接上讀卡機,插入32MBMMC卡並規劃為I槽,依序放入01.dat~05.dat516kb大小的檔案。注意要先在PC硬碟上預建好01.dat~05.dat516kb大小的空白檔案,並和此批次檔放在同一路徑下,如此拷貝空白預建檔時不需指定來源路徑,而拷貝目標路徑為IMMC卡。點擊執行批次檔後,便會自動格式化I槽的MMC卡,並且依序置入01.DAT~05.DAT檔案,並將此張MMC卡命名為MMC_32MB

如圖14所示,批次檔執行完畢後可以看到MMC卡面有拷貝進去的01.DAT~05.DAT五個空白的預建檔。使用者可以用UltraEdit 32等軟體讀出MMC卡中空白預建檔的內容,UltraEdit32啟用Hex Edit功能顯示的檔案內容,會自動標示游標所在位置的記憶體位置,非常方便。如圖15所示藍色游標處為511的位置(1ff16進位的表示法,代表511),從0~511恰好為一個sector的大小。

13. 格式化MMC與置入預建檔的批次檔內容

14. MMC卡中所包含的五個空白預建檔

15. 使用UltraEdit32 開啟MMC內檔案

4.3 檔案寫入與讀出

完成格式化與預建檔放置的工作後,便可以將此張MMC卡放入PIC_SERVERMMC插槽使用。使用方式與指令與3.2節敘述完全相同,不會因為MMC經過格式化而不同,但必須注意的是,必須避開0~81919的位置,因為這個區塊已經用來放置FAT檔案配置表。

例如執行圖10程式寫入一個數值10081920的位置,81920恰巧為第一個檔案01.DAT的起始位置,因此將01.DAT開啟後可以看到第一個位置被更改為64(十六進位,代表十進位數值的100)如圖16所示。而如前文所述,這個sector的其他511個數值均被塗寫成FF(十六進位,代表十進位數值的255),而下一個sector的數值則不受影響,均仍然為0

16. 基礎程式將數值100寫入MMC

5.     實例應用-從遠端讀取MMC卡內容

在這個應用實例中PIC_SERVER裝置一張已經儲存資料的MMC卡,資料內容在81920位置為數字082432位置為數字182944位置為數字2、…,以此類推,每隔512位置儲存一個數字,共儲存0~79的數字。這裡要撰寫PIC_SERVERC程式,使得在遠端網頁在輸入指令及MMC卡記憶位置後,便可控制PIC_SERVER讀取MMC卡該記憶位置的資料數值,傳送至遠端網頁呈現。例如輸入A0000081920字串,網頁會顯示數值0,輸入A0000082432字串網頁會顯示數值1,以此類推。

1718為此實例應用之PIC_SERVERC程式,此處僅列出主程式部分(圖17)及PIC_SERVER接受遠端控制命令及傳輸資料回遠端的兩個call_back程式(圖18)。圖1718的程式架構,與PIC_SERVER教材(8)中的遠端校調系統時鐘的範例程式十分類似。圖17主程式中為不斷地執行HTTP伺服器,每秒閃爍一次LED,如果遠端有指令送進來,則會開始執行Callback程式。圖18Callback程式中,如果遠端傳來指令符合A0000000000的格式,PIC_SERVER會將後面的數字字串換算成MMC記憶體位置(mmc_read_addr),並且記錄於block_1_data[0],僅需在動態網頁egi中以動態egi@a即可顯示此數值。實際測試結果從遠端網頁輸入A000081920~A0000122880指令,網頁會顯示0~79MMC卡內資料數值。

17. 應用實例主程式

18. 應用實例call_back程式