FRIENDz

FAILURE IS THE SIGN OF SUCCESS!!

Connect Flash Card with PIC18F4520

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)
  }

}

HW Connection

 

No comments:

Post a Comment