The Multi Media Card (MMC) is a Flash memory card standard. MMC cards are
currently available in sizes up to and including 32 GB and are used in cellular
phones, digital audio players, digital cameras and PDA’s.
mikroC PRO for PIC provides a library for accessing data on Multi Media Card via SPI communication. This library also supports SD (Secure Digital) and high capacity SDHC (Secure Digital High Capacity) memory cards .
SD cards are currently available in sizes of up to and including 2 GB, and are used in digital cameras, digital camcorders, handheld computers, media players, mobile phones, GPS receivers, video games and PDAs.
SDHC cards share the same physical and electrical form factor as older (SD 1.x) cards, allowing SDHC-devices to support both newer SDHC cards and older SD-cards. The current standard limits the maximum capacity of an SDHC card to 32 GB.
mikroC PRO for PIC provides a library for accessing data on Multi Media Card via SPI communication. This library also supports SD (Secure Digital) and high capacity SDHC (Secure Digital High Capacity) memory cards .
Secure Digital Card
Secure Digital (SD) is a Flash memory card standard, based on the older Multi Media Card (MMC) format.SD cards are currently available in sizes of up to and including 2 GB, and are used in digital cameras, digital camcorders, handheld computers, media players, mobile phones, GPS receivers, video games and PDAs.
Secure Digital High Capacity Card
SDHC (Secure Digital High Capacity, SD 2.0) is an extension of the SD standard which increases card's storage capacity up to 32 GB by using sector addressing instead of byte addressing in the previous SD standard.SDHC cards share the same physical and electrical form factor as older (SD 1.x) cards, allowing SDHC-devices to support both newer SDHC cards and older SD-cards. The current standard limits the maximum capacity of an SDHC card to 32 GB.
Important :
The SPI module has to
be initialized through - Routines for file handling can be used only with FAT16 file system.
- Library functions create and read files from the root directory only.
- Library functions populate both FAT1 and FAT2 tables when writing to files, but the file data is being read from the FAT1 table only; i.e. there is no recovery if the FAT1 table gets corrupted.
- If MMC/SD card has Master Boot Record (MBR), the library will work with the first available primary (logical) partition that has non-zero size. If MMC/SD card has Volume Boot Record (i.e. there is only one logical partition and no MBRs), the library works with entire card as a single partition. For more information on MBR, physical and logical drives, primary/secondary partitions and partition tables, please consult other resources, e.g. Wikipedia and similar.
- Before write operation, make sure you don’t overwrite boot or FAT sector as it could make your card on PC or digital camera unreadable. Drive mapping tools, such as Winhex, can be of a great assistance.
- Library uses SPI module for communication. The user must initialize the appropriate SPI module before using the MMC Library.
- For MCUs with multiple SPI modules it is possible to initialize all of them
and then switch by using the
SPI_Set_Active()
function. See the SPI Library functions. - MMC FAT 16 Library works with PIC18 family only.
SPIx_Init_Advanced
routine with the
following parameters:- SPI Master
- Primary prescaler 64
- Data sampled in the middle of data output time
- Clock idle low
- Serial output data changes on transition form low to high edge
Tip : Once the MMC/SD card is
initialized, SPI module can be reinitialized at higher a speed. See the Mmc_Init and Mmc_Fat_Init
routines.
External dependencies of MMC Library
The following variable must be defined in all projects using MMC library: | Description : | Example : |
---|---|---|
extern sfr sbit Mmc_Chip_Select; |
Chip select pin. | sbit Mmc_Chip_Select at
RC0_bit; |
extern sfr sbit
Mmc_Chip_Select_Direction; |
Direction of the chip select pin. | sbit Mmc_Chip_Select_Direction at
TRISC0_bit; |
Library Routines
- Mmc_Init
- Mmc_Read_Sector
- Mmc_Write_Sector
- Mmc_Read_Cid
- Mmc_Read_Csd
- Mmc_Multi_Read_Start
- Mmc_Multi_Read_Sector
- Mmc_Multi_Read_Stop
- Mmc_Fat_Init
- Mmc_Fat_QuickFormat
- Mmc_Fat_Assign
- Mmc_Fat_Reset
- Mmc_Fat_Read
- Mmc_Fat_Rewrite
- Mmc_Fat_Append
- Mmc_Fat_Delete
- Mmc_Fat_Write
- Mmc_Fat_Set_File_Date
- Mmc_Fat_Get_File_Date
- Mmc_Fat_Get_File_Date_Modified
- Mmc_Fat_Get_File_Size
- Mmc_Get_File_Write_Sector
- Mmc_Fat_Get_Swap_File
- Mmc_Fat_Tell
- Mmc_Fat_Seek
- Mmc_Fat_Rename
- Mmc_Fat_MakeDir
- Mmc_Fat_RenameDir
- Mmc_Fat_RemoveDir
- Mmc_Fat_ChangeDir
- Mmc_Fat_Exists
- Mmc_Fat_Dir
- Mmc_Fat_ReadDir
- Mmc_Fat_Activate
- Mmc_Fat_ReadN
- Mmc_Fat_Open
- Mmc_Fat_Close
- Mmc_Fat_EOF
Code Example
The following example demonstrates MMC library test. Upon flashing, insert a MMC/SD card into the module, when you should receive the "Init-OK" message. Then, you can experiment with MMC read and write functions, and observe the results through the Usart Terminal.// MMC module connections
sbit Mmc_Chip_Select at LATC0_bit; // for writing to output pin always use latch (PIC18 family)
sbit Mmc_Chip_Select_Direction at TRISC0_bit;
// eof MMC module connections
const LINE_LEN = 43;
char err_txt[20] = "FAT16 not found";
char file_contents[LINE_LEN] = "XX MMC/SD FAT16 library by Anton Rieckertn";
char filename[14] = "MIKRO00x.TXT"; // File names
unsigned short loop, loop2;
unsigned long i, size;
char Buffer[512];
// UART1 write text and new line (carriage return + line feed)
void UART1_Write_Line(char *uart_text) {
UART1_Write_Text(uart_text);
UART1_Write(13);
UART1_Write(10);
}
// Creates new file and writes some data to it
void M_Create_New_File() {
filename[7] = 'A';
Mmc_Fat_Set_File_Date(2010, 4, 19, 9, 0, 0); // Set file date & time info
Mmc_Fat_Assign(&filename, 0xA0); // Find existing file or create a new one
Mmc_Fat_Rewrite(); // To clear file and start with new data
for(loop = 1; loop <= 99; loop++) {
UART1_Write('.');
file_contents[0] = loop / 10 + 48;
file_contents[1] = loop % 10 + 48;
Mmc_Fat_Write(file_contents, LINE_LEN-1); // write data to the assigned file
}
}
// Creates many new files and writes data to them
void M_Create_Multiple_Files() {
for(loop2 = 'B'; loop2 <= 'Z'; loop2++) {
UART1_Write(loop2); // signal the progress
filename[7] = loop2; // set filename
Mmc_Fat_Set_File_Date(2010, 4, 19, 9, 0, 0); // Set file date & time info
Mmc_Fat_Assign(&filename, 0xA0); // find existing file or create a new one
Mmc_Fat_Rewrite(); // To clear file and start with new data
for(loop = 1; loop <= 44; loop++) {
file_contents[0] = loop / 10 + 48;
file_contents[1] = loop % 10 + 48;
Mmc_Fat_Write(file_contents, LINE_LEN-1); // write data to the assigned file
}
}
}
// Opens an existing file and rewrites it
void M_Open_File_Rewrite() {
filename[7] = 'C';
Mmc_Fat_Assign(&filename, 0);
Mmc_Fat_Rewrite();
for(loop = 1; loop <= 55; loop++) {
file_contents[0] = loop / 10 + 48;
file_contents[1] = loop % 10 + 48;
Mmc_Fat_Write(file_contents, LINE_LEN-1); // write data to the assigned file
}
}
// Opens an existing file and appends data to it
// (and alters the date/time stamp)
void M_Open_File_Append() {
filename[7] = 'B';
Mmc_Fat_Assign(&filename, 0);
Mmc_Fat_Set_File_Date(2010, 4, 19, 9, 20, 0);
Mmc_Fat_Append(); // Prepare file for append
Mmc_Fat_Write(" for mikroElektronika 2010n", 27); // Write data to assigned file
}
// Opens an existing file, reads data from it and puts it to UART
void M_Open_File_Read() {
char character;
filename[7] = 'B';
Mmc_Fat_Assign(&filename, 0);
Mmc_Fat_Reset(&size); // To read file, procedure returns size of file
for (i = 1; i <= size; i++) {
Mmc_Fat_Read(&character);
UART1_Write(character); // Write data to UART
}
}
// Deletes a file. If file doesn't exist, it will first be created
// and then deleted.
void M_Delete_File() {
filename[7] = 'F';
Mmc_Fat_Assign(filename, 0);
Mmc_Fat_Delete();
}
// Tests whether file exists, and if so sends its creation date
// and file size via UART
void M_Test_File_Exist() {
unsigned long fsize;
unsigned int year;
unsigned short month, day, hour, minute;
unsigned char outstr[12];
filename[7] = 'B'; //uncomment this line to search for file that DOES exists
// filename[7] = 'F'; //uncomment this line to search for file that DOES NOT exist
if (Mmc_Fat_Assign(filename, 0)) {
//--- file has been found - get its create date
Mmc_Fat_Get_File_Date(&year, &month, &day, &hour, &minute);
UART1_Write_Text(" created: ");
WordToStr(year, outstr);
UART1_Write_Text(outstr);
ByteToStr(month, outstr);
UART1_Write_Text(outstr);
WordToStr(day, outstr);
UART1_Write_Text(outstr);
WordToStr(hour, outstr);
UART1_Write_Text(outstr);
WordToStr(minute, outstr);
UART1_Write_Text(outstr);
//--- file has been found - get its modified date
Mmc_Fat_Get_File_Date_Modified(&year, &month, &day, &hour, &minute);
UART1_Write_Text(" modified: ");
WordToStr(year, outstr);
UART1_Write_Text(outstr);
ByteToStr(month, outstr);
UART1_Write_Text(outstr);
WordToStr(day, outstr);
UART1_Write_Text(outstr);
WordToStr(hour, outstr);
UART1_Write_Text(outstr);
WordToStr(minute, outstr);
UART1_Write_Text(outstr);
//--- get file size
fsize = Mmc_Fat_Get_File_Size();
LongToStr((signed long)fsize, outstr);
UART1_Write_Line(outstr);
}
else {
//--- file was not found - signal it
UART1_Write(0x55);
Delay_ms(1000);
UART1_Write(0x55);
}
}
// Tries to create a swap file, whose size will be at least 100
// sectors (see Help for details)
void M_Create_Swap_File() {
unsigned int i;
for(i=0; i<512; i++)
Buffer[i] = i;
size = Mmc_Fat_Get_Swap_File(5000, "mikroE.txt", 0x20); // see help on this function for details
if (size) {
LongToStr((signed long)size, err_txt);
UART1_Write_Line(err_txt);
for(i=0; i<5000; i++) {
Mmc_Write_Sector(size++, Buffer);
UART1_Write('.');
}
}
}
// Main. Uncomment the function(s) to test the desired operation(s)
void main() {
#define COMPLETE_EXAMPLE // comment this line to make simpler/smaller example
ADCON1 |= 0x0F; // Configure AN pins as digital
CMCON |= 7; // Turn off comparators
// Initialize UART1 module
UART1_Init(19200);
Delay_ms(10);
UART1_Write_Line("PIC-Started"); // PIC present report
// Initialize SPI1 module
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
// use fat16 quick format instead of init routine if a formatting is needed
if (Mmc_Fat_Init() == 0) {
// reinitialize spi at higher speed
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
//--- Test start
UART1_Write_Line("Test Start.");
//--- Test routines. Uncomment them one-by-one to test certain features
M_Create_New_File();
#ifdef COMPLETE_EXAMPLE
M_Create_Multiple_Files();
M_Open_File_Rewrite();
M_Open_File_Append();
M_Open_File_Read();
M_Delete_File();
M_Test_File_Exist();
M_Create_Swap_File();
#endif
UART1_Write_Line("Test End.");
}
else {
UART1_Write_Line(err_txt); // Note: Mmc_Fat_Init tries to initialize a card more than once.
// If card is not present, initialization may last longer (depending on clock speed)
}
}
No comments:
Post a Comment