//Logo Image
作者:陳明周(2004-04-01);推薦:徐業良(2004-04-05)

以單晶片PIC16f877將資料寫入MMC模組使用說明

在單晶片的應用中,資料無法儲存是常會碰到的問題,解決的方法包括有增加EEPROM或使用Flash memoryEEPROM的儲存空間較小,因此若有大量的資料需要儲存時,Flash memory是最迅速有效的方法,同時它的後續的處理也很方便,只需要一台讀卡機就可以將資料輸入電腦。本文即在介紹使用單晶片PIC16f877將資料寫入Multi Media Card (MMC)的方式。本文中所提及之軟硬體解決方案均由元智大學3425機電整合實驗室提供。

1.     MMC簡介

MMCMulti Media CardInfineon(原西門子公司記憶事業部)和SanDisk公司在1997年推出,並於1998年標準化,MMC的發展目標主要是針對數碼影像、音樂、手機、PDA、電子書、玩具等産品。MMC的外觀如圖1所示,體積為32mm×24mm×1.4mm,重量1.5公克

1. Pretec Multimedia Card 32MB

MMC儲存卡可以分爲MMCSPI兩種工作模式,MMC模式是標準模式,具有MMC的全部特性。而SPI模式則是MMC儲存卡可選擇的第二種模式,這個模式的性能較不如MMC模式,但只需要4支接腳即可進行讀寫的控制,因此本MMC模組所採用的即為SPI模式。MMC是一種低成本的資料平臺和通訊介質,它的介面設計非常簡單,只有7接腳,介面成本低於0.5美元。資料傳送只需3支接腳的串列匯流排即可(SPI模式再加上1針用於選擇晶片)。低成本的串列匯流排時鐘頻率可達20MHz,操作電壓爲2.7V3.6V,寫∕讀電流只有27mA23mA,功耗很低。

本文將先介紹MMC接腳與PIC間的對應關係,以及MMC在使用前應如何格式化,再以實際的例子說明PIC將資料寫入與讀出的程式指令。由於PIC存入MMC內的資料為二進位格式,因此以讀卡機輸入電腦後,必需由Matlab搭配相關指令將其轉換為十進位,本文最後將會介紹這個過程的進行方式。

2.     接腳說明與前置作業

2.1  MMCPIC之接腳對應

MMCPIC的接腳對應如表1所示。注意MMC_DoutLCD和網路卡同時共用PICRB3接腳,因此必需串連一個1kW的電阻隔離,才能彼此共存。另一個注意的重點,是MMC電源正常為2.7~3.6V,而PIC電源為5V,因此有燒壞的可能。同時有些廠牌的MMC可能無法使用,選購時需注意,目前已知可使用的廠牌有PretecApacer

1. MMCPIC接腳對應

MMC_PIN

PIC_PROTO

PIC_SERVER

腳位

腳位說明

對應接腳

對應接腳

1. MMC_SEL

active low

RC4

RD1

2. MMC_Din

data, host to MMC

RC3

RD0

3. GND

 

GND

GND

4. Vdd

2.7~3.6V

Vdd

Vdd

5. MMC_CLK

clock專線

RB 3

RC5

6. GND

 

GND

GND

7. MMC_Dout

data, MMC to host

RB2

RD2

2.2  MMC前置作業

使用MMC的前置作業包括將MMC格式化為FAT格式,以及將特定檔案複製於MMC中。PIC將資料寫入MMC時,MMC內需要有一個特定格式的檔案承接PIC寫入的資料,目前已預建有ecg_1k.datecg_4k.datecg_16k.datecg_64k.dat、…、ecg_16MB.dat…等檔案(上述檔名可自行更改,不影響效果),將上述檔案依序複製至MMC中,即可承接PIC所寫入的資訊。需特別注意「依序」這個步驟,原因為PIC寫入時需指定寫入的位址,但若複製時若未照順序則各檔案的起始點位址就會與預設不同,這樣會造成程式撰寫上很大的困擾。不過使用者當然也可以依照自已的需求建立不同大小或數量的預建檔放入MMC中,只需要再自行計算出該檔案的起始位址即可,此處只是提供一個較為通用的方式,在MMC中放入各種size的預建檔,使用者可依照需求選擇大小適當的區塊儲存。

上述流程可由一個批次檔簡化,方式為開啟一個純文字檔,輸入表2中的指令後將副檔名改為.bat即可雙擊滑鼠執行。表2是以一張容量為32MBMMC為範例;若使用16MBMMC,則將最下一行指令「copy ecg_16MB.dat    L:\」刪除即可。

2. 批次檔範例及說明

format L: /FS:FAT /A:2048 /V:MMC_32MB

copy ecg_1k.dat          L:\

copy ecg_4k.dat          L:\

copy ecg_16k.dat        L:\

copy ecg_64k.dat        L:\

copy ecg_256k.dat L:\

copy ecg_1MB.dat L:\

copy ecg_4MB.dat L:\

copy ecg_8MB.dat L:\

copy ecg_16MB.dat    L:\

說明:

FORMAT 磁碟機 [/FS:檔案-系統] [/V:標籤] [/Q] [/A:大小] [/C] [/X]

磁碟機                    指定磁碟機代號,本範例讀卡機的磁碟代號為L碟。

/FS:filesystem           指定檔案系統的類型 (FATFAT32 NTFS)

/A:size                      覆寫預設的配置單位大小。建議一般使用時,最好使用預設設定。

/V:label                     指定磁碟區標記,可自行更改。

copy ecg_1k.dat       L:\      ecg_1k.dat複製至MMC磁碟中

檔案複製至MMC後,依照不同的作業系統,預建檔會有不同的起始位置,請查表3、表4。假設作業系統為Win_XP,寫入MMC卡的起始位址指定為0x001 4000(表32列),資訊就會寫入ecg_1k.dat區塊中,待該區塊寫滿後再依序填入後面的區塊。目前目前釋出的MMC驅動程式,所能儲存的變數格式為8位元或16位元,表中的size即表示該區塊所能儲存的8位元變數個數,如ecg_4k.dat區塊能儲存40968位元的變數,若儲存的變數為16位元,則可儲存的變數個數減半成為2048個。

若使用者選擇自行放入預建檔的方式,則需要計算檔案的起始位址,以Win_XP作業系統為例,對MMC執行格式化後,資料會以0x0001 4000為起始點開始寫入(表3第二列),因此第一個複製進入的檔案就會以這個位址為起始點,將這個起始點加上第一個複製進入的檔案所佔記憶體空間,就會是第二個檔案的起始位址,餘下類推。以表3ecg_1k.dat為例,它的起始位址(0x0001 4000)再加上磁碟空間(0x0000 0800),即為下一個檔案ecg_4k.dat的起始位址(0x0001 4800),餘下類推,了解之後就可以建立適合自已的MMC區塊。

3. Win_XP MMC檔案位置

檔名

size

佔用磁碟空間

磁碟空間

起始位址

ecg_1k.dat

46

2048 x 1

0x0000 0800

0x0001 4000

ecg_4k.dat

4096

2048 x 2

0x0000 1000

0x0001 4800

ecg_16k.dat

16384

2048 x 8

0x0000 4000

0x0001 5800

ecg_64k.dat

65536

2048 x 32

0x0001 0000

0x0001 9800

ecg_256k.dat

262144

2048 x 128

0x0004 0000

0x0002 9800

ecg_1MB.dat

1048576

2048 x 512

0x0010 0000

0x0006 9800

ecg_4MB.dat

4194304

2048 x 2048

0x0040 0000

0x0016 9800

ecg_8MB.dat

8388608

2048 x 4096

0x0080 0000

0x0056 9800

ecg_16MB.dat

16777216

2048 x 8192

0x0100 0000

0x00d6 9800

4. Win_2000 MMC檔案位置

檔名

size

佔用磁碟空間

磁碟空間

起始位址

ecg_1k.dat

46

2048 x 1

0x0000 0800

0x0001 3a00

ecg_4k.dat

4096

2048 x 2

0x0000 1000

0x0001 4200

ecg_16k.dat

16384

2048 x 8

0x0000 4000

0x0001 5200

ecg_64k.dat

65536

2048 x 32

0x0001 0000

0x0001 9200

ecg_256k.dat

262144

2048 x 128

0x0004 0000

0x0002 9200

ecg_1MB.dat

1048576

2048 x 512

0x0010 0000

0x0006 9200

ecg_4MB.dat

4194304

2048 x 2048

0x0040 0000

0x0016 9200

ecg_8MB.dat

8388608

2048 x 4096

0x0080 0000

0x0056 9200

ecg_16MB.dat

16777216

2048 x 8192

0x0100 0000

0x00d6 9200

3.     MMC程式說明

接下來正式介紹如何將如何將資料寫入MMC,首先在程式的開始先引用「yz_mmc.c」檔,即可在程式中呼叫MMC的相關指令,目前規劃的MMC指令集共有7個指令,分別用於初始設定、指定位址、讀取寫入和錯誤檢查,表5將其列出並簡單說明,而其中的錯誤檢查會回傳7種可能,如表6所示。後面再以實際的程式範例做說明如何使用。

5. MMC指令集

指令

說明

mmc_init_spi(void);

設定MMC初始狀態為SPI模式

mmc_open(int32 addr );

設定寫入或是讀取的起始位址

mc_close(void);

結束寫入或是讀取

mmc_read(void);

讀出1byte

mmc_write(int8 data);

寫入1byte

mmc_check_error(void);

檢查MMC是否正確

mmc_write_int16(int16 x);

寫入16位元變數,會拆成2byte,先傳low byte 再傳high byte

6. MMC_error_code

傳回值

意義

0

no error

1

initialization failed

2

open for write failed, in mmc_open_4_write()

3

open for read failed, in mmc_open_4_read ()

4

not opened for write, in mmc_write()

5

not opened for  read, in mmc_read ()

6

block programming failed, in mmc_write() or mmc_write_flush()

3.1  範例1:寫入常數變數

首先使用一個簡單的範例做說明如何將8位元的變數寫入MMC中。假定目標為在ecg_4k.dat的區塊內寫入1002008位元常數,前半部100、後半部200ecg_4k.dat區塊內共有40968位元變數,前2048個為100,後2048個為200。程式內容如圖2所示,表7為指令說明。

#include <16F877.H>

#include "pic_PROTO_lib.h"

#use     rs232(baud= 115200, xmit=PIN_C6, rcv=PIN_C7, errors)

#define  print_MMC_debug_msg  0        // 310 words !

#include <yz_mmc.c>

#org 0x0800

void main()

{

   int16 i;

   pic_PROTO_init();

   port_b_pullups ( FALSE );  // MMC_Dout 有隔離電阻 PIC 端就不能提昇!

                              // 若用 18FXXX 且無需 mmc_read()   可以提昇。

   printf("\n\n\t\n\n\r32 MB MMC memory card test . . ");

   mmc_init_spi();  

   printf("error_code=%x",MMC_error_code);  //印出錯誤檢查的傳回值,"0"表示正確

   if ( MMC_error_code!=0 )                 //mmc錯誤,程式停止

      {  printf("\n\rmmc error !!STOP!!");  while (1); }

   printf("\n\rMMC OK    Writing data to . . ecg_4k.dat");

   mmc_open( 0x00014800 + 'w' );             // 設定寫入ecg_4k.dat(查表)   xp

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

      {

         mmc_write( 100 );                   //寫入2048100

      }

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

      {

         mmc_write( 200 );                   //寫入2048200

      }

      printf("\n\rFinish.");

}

2. 範例程式1

7. 範例1指令說明

指令

說明

#include <yz_mmc.c>

引用yz_mmc.c,可視為MMC的驅動程式。

MMC_init_spi();

MMC設定為SPI模式(本模組目前尚無MMC模式)

MMC_open(0x00014800 + 'w');

MMC_open(int32 + 'w')」指定寫入起始位址的指令,由於採用XP作業系統,並且希望將資料寫入edg_4k.dat的區塊中,因此查表3第三列可得知起始位址為0x0001 4800

MMC_write(100);

MMC_write (int8 data)」將資料寫入MMC的指令,本指令限定資料必需是int8,若資料為int16,則使用「MMC_write_int16(int16 x)」指令,程式會將16位元的變數x拆成兩組8位元,先傳送high byte,再傳送low byte

3.2  範例2:寫入AD轉換值及讀取

本範例設定目標為將麥克風的電壓訊號儲存於ecg_16k.dat區塊中,再以PIC讀取MMC該區塊的內容。由於AD轉換的值介於0~1023,變數必需定義為int16,因此使用的寫入指令為「MMC_write_int16(int16 x)」;讀取MMC時必需指定起始點,使用「mmc_open(0x00015800 + 'r')」指令,位址0x00015800可查表3第四列得知。ecg_16k.dat區塊能儲存8192int16的變數,因此若以0.5kHz的頻率寫入可以儲存16.4秒的資料,程式內容如圖3所示。

#include <16F877.H>

#include "pic_PROTO_lib.h"

#use     rs232(baud= 115200, xmit=PIN_C6, rcv=PIN_C7, errors)

#define  print_MMC_debug_msg  0      

#define  MMC_spec_v_3_31    0 

#include <yz_mmc.c>

#org 0x0800

void main()

{

   int16 j,i, ra0;

   int8 x,k;

   pic_PROTO_init();

   setup_adc_ports( ALL_ANALOG );         //A/D轉換設定

   setup_adc( ADC_CLOCK_DIV_32 );

   port_b_pullups ( FALSE );

   printf("\n\n\t\n\n\r32 MB MMC memory card test . . ");

   mmc_init_spi();

   printf("error_code=%x",MMC_error_code);  //印出錯誤檢查的傳回值,"0"表示正確

   if ( MMC_error_code!=0 )                 //mmc錯誤,程式停止

      {  printf("\n\rmmc error !!STOP!!");  while (1); }

   printf("\r\nWriting data to . . ecg_16k.dat");

   mmc_open( 0x00015800 + 'w' );           // 設定寫入ecg_16k.dat (請查表) xp

      for(i=0;i< 8192;i++)                   //寫入8192個值

      {

         ra0=analog(0,100);

         delay_ms(2);              

         mmc_write_int16( ra0);     //寫入變數ra0

      }

   printf("\n\n\rReading . . ecg_16k.dat . . ");

   printf("press any key to continue . . ");  getc();   printf("\n\n\r ");

   mmc_open( 0x00015800 + 'r' );              // 設定開始讀取位址

   for (k=0; k< 8; k++)

   {

      for (j=0; j< 1024; j++)

      {

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

         { x = mmc_read();   printf("%x ", x ); }  //讀取資料,並列印至螢幕

         printf("\n\r");         delay_ms(100);

      }

   }

}

3. 範例2程式

4.     Matlab讀取MMC資料

接著說明如何將範例1與範例2所寫入的數據讀出。程式如圖4所示,首先指定讀卡機的磁碟,本範例為「L:\」,接著以「fopen」指令開啟所寫需要的區塊檔案,再以「fread」指令將資料進行轉換,需注意寫入的變數為8位元或16位元會有不同的設定方式,此時數據已轉換為十進位,最後以plot繪出圖形,當然也可以進行其它的應用,得到的圖形如圖5、圖6所示。

4. Matlab程式說明

        cd L:\

        f1 = fopen('ecg_4k.dat','r');             %開啟ecg_4k.dat

        f2 = fopen('ecg_16k.dat','r');            %開啟ecg_4k.dat

        data1 = fread( f_1, [1 16384], 'uint8' );   %8位元變數轉換

data2 = fread( f_2, [1 16384], 'uint16' );  %16位元變數轉換

fclose(f_1);   fclose(f_2);              %關閉檔案

        figure;        plot(data1);             %繪圖

        figure;        plot(data2);

5 範例1輸出圖形

6. 範例2輸出圖形

參考資料

http://pic-proto.mech.yzu.edu.tw/software/YZ_PIC_壓縮檔_V_4.07z.exe.