The Compact Flash Library provides routines for accessing data on Compact Flash card (abbr. CF further in text). CF cards are widely used memory elements, commonly used with digital cameras. Great capacity and excellent access time of only a few microseconds make them very attractive for microcontroller applications.
In CF card, data is divided into sectors. One sector usually comprises 512 bytes. Routines for file handling, the
Cf_Fat
routines, are not performed directly but successively through 512B buffer.
Important :
- 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 writing operation, make sure not to 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 great assistance.
External dependencies of Compact Flash Library
The following variables must be defined in all projects using Compact Flash Library: | Description : | Example : |
---|---|---|
extern sfr char CF_Data_Port; | Compact Flash Data Port. | char CF_Data_Port at PORTD; |
extern sfr sbit CF_RDY; | Ready signal line. | sbit CF_RDY at RB7_bit; |
extern sfr sbit CF_WE; | Write Enable signal line. | sbit CF_WE at LATB6_bit; |
extern sfr sbit CF_OE; | Output Enable signal line. | sbit CF_OE at LATB5_bit; |
extern sfr sbit CF_CD1; | Chip Detect signal line. | sbit CF_CD1 at RB4_bit; |
extern sfr sbit CF_CE1; | Chip Enable signal line. | sbit CF_CE1 at LATB3_bit; |
extern sfr sbit CF_A2; | Address pin 2. | sbit CF_A2 at LATB2_bit; |
extern sfr sbit CF_A1; | Address pin 1. | sbit CF_A1 at LATB1_bit; |
extern sfr sbit CF_A0; | Address pin 0. | sbit CF_A0 at LATB0_bit; |
extern sfr sbit CF_RDY_direction; | Direction of the Ready pin. | sbit CF_RDY_direction atTRISB7_bit; |
extern sfr sbit CF_WE_direction; | Direction of the Write Enable pin. | sbit CF_WE_direction at TRISB6_bit; |
extern sfr sbit CF_OE_direction; | Direction of the Output Enable pin. | sbit CF_OE_direction at TRISB5_bit; |
extern sfr sbit CF_CD1_direction; | Direction of the Chip Detect pin. | sbit CF_CD1_direction atTRISB4_bit; |
extern sfr sbit CF_CE1_direction; | Direction of the Chip Enable pin. | sbit CF_CE1_direction atTRISB3_bit; |
extern sfr sbit CF_A2_direction; | Direction of the Address 2 pin. | sbit CF_A2_direction at TRISB2_bit; |
extern sfr sbit CF_A1_direction; | Direction of the Address 1 pin. | sbit CF_A1_direction at TRISB1_bit; |
extern sfr sbit CF_A0_direction; | Direction of the Address 0 pin. | sbit CF_A0_direction at TRISB0_bit; |
Library Routines
- Cf_Init
- Cf_Detect
- Cf_Enable
- Cf_Disable
- Cf_Read_Init
- Cf_Read_Byte
- Cf_Write_Init
- Cf_Write_Byte
- Cf_Read_Sector
- Cf_Write_Sector
Routines for file handling:
- Cf_Fat_Init
- Cf_Fat_QuickFormat
- Cf_Fat_Assign
- Cf_Fat_Reset
- Cf_Fat_Read
- Cf_Fat_Rewrite
- Cf_Fat_Append
- Cf_Fat_Delete
- Cf_Fat_Write
- Cf_Fat_Set_File_Date
- Cf_Fat_Get_File_Date
- Cf_Fat_Get_File_Date_Modified
- Cf_Fat_Get_File_Size
- Cf_Fat_Get_Swap_File
Code Example
This example consists of several blocks that demonstrate various aspects ofusage of the Cf_Fat16 library. These are:
- Creation of new file and writing down to it;
- Opening existing file and re-writing it (writing from start-of-file);
- Opening existing file and appending data to it (writing from end-of-file);
- Opening a file and reading data from it (sending it to USART terminal);
- Creating and modifying several files at once;
- Reading file contents;
- Deleting file(s);
- Creating the swap file (see Help for details);
// set compact flash pinout char Cf_Data_Port at PORTD; sbit CF_RDY at RB7_bit; sbit CF_WE at LATB6_bit; // for writing to output pin always use latch (PIC18 family) sbit CF_OE at LATB5_bit; // for writing to output pin always use latch (PIC18 family) sbit CF_CD1 at RB4_bit; sbit CF_CE1 at LATB3_bit; // for writing to output pin always use latch (PIC18 family) sbit CF_A2 at LATB2_bit; // for writing to output pin always use latch (PIC18 family) sbit CF_A1 at LATB1_bit; // for writing to output pin always use latch (PIC18 family) sbit CF_A0 at LATB0_bit; // for writing to output pin always use latch (PIC18 family) sbit CF_RDY_direction at TRISB7_bit; sbit CF_WE_direction at TRISB6_bit; sbit CF_OE_direction at TRISB5_bit; sbit CF_CD1_direction at TRISB4_bit; sbit CF_CE1_direction at TRISB3_bit; sbit CF_A2_direction at TRISB2_bit; sbit CF_A1_direction at TRISB1_bit; sbit CF_A0_direction at TRISB0_bit; // end of cf pinout const LINE_LEN = 39; char err_txt[20] = "FAT16 not found"; char file_contents[LINE_LEN] = "XX CF 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'; Cf_Fat_Set_File_Date(2005,6,21,10,35,0); // Set file date & time info Cf_Fat_Assign(&filename, 0xA0); // Find existing file or create a new one Cf_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; Cf_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 Cf_Fat_Set_File_Date(2005,6,21,10,35,0); // Set file date & time info Cf_Fat_Assign(&filename, 0xA0); // find existing file or create a new one Cf_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; Cf_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'; Cf_Fat_Assign(&filename, 0); Cf_Fat_Rewrite(); for(loop = 1; loop <= 55; loop++) { file_contents[0] = loop / 10 + 48; file_contents[1] = loop % 10 + 48; Cf_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'; Cf_Fat_Assign(&filename, 0); Cf_Fat_Set_File_Date(2009, 1, 23, 17, 22, 0); Cf_Fat_Append(); // Prepare file for append Cf_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'; Cf_Fat_Assign(&filename, 0); Cf_Fat_Reset(&size); // To read file, procedure returns size of file for (i = 1; i <= size; i++) { Cf_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'; Cf_Fat_Assign(filename, 0); Cf_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 (Cf_Fat_Assign(filename, 0)) { //--- file has been found - get its date Cf_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 Cf_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 = Cf_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 = Cf_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++) { Cf_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 // use fat16 quick format instead of init routine if a formatting is needed if (Cf_Fat_Init() == 0) { Delay_ms(2000); // wait for a while until the card is stabilized // period depends on used CF card //--- 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: Cf_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