CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Problem with FAT32 write to MMC

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
thenorthstar



Joined: 06 Mar 2010
Posts: 24

View user's profile Send private message

Problem with FAT32 write to MMC
PostPosted: Thu Mar 14, 2013 3:09 am     Reply with quote

Hello Friends;
I have a problem with FAT32, please can you help me?
SAMPLE.TEXT into MMC creates a file, but when I print the "Hello world" in the file but incorrectly writes.

I could not find a working properly: ( FAT32 mmc code.
I have found I have tried all of them, but did not work.

My project Files: http://yadi.sk/d/hJS2uP393HEzt





my codes are as follows, I can not find where the error is. Crying or Very sad

main.c
Code:

#include <18F4620.h>
#include <string.h>

#fuses H4,NOWDT,NOPROTECT,NOLVP,NODEBUG
#use delay(clock=40000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include "2x16_4x20_LCD.c"
#include "MMC_SPI_FAT32.h"
#include "MMC_SPI_FAT32.c"


void main(){
    delay_ms(100);
   char f,gfilename[12],c;
   char msg[64];
   int cart;
   int i=0;
   
   cart=0;
   lcd_init();
   LCD_gotoxy(1,1);
   printf(lcd_putc,"   MMC CONTROL   ");
   printf("\r\nMMC CONTROL\r\n");

while(true)
{  LCD_gotoxy(1,1);
   printf(lcd_putc,"   MMC CONTROL    ");
   
   
  if(MMCInit() == MMC_OK)  {
    LCD_gotoxy(1,1);
    printf(lcd_putc,"MMC init OK   ");
    printf("MMC init OK\r\n");
    delay_ms(2000);
   
    InitFAT();
   
      LCD_gotoxy(1,2);
      printf(lcd_putc,"FAT init OK");
      printf("FAT init OK\r\n");
      printf("Creating Files\r\n");
      delay_ms(1000);
      printf(lcd_putc,"\f"); 
      strcpy(gfilename,"SAMPLE.TXT");
       
   
      f = fopen(gfilename,'a');
      printf("Created SAMPLE.TXT\r\n");
      delay_ms(1000);
     
     if (f & MMC_ERROR)
      {                                               
      printf(lcd_putc,"Couldn't open file!");         
      if(f == MMC_NO_CARD_INSERTED)                           
         printf(lcd_putc,"Please, insert MMC!");                         
      else if(f == MMC_MAX_FILES_REACHED)                   
         printf(lcd_putc,"ops.. =)");                                   
      }                                                 
   else                                                         
   {       
      printf(lcd_putc,"\f");
      LCD_gotoxy(1,1);
      printf(lcd_putc,"Writing Began");
      printf("Writing Began\r\n");

      strcpy(msg,"Hello World");
      fputstring(msg,f);

      printf("Written data=%s",msg);
      fclose(f);
      delay_ms(100);
     
   while (MMCInit() == MMC_OK)
      {
      int w;
      w==1;
      LCD_gotoxy(1,1);
      printf(lcd_putc,"Writing Done  ");
      printf("\r\nWriting Done");
     while (MMCInit() == MMC_OK)
     {
     }
      }
     
      }
     }//MMCInit
   } //while
} //Main
//!//+++++++++++++++++++++++++++++++++++++++++++++++++++
//!



MMC_SPI_FAT32.c
Code:

// If you want to use software SPI keep this line uncommented
// If you want to use hardware SPI comment this line..
// Software SPI are slower, but you can use any clock and data
// pins that you want..
#define MMC_SPI_SOFTWARE
// Change the port to whatever port you are going to use
#use FAST_IO(C)
// Change this to set the right tris for your pins
#define SET_MMC_TRIS() set_tris_C(0x10) // 0b0001000 1=input,0=output
// Change these pins to whatever pins you are using
#define ChipSel      pin_C2 // Chip-Select pin
#define ChipClk      pin_C3 // SPI-Clock pin    //SD C0
#define ChipDout     pin_C5 // SPI-Data out pin
#define ChipDin      pin_C4 // SPI-Data in pin  //SD C1

#ifdef MMC_SPI_SOFTWARE
   // You can also specify a baud-rate in the line below, if not the fastest possible speed will be used.
   // For me that was 800kHz on a 18F4550 with 48MHz external clock
   #USE SPI(MASTER, SAMPLE_RISE, MSB_FIRST, IDLE=1, DI=ChipDin, DO=ChipDout, CLK=ChipClk, BITS=8, STREAM=MMC_SPI)
   #define MMC_Xfer(a) SPI_Xfer(MMC_SPI,a)
#else
   // If MMC_SPI_SOFTWARE isn't defined (se above) these variables are used, you should check if they
   // matches your target device, but for most pic's they should do
   #byte SSPBUF   = 0xFC9
   #byte SSPSTAT   = 0xFC7
   #byte SSPCON1   = 0xFC6
   #bit  BF      = SSPSTAT.0
#endif

#ifdef ENABLE_FILELISTNG
   #include <STDLIBM.H> // used for malloc and free functions
#endif

int32 FATTable[128];
int32 gFirstEmptyCluster;

FAT32Vars gFAT32Vars;
diskinforec DiskInfo;
FILE gFiles[MAXFILES];

// Time stores the date and time, this is used when writing and/or creating files
TimeRecord Time;

#ifdef ENABLE_FILELISTNG
   // Set the maximum number of files/dirs to be listed by Listfile()
   #define MAX_FILE_LIST 10
   // Variables used by InitList(), ListFiles(), NextPage() and SetPage()
   ListPos StartList;
   ListPos CurrentList;
   BOOLEAN changeList; // Do not use this; it is only used by SetPage() and ListFiles() and Initialized by InitFAT()
   // The result of ListFiles() function..
   LongFileName FileList[MAX_FILE_LIST];
#endif

#byte MMCAddressL = gFAT32Vars
#byte MMCAddressH = gFAT32Vars+1
#byte MMCAddressHL = gFAT32Vars+2
#byte MMCAddressHH = gFAT32Vars+3
#byte gStartSectorL = gFAT32Vars+8
#byte gStartSectorH = gFAT32Vars+9
#byte gStartSectorHL = gFAT32Vars+10

// You should check that these values matches your pic device
// but for most devices they should be correct
#define FSR0L      *0xFE9
#define POSTINC0   *0xFEE

// A bunch of error codes
#define MMC_OK                0
#define MMC_ERROR             0x80
#define MMC_INVALID_FILE       0x88
#define MMC_MAX_FILES_REACHED    0x90
#define MMC_NO_CARD_INSERTED    0x98
#define MMC_TIME_OUT         0xA0
#define MMC_INVALID_RESPONSE   0xA8
#define MMC_NOT_FOUND         0xB0
#define MMC_INVALID_CLUSTER      0xB8
#define MMC_END_OF_DIR         0xC0
#define MMC_INVALID_POSITION   0xC8

// I don't like having constants in the code... yeah, I do have some anyway ;)
#define END_OF_DIR                  17
#define DIRENTRYS_PER_SECTOR         16
#define CHARACTERS_IN_LONG_FILENAMES   13

// If you want to have a cardinserted sens-pin, define CardInserted to a input, like:
// #define CardInserted !input(PIN_XX)
// MMC Card have two GND pins, pull one up with a resistor (10K or somwthing like that) to Vcc
// and connect to desired pin
#define CardInserted() 1

// Looks a bit nicer in the code
#define MMC_Select()    output_low(ChipSel)
#define MMC_Deselect()   output_high(ChipSel)


// Below this, there should be no need to change anything


char IsSelfDir(char *be)
{
   if (be[0] == '.' && be[1] == '.')
      return 0xFF;
   else
      return 0;
}

void MMCOut(char indata)
{
  #ifdef MMC_SPI_SOFTWARE
   MMC_Xfer(indata);
  #else
   char i;
   SSPBUF=indata;
   while (!BF);
   i = SSPBUF;
  #endif
}

void MMC8Clock()
{
  #ifdef MMC_SPI_SOFTWARE
   MMC_Xfer(0xFF);
  #else
   char i;
   SSPBUF=0xFF;
   while (!BF);
   i = SSPBUF;
  #endif
}

char MMCIn()
{
  #ifdef MMC_SPI_SOFTWARE
   return MMC_Xfer(0xFF);
  #else
   char i;
   SSPBUF=0xFF;
   while (!BF);
   i = SSPBUF;
   return i;
  #endif
}

MMCResponse MMCInit()
{
   char response,iii,errcnt;
   

   if (!CardInserted())
      return MMC_NO_CARD_INSERTED;

   SET_MMC_TRIS();  // Set input/output
   restart_wdt();
   MMC_Deselect();

   #ifndef MMC_SPI_SOFTWARE
      bit_clear(SSPCON1,5); // Disables serial port and configures these pins as I/O port pins
      SSPCON1 = 0x30; // modify this number to change SPI clock rate
                     // Enables serial port and configures SCK, SDO, SDI and SS as serial port pins
                     // Idle state for clock is a high level
                     // 0000 = SPI Master mode, clock = FOSC/4

      SSPSTAT = 0;   // Only bit 6,7 are writable
                     // 0 = Input data sampled at middle of data output time
                     // 0 = Transmit occurs on transition from Idle to active clock state
   #endif

   iii = 10;
   errcnt = 100;
   do
   {
      MMCOut(0xFF);
   } while (--iii);
   delay_us(1000);

   MMC_Select(); // if the /CS line of the MMC is low during CMD0,(below), the card enters SPI-mode
   MMCOut(0x40); // CMD0
   MMCOut(0x00);
   MMCOut(0x00);
   MMCOut(0x00);
   MMCOut(0x00);
   MMCOut(0x95); // CRC
   MMC8Clock();
   response = MMCIn();
   MMC_Deselect();
   do
   {
      delay_us(1000);
      //output_low(ChipClk);
      MMC_Select();
      MMCOut(0x41); // CMD1
      MMCOut(0x00);
      MMCOut(0x00);
      MMCOut(0x00);
      MMCOut(0x00);
      MMCOut(0x01);
      MMC8Clock();
      response = MMCIn();
      MMC_Deselect();
      MMC8Clock();
      errcnt--;
   } while (response && errcnt);
   if(response == 0)
      return MMC_OK;
   else
      return MMC_TIME_OUT;
}


// "Packed" Date:
// +-------+------------+-------+-----+
// | BITS  |    15:9    |  8:5  | 4:0 |
// | VALUE |Year – 1980 | Month | Day |
// +-------+------------+-------+-----+
int16 GetCurrentDOSDate()
{
   int16 retval;

   retval = Time.Year - 1980;
   retval <<= 9;
   retval |= ((int16)Time.Month << 5);
   retval |= (int16)Time.Day;
   return retval;
}

// "Packed" Time:
// +-------+-------+--------+----------+
// | BITS  | 15:11 |  10:5  |   4:0    |
// | VALUE | Hour  | Minute | Second/2 |
// +-------+-------+--------+----------+
int16 GetCurrentDOSTime()
{
   int16 retval;

   retval = Time.Hour;
   retval <<= 11;
   retval |= ((int16)Time.Minute << 5);
   retval |= (int16)Time.Second >> 1;
   return retval;
}

// Function: Reads a sector from MMC
MMCResponse ReadSector(int32 sector, char *hova)
{
   char errs,response;
   char cnt2,cnt3;

   #byte sectorL = sector
   #byte sectorH = sector+1
   #byte sectorHL = sector+2

   if (!CardInserted())
      return MMC_NO_CARD_INSERTED;
   Disable_interrupts(GLOBAL);
   Restart_wdt();
   MMCAddressL = 0;
   MMCAddressH = sectorL;
   MMCAddressHL = sectorH;
   MMCAddressHH = sectorHL;
   gFAT32Vars.MMCAddress <<= 1;

   MMC_Select();
   MMCOut(0x51);
   MMCOut(MMCAddressHH);
   MMCOut(MMCAddressHL);
   MMCOut(MMCAddressH & 0xFE);
   MMCOut(0);
   MMCOut(0x01);
   errs = 8;
   do
   {
      response = MMCIn();
   } while (--errs && response==0xFF);
   errs = 50;
   do
   {
      response = MMCIn();
      if (response == 0xFE)
         break;
      delay_ms(1);
   } while (--errs);
   FSR0L = (int16)hova; // *0xFE9
   cnt3 = 2;
   cnt2 = 0;
   do
   {
      do
      {
         #ifdef MMC_SPI_SOFTWARE
            POSTINC0 = MMC_Xfer(0xFF); // *0xFEE
         #else
            SSPBUF=0xFF; // Writes 0xFF on SPI
            while(!BF); // Wait until Transmitted/Received
            POSTINC0 = SSPBUF; // Read the received byte and place it in adress oxFEE
         #endif
      } while (--cnt2);
   } while (--cnt3);
   response = MMCIn();
   response = MMCIn();
   MMC_Deselect();
   Enable_interrupts(GLOBAL);
   return MMC_OK;
}

// Writes a sector to MMC
MMCResponse WriteSector(int32 sector, char *honnan)
{
   char errs,response;
   char cnt2,cnt3;
   #byte sectorL = sector
   #byte sectorH = sector+1
   #byte sectorHL = sector+2

   if (!CardInserted())
      return MMC_NO_CARD_INSERTED;
   Disable_interrupts(GLOBAL);
   Restart_wdt();
   MMCAddressL = 0;
   MMCAddressH = sectorL;
   MMCAddressHL = sectorH;
   MMCAddressHH = sectorHL;
   gFAT32Vars.MMCAddress <<= 1;
   response = 0;
   //output_low(ChipClk);
   MMC_Select();
   MMCOut(0x58);
   MMCOut(MMCAddressHH);
   MMCOut(MMCAddressHL);
   MMCOut(MMCAddressH & 0xFE);
   MMCOut(0);
   MMCOut(0x01);
   MMC8Clock();
   errs = 8;
   do
   {
      response = MMCIn();
   } while (--errs && response==0xFF);
   if (response)
   {
      MMC_Deselect();
      //output_high(ChipClk);
      MMC8Clock();
      Enable_interrupts(GLOBAL);
      return MMC_INVALID_RESPONSE;
   }
   MMC8Clock();
   MMCOut(0xFE);
   FSR0L = (int16)honnan; // *0xFE9
   cnt3 = 2;
   cnt2 = 0;
   do
   {
      do
      { 
     
     
   

//!//================================================================         
 #ifdef MMC_SPI_SOFTWARE
MMC_Xfer(POSTINC0); // *0xFEE
#else
SSPBUF=POSTINC0; // Write the byte on address oxFEE to SPI
while (!BF);
dummy= SSPBUFF ; dummy read to clear status bits
#endif
//!//==================================================================
      } while (--cnt2);
   } while (--cnt3);
   MMCOut(0x00);
   MMCOut(0x01);
   response = MMCIn();
   response ^= 0xE5; // Bitwise exclusive or assignment operator, x^=y, is the same as x=x^y
   if (response)
   {
      goto endwr3;
   }
   do
   {
      response = MMCIn();
   } while (response == 0);
   response = 0;
endwr3:
   MMC_Deselect();
   //output_high(ChipClk);
   MMC8Clock();
   Enable_interrupts(GLOBAL);
   return MMC_OK;
}

// Function: Initializes the FAT system
void InitFAT()
{
   int32 actsector;
   char i;

   gFirstEmptyCluster = 0;
   gFAT32Vars.gStartSector = 0;
   ReadSector(gFAT32Vars.gStartSector,gFiles[MAXFILES-1].IOpuffer);
   if (gFiles[MAXFILES-1].IOpuffer[0] != 0xEB)
   {
      gStartSectorL = gFiles[MAXFILES-1].IOpuffer[0x1C6];
      gStartSectorH = gFiles[MAXFILES-1].IOpuffer[0x1C7];
      gStartSectorHL = gFiles[MAXFILES-1].IOpuffer[0x1C8];
      ReadSector(gFAT32Vars.gStartSector,gFiles[MAXFILES-1].IOpuffer);
   }
   memcpy(&DiskInfo,gFiles[MAXFILES-1].IOpuffer,sizeof(DiskInfo));
   actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1;
   ReadSector(actsector,FATTable);
   gFAT32Vars.FATstartidx = 0;
   gFAT32Vars.gFirstDataSector = gFAT32Vars.gStartSector + DiskInfo.FATCopies*DiskInfo.hSectorsPerFat+DiskInfo.Reserved1 - 2;

   for (i=0;i<MAXFILES;i++)
   {
      gFiles[i].Free = TRUE;
   }
   #ifdef ENABLE_FILELISTNG
      // Code for initializing file-listing
      for(i=0;i<MAX_FILE_LIST;i++)
         FileList[i].name = NULL;
      changeList = TRUE;
   #endif
//   MMC_Debug("-FATInit ");
}

int32 GetNextCluster(int32 curcluster)
{
   int32 actsector;
   int32 clpage;
   char clpos;

   clpage = curcluster >> 7;
   clpos = curcluster & 0x7F;
   if (clpage != gFAT32Vars.FATstartidx) // read in the requested page
   {
      actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + clpage;
      ReadSector(actsector,FATTable);
      gFAT32Vars.FATstartidx = clpage;
   }
   return (FATTable[clpos]);
}

void SetClusterEntry(int32 curcluster,int32 value)
{
   int32 actsector;
   int32 clpage;
   char clpos;

   clpage = curcluster >> 7;
   clpos = curcluster & 0x7F;
   actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + clpage;
   if (clpage != gFAT32Vars.FATstartidx)
   {
      ReadSector(actsector,FATTable);
      gFAT32Vars.FATstartidx = clpage;
   }
   FATTable[clpos] = value;
   WriteSector(actsector,FATTable);
   actsector += DiskInfo.hSectorsPerFat;
   WriteSector(actsector,FATTable);
}

void ClearClusterEntry(int32 curcluster)
{
   int32 actsector;
   int32 clpage;
   char clpos;

   clpage = curcluster >> 7;
   clpos = curcluster & 0x7F;
   if (clpage != gFAT32Vars.FATstartidx)
   {
      actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + gFAT32Vars.FATstartidx;
      WriteSector(actsector,FATTable);
      actsector += DiskInfo.hSectorsPerFat;
      WriteSector(actsector,FATTable);
      actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + clpage;
      ReadSector(actsector,FATTable);
      gFAT32Vars.FATstartidx = clpage;
   }
   FATTable[clpos] = 0;
}

int32 FindFirstFreeCluster()
{
   int32 i,st,actsector,retval;
   char j;

   st = gFirstEmptyCluster;
   for (i=st;i<DiskInfo.hSectorsPerFat;i++)
   {
      if (i != gFAT32Vars.FATstartidx)
      {
         actsector = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + i;
         ReadSector(actsector,FATTable);
         gFAT32Vars.FATstartidx = gFirstEmptyCluster = i;
      }
      for (j=0;j<128;j++)
      {
         if (FATTable[j] == 0)
         {
            retval = i;
            retval <<= 7;
            retval |= j;
            return retval;
         }
      }
   }
   return 0x0FFFFFFF;
}

// Function: Converts a dir-entry to a 8.3 filename
void ConvertFilename(DIR *beDir,char *name)
{
   char i,j,c;

   j = 0;
   name[0] = 0;
   for (i=0;i<8;i++)
   {
      c = beDir->sName[i];
      if (c == ' ')
         break;
      name[j++] = c;
   }
   for (i=0;i<3;i++)
   {
      c = beDir->spam[i];
      if (c == ' ' || c == 0)
         break;
      if (!i)
         name[j++] = '.';
      name[j++] = c;
   }
   name[j++] = 0;
}

// Function: Converts a dir-entry to a (part of a) long filename.
//           One dir-entry can hold 13 unicode characters
void ConvertLongFilename(DIR *beDir,char *name)
{
   char i,j,c;

   j = 0;
   name[0] = 0;
   for (i=1;i<11;i+=2)
   {
      c = (char)(*(((char*)beDir)+i));
      if (c == 0x00 || c == 0xFF)
         break;
      name[j++] = c;
   }
   if(c!=0x00 && c!= 0xFF)
   {
      for (i=14;i<26;i+=2)
      {
         c = (char)(*(((char*)beDir)+i));;
         if (c == 0 || c == 0xFF)
            break;
         name[j++] = c;
      }
      if(c!=0x00 && c != 0xFF)
      {
         for (i=28;i<31;i+=2)
         {
            c = (char)(*(((char*)beDir)+i));
            if (c == 0 || c == 0xFF)
               break;
            name[j++] = c;
         }
      }
   }
   name[j++] = 0;
}

void GetDOSName(DIR *pDir, char *fname)
{
   char i,j,leng,c,toext;

   toext = FALSE;
   j = 0;
   leng = strlen(fname);
   for (i=0;i<8;i++)
      pDir->sName[i] = ' ';
   for (i=0;i<3;i++)
      pDir->spam[i] = ' ';
   for (i=0;i<leng;i++)
   {
      c = fname[i];
      c = toupper(c);
      if (c == '.')
      {
         toext = TRUE;
         continue;
      }
      if (toext)
         pDir->spam[j++] = c;
      else
         pDir->sName[i] = c;
   }
}

// Function: Sets the file f to root dir
MMCResponse ReadRootDirectory(char fil)
{
   int32 actsector;

   if (fil > (MAXFILES-1))
      return MMC_INVALID_FILE;
   actsector = gFAT32Vars.gStartSector + DiskInfo.FATCopies*DiskInfo.hSectorsPerFat+DiskInfo.Reserved1;
   ReadSector(actsector,gFiles[fil].IOpuffer);
   gFAT32Vars.gDirEntrySector = actsector;
   gFiles[fil].dirSector = actsector;
   gFiles[fil].dirIdx = 0;
   memcpy(&(gFiles[fil].DirEntry),gFiles[fil].IOpuffer,32);
   gFiles[fil].CurrentCluster = DiskInfo.hRootStartCluster;
   return MMC_OK;
}

// Funciton: Finds a file
char FindDirEntry(char *fname,char f)
{
   DIR *pDir;
   int16 i;
   char filename[16];
   int32 nextcluster,actsector;

   if (f > (MAXFILES-1))
   {
      return FALSE;
   }
   gFAT32Vars.gFirstEmptyDirEntry = 0xFF;
   gFAT32Vars.gFirstDirEntryCluster = 0x0FFFFFFF;
   do
   {
      pDir = (DIR*)(gFiles[f].IOpuffer);
      for (i=0;i<DIRENTRYS_PER_SECTOR;i++)
      {
         if ((pDir->sName[0] == 0xE5 || pDir->sName[0] == 0) && gFAT32Vars.gFirstEmptyDirEntry == 0xFF) // store first free
         {
            gFAT32Vars.gFirstEmptyDirEntry = i;
            gFAT32Vars.gFirstDirEntryCluster = gFiles[f].CurrentCluster;
         }
         if (pDir->sName[0] == 0)
         {
            return FALSE;
         }
         ConvertFilename(pDir,filename);
         if (!strcmp(filename,fname))
         {
            memcpy(&(gFiles[f].DirEntry),pDir,32);
            gFiles[f].dirIdx = i;
            gFAT32Vars.gDirEntryIdx = i;
            return TRUE;
         }
         pDir++;
      }
      nextcluster = GetNextCluster(gFiles[f].CurrentCluster);
      if (nextcluster != 0x0FFFFFFF && nextcluster != 0)
      {
         actsector = nextcluster + gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);
         gFAT32Vars.gDirEntrySector = actsector;
         gFiles[f].dirSector = actsector;
         gFiles[f].CurrentCluster = nextcluster;
      }
   } while (nextcluster != 0x0FFFFFFF && nextcluster != 0);
   return FALSE;
}

// Function: Assign a filenumber(f) and open the directory
//           where the file are and return the filename.
char* TryFile(char *fname, char *f)
{
   char i,leng;
   char *filename;

   *f = 0xFF;
   for (i=0;i<MAXFILES;i++)
   {
      if (gFiles[i].Free)
      {
         *f = i;
         break;
      }
   }
   if (*f == 0xFF)
   {
      return 0;
   }
   ReadRootDirectory(*f);
   filename = fname;
   leng = strlen(fname);
   for (i=0;i<leng;i++)
   {
      if (fname[i] == '/')
      {
         fname[i] = 0;
         if (!cwd(filename,*f))
         {
            gFiles[*f].Free = TRUE;
            return 0;
         }
         filename = fname+i+1;
      }
   }
   return filename;
}

void strfill(char *dest,char *source,int position)
{
   char *d;
   for(d=dest+position; *source!=0; d++, source++)
   {
      *d = *source;
   }
}

// Parameters: path, the path to the directory you
//             want to view
// Function    : Initializes file/dir listing
// Examples:
// strcpy(path,""); // the "path" to the root directory
// f = InitList(path);
// ...
// strcpy(path,"DIR3/DIR32/");
// f = InitList(path);
// if(InitList == MMC_OK)
// {
//   res = Listfiles(f);
//   CloseList(f);
// }
#ifdef ENABLE_FILELISTNG
MMCResponse InitList(char *path)
{
   char f;
   if(TryFile(path,&f) == 0)
   {
      return MMC_NOT_FOUND;
   }
   gFiles[f].Free = FALSE;   
   StartList.dirSector = gFiles[f].dirSector;
   StartList.CurrentCluster = gFiles[f].CurrentCluster;
   StartList.dirIdx = 0;
   CurrentList.dirSector = gFiles[f].dirSector;
   CurrentList.CurrentCluster = gFiles[f].CurrentCluster;
   CurrentList.dirIdx = 0;
   return f;
}

// Function: Lists a part (aka page) of the files in the directory
//           specified by InitList()
// Returns : The number of files/dirs that were listed
int8 ListFiles(char f)
{
   DIR *pDir;
   char filename[(CHARACTERS_IN_LONG_FILENAMES+1)]; // should be enough with 13+1
   char i,u,fni,len;
   BOOLEAN isLongFileName = FALSE;
   int32 nextcluster,actsector;

   if (f > (MAXFILES-1))
      return 0;

   if(changeList)
   {
      FreeList();
   }

   if((gFiles[f].CurrentCluster != CurrentList.CurrentCluster) || (gFiles[f].dirSector != CurrentList.dirSector))
   {
      gFiles[f].dirSector = CurrentList.dirSector;
      gFiles[f].CurrentCluster = CurrentList.CurrentCluster;   
      ReadSector(gFiles[f].dirSector,gFiles[f].IOpuffer);
   }
   gFiles[f].dirIdx = CurrentList.dirIdx;


   u=0;
   do
   {
      pDir = (DIR*)(&(gFiles[f].IOpuffer[32*(int16)gFiles[f].dirIdx]));
      for (i=gFiles[f].dirIdx;i<DIRENTRYS_PER_SECTOR;i++) // loop throu all direntrys in the sector
      {
         if ((pDir->sName[0] != 0xE5 && pDir->sName[0] != 0)) // if file/dir isn't deleted and isn't the end of the directory
         {
            if(pDir->bAttr != 0x0F) // Normal filename (8.3)
            {
               if(isLongFilename) // If this is the short version of the long filename, just save the number
               {
                  if(changeList)
                  {
                     FileList[u].shortName = malloc(13); // 8.3 = 8chars + '.' + 3chars + 0x00
                     FileList[u].isLong = TRUE;
                     ConvertFilename(pDir,filename);
                     strcpy(FileList[u].shortName,filename); // copy the 8.3 name of the file
                  }
                  u++;
                  isLongFilename = FALSE;
                  if(u == MAX_FILE_LIST)
                  {
                     gFiles[f].dirIdx = i+1;
                     return u;
                  }
               }
               else // normal 8.3 filename
               {
                  if(changeList)
                  {
                     ConvertFilename(pDir,filename);
                     FileList[u].name = malloc(strlen(filename)+1); // +1 for char 0x00
                     strcpy(FileList[u].name,filename);
                     FileList[u].shortName = FileList[u].name; // point to same string
                     FileList[u].isLong = FALSE;
                     if(pDir->bAttr & 0x10) // is directory
                        FileList[u].isDir = TRUE;
                     else
                        FileList[u].isDir = FALSE;
                  }

                  u++;
                  if(u == MAX_FILE_LIST)
                  {
                     gFiles[f].dirIdx = i+1;
                     return u;
                  }
               }
            }
            else if((pDir->bAttr & 0x0F) == 0x0F) // If it is a long filename entry
            {
               fni = (pDir->sName[0] & 0x3F); // Filename Index
               if((pDir->sName[0] & 0x40)) // First LongFilename entry, the last characters of a long filename
               {
                  if(changeList)
                  {
                     ConvertLongFilename(pDir,filename);
                     len = strlen(filename)+CHARACTERS_IN_LONG_FILENAMES*(fni-1); // Length of the long filename
                     FileList[u].name = malloc(len+1);// number of chars in this strinng + 13 in each other long filname entry
                     FileList[u].name[len] = 0x00; // set last char to 0
                     strfill(FileList[u].name,filename,(fni-1)*CHARACTERS_IN_LONG_FILENAMES); //Fills the name from position (fni-1)*13
                     if(pDir->bAttr & 0x10) // is directory
                        FileList[u].isDir = TRUE;
                     else
                        FileList[u].isDir = FALSE;
                  }
                  isLongFilename = TRUE;
               }
               else if((pDir->sName[0] & 0x80) == 0) // If it is a long filname, but not deleted
               {
                  if(isLongfilename && changeList)
                  {
                     ConvertLongFilename(pDir,filename);
                     strfill(FileList[u].name,filename,(fni-1)*CHARACTERS_IN_LONG_FILENAMES); //Fills the name from position (fni-1)*13
                  }
                  else
                     printf(lcd_putc,"NoLongFileName!");
               }
            }
         }
         if (pDir->sName[0] == 0)
         {
            gFiles[f].dirIdx = END_OF_DIR;
            return u;
         }
         pDir++;
      }
      nextcluster = GetNextCluster(gFiles[f].CurrentCluster);
      if (nextcluster != 0x0FFFFFFF && nextcluster != 0)
      {
         actsector = nextcluster + gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);
         gFiles[f].dirSector = actsector;
         gFiles[f].CurrentCluster = nextcluster;
         gFiles[f].dirIdx = 0;
      }
   } while (nextcluster != 0x0FFFFFFF && nextcluster != 0);
   gFiles[f].dirIdx = END_OF_DIR;
   return u;
}

// Function: Go to next page in the file/dir list
// Returns : MMCResponse
MMCResponse NextPage(char f)
{
   int32 nextcluster,actsector;
   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;

   CurrentList.dirSector = gFiles[f].dirSector;
   CurrentList.CurrentCluster = gFiles[f].CurrentCluster;

   if(gFiles[f].dirIdx == DIRENTRYS_PER_SECTOR)
   {
      nextcluster = GetNextCluster(gFiles[f].CurrentCluster);
       if (nextcluster != 0x0FFFFFFF && nextcluster != 0)
      {
         actsector = nextcluster + gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);

         CurrentList.dirSector = actsector;
         CurrentList.CurrentCluster = nextcluster;
         CurrentList.dirIdx = 0;
         return MMC_OK;
       }
      return MMC_INVALID_CLUSTER;
   }
   else if(gFiles[f].dirIdx == END_OF_DIR)
   {
      return MMC_END_OF_DIR; // Last file/dir have already been listed by ListFiles
   }
   else
   {
      CurrentList.dirIdx = gFiles[f].dirIdx;
   }
   return MMC_OK;
}

// Note: 0 = first page
MMCResponse SetPage(char f, int32 page)
{
   int32 i;
   MMCResponse res;
   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;

   CurrentList.dirSector = StartList.dirSector;
   CurrentList.CurrentCluster = StartList.CurrentCluster;
   CurrentList.dirIdx = StartList.dirIdx; // should always be 0

   changeList = FALSE; // this tells the ListFiles function to not change the list, just loop through files
   for(i=0;i<page;i++)
   {
      ListFiles(f);
      res = NextPage(f);
      if(res != MMC_OK)
      {
         changeList = TRUE;
         return res;
      }
   }
   changeList = TRUE;
   return MMC_OK;
}

MMCResponse CloseList(char f)
{
   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   gFiles[f].Free = TRUE;
   return MMC_OK;
}

void FreeList()
{
   int i;
   for(i=0;i<MAX_FILE_LIST;i++)
   {
      if(FileList[i].isLong)           // If it is a long filename, name and short name are different string
         free(FileList[i].shortName); // then free both
      else
         FileList[i].shortName = NULL;
      free(FileList[i].name);          // else free ONLY name(they point to same string..)
   }
}
#endif// ENABLE_FILELISTNG

// Function: Creates a file
MMCResponse fcreate(char f,char *fname)
{
   DIR *pDir;
   int32 actsector,actcl;
   int16 i;

   if (f > (MAXFILES-1))
   {
      return MMC_INVALID_FILE;
   }
   if (gFAT32Vars.gFirstDirEntryCluster == 0x0FFFFFFF)
   {
      // extend the directory file !!!
      gFAT32Vars.gFirstDirEntryCluster = FindFirstFreeCluster();
      gFAT32Vars.gFirstEmptyDirEntry = 0;
      SetClusterEntry(gFiles[f].CurrentCluster,gFAT32Vars.gFirstDirEntryCluster);
      SetClusterEntry(gFAT32Vars.gFirstDirEntryCluster,0x0FFFFFFF);
      actsector = gFAT32Vars.gFirstDirEntryCluster + gFAT32Vars.gFirstDataSector;
      for (i=0;i<512;i++)
         gFiles[f].IOpuffer[i] = 0;
      WriteSector(actsector,gFiles[f].IOpuffer);
   }
   actsector = gFAT32Vars.gFirstDirEntryCluster + gFAT32Vars.gFirstDataSector;
   ReadSector(actsector,gFiles[f].IOpuffer);
   pDir = (DIR*)(&(gFiles[f].IOpuffer[32*(int16)gFAT32Vars.gFirstEmptyDirEntry]));
   gFiles[f].dirSector = actsector;
   gFiles[f].dirIdx = gFAT32Vars.gFirstEmptyDirEntry;
   GetDOSName(pDir,fname);
   pDir->bAttr = 0;
   actcl = FindFirstFreeCluster();
   pDir->hCluster = actcl & 0xFFFF;
   pDir->hClusterH = actcl >> 16;
   SetClusterEntry(actcl,0x0FFFFFFF);
   pDir->wSize = 0;
   gFiles[f].position = 0;
   pDir->hDate = GetCurrentDOSDate();
   pDir->hTime = GetCurrentDOSTime();
   WriteSector(actsector,gFiles[f].IOpuffer);
   memcpy(&(gFiles[f].DirEntry),pDir,32);
   return MMC_OK;
}

int32 ComposeCluster(char f)
{
   int32 retval;

   retval = gFiles[f].DirEntry.hClusterH;
   retval <<= 16;
   retval |= gFiles[f].DirEntry.hCluster;
   return retval;
}

// Function: Opens a file with the specified mode
// Returns : A file handle or error code
MMCResponse fopen(char *fname, char mode)
{
   char found;
   char f;
   int32 actsector,actcluster,nextcluster;
   char *filename;

   if (!CardInserted())
      return MMC_NO_CARD_INSERTED;

   filename = TryFile(fname,&f);
   if (filename == 0)
   {
      return MMC_NOT_FOUND; // probebly invalid directory
   }
   found = FALSE;
   found = FindDirEntry(filename,f);

   if (!found)
   {
      if (mode == 'r')
      {
         gFiles[f].Free = TRUE;
         return MMC_NOT_FOUND;
      }
      else
      {
         if (fcreate(f,filename) != MMC_OK)
            return MMC_NOT_FOUND;
         found = TRUE;
      }
   }
   if (found)
   {
      gFiles[f].Free = FALSE;
      gFiles[f].mode = mode;
      if  (mode == 'a')
      {
         gFiles[f].position = gFiles[f].DirEntry.wSize;
         actcluster = ComposeCluster(f);
         while (actcluster != 0x0FFFFFFF && nextcluster != 0)
         {
            nextcluster = GetNextCluster(actcluster);
            if (nextcluster == 0x0FFFFFFF || nextcluster == 0)
               break;
            actcluster = nextcluster;
         }
         actsector = actcluster + gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);
         gFiles[f].CurrentCluster = actcluster;
         gFiles[f].posinsector = gFiles[f].position & 0x01FF;
         if (gFiles[f].posinsector == 0 && gFiles[f].position != 0)
            gFiles[f].posinsector = 512;
      }
      else
      {
         gFiles[f].position = 0;
         actsector = ComposeCluster(f);
         actsector += gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);
         gFiles[f].CurrentCluster = ComposeCluster(f);
         gFiles[f].posinsector = 0;
      }
   }
   return f;
}

// Function: closes a open file and makes it avavible for a new file
MMCResponse fclose(char f)
{
   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   if ((gFiles[f].mode == 'a') || (gFiles[f].mode == 'w'))
      fflush(f);
   gFiles[f].Free = TRUE;
   return MMC_OK;
}

// Function: writes the chach to the MMC
MMCResponse fflush(char f)
{
   int32 actsector;
   DIR *pDir;

   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   actsector = gFiles[f].CurrentCluster + gFAT32Vars.gFirstDataSector;
   WriteSector(actsector,gFiles[f].IOpuffer);
   ReadSector(gFiles[f].dirSector,gFiles[f].IOpuffer);
   pDir = (DIR*)(&(gFiles[f].IOpuffer[32*gFiles[f].dirIdx]));
   if (gFiles[f].DirEntry.bAttr & 0x10)  // if it is a directory
      pDir->wSize = 0;
   else
      pDir->wSize = gFiles[f].position;
   pDir->hDate = GetCurrentDOSDate();
   pDir->hTime = GetCurrentDOSTime();
   WriteSector(gFiles[f].dirSector,gFiles[f].IOpuffer);
   ReadSector(actsector,gFiles[f].IOpuffer);
   return MMC_OK;
}

// Function: Enter a specified directory
char cwd(char *fname, char f)
{
   int32 actsector;
   if (f > (MAXFILES-1))
   {
      return FALSE; // just in case of overaddressing
   }
   if (IsSelfDir(fname))
   {
      return TRUE; // already in Root dir
   }
   if (!FindDirEntry(fname,f))
   {
      return FALSE; // not found
   }

   actsector = ComposeCluster(f);
   actsector += gFAT32Vars.gFirstDataSector; // read current dir
   ReadSector(actsector,gFiles[f].IOpuffer);
   gFAT32Vars.gDirEntrySector = actsector;
   gFiles[f].dirSector = actsector;
   gFiles[f].CurrentCluster = ComposeCluster(f);

   return TRUE;
}

// Function: Put a char to the open file
MMCResponse fputch(char be, char f)
{
   int32 nextcluster,actsector;

   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   if (gFiles[f].posinsector == 512)
     {
      actsector = gFiles[f].CurrentCluster + gFAT32Vars.gFirstDataSector;
      WriteSector(actsector,gFiles[f].IOpuffer);
      nextcluster = FindFirstFreeCluster();
      if (nextcluster != 0x0FFFFFFF && nextcluster != 0)
      {
         SetClusterEntry(gFiles[f].CurrentCluster,nextcluster);
         SetClusterEntry(nextcluster,0x0FFFFFFF);
         actsector = nextcluster + gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);
         gFiles[f].CurrentCluster = nextcluster;
         gFiles[f].posinsector = 0;
      }
   }
   gFiles[f].IOpuffer[gFiles[f].posinsector] = be;
   gFiles[f].posinsector++;
   gFiles[f].position++;
   return MMC_OK;
}

// Function: Puts a string to the open file
MMCResponse fputstring(char *be, char f)
{
   int16 leng,i;

   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   leng = strlen(be);
   for (i=0;i<leng;i++)
       fputch(be[i],f);
     
   return MMC_OK;
}

// Function: Read a buffer from the open file
int16 fread(char *buffer, int16 leng, char f)
{
   int16 i,retv;
   char c,v;

   if (f > (MAXFILES-1))
      return 0;
   retv = 0;
   for (i=0;i<leng;i++)
   {
      v = fgetch(&c,f);
      if (v == MMC_OK)
      {
         buffer[i] = c;
         retv++;
      }
      else
         break;
   }
   return retv;
}

// Function: Write a buffer to the open file
MMCResponse fwrite(char *buffer, int16 leng, char f)
{
   int16 i;

   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   for (i=0;i<leng;i++)
      fputch(buffer[i],f);
   return MMC_OK;
}

// Function: Read a char from the open file
MMCResponse fgetch(char *ki,char f)
{
   int32 nextcluster,actsector;

   if (f > (MAXFILES-1))
      return MMC_INVALID_FILE;
   if (gFiles[f].position >= gFiles[f].DirEntry.wSize)
      return MMC_INVALID_POSITION;
   *ki = gFiles[f].IOpuffer[gFiles[f].posinsector];
   gFiles[f].posinsector++;
   gFiles[f].position++;
   if (gFiles[f].posinsector == 512)
   {
      nextcluster = GetNextCluster(gFiles[f].CurrentCluster);
      if (nextcluster != 0x0FFFFFFF && nextcluster != 0)
      {
         actsector = nextcluster + gFAT32Vars.gFirstDataSector;
         ReadSector(actsector,gFiles[f].IOpuffer);
         gFiles[f].CurrentCluster = nextcluster;
         gFiles[f].posinsector = 0;
      }
   }
   return MMC_OK;
}

// Function: Removes a file
MMCResponse remove(char *fname)
{
   char i,found;
   char f;
   DIR *pDir;
   int32 nextcluster,currentcluster;
   char *filename;

   filename = TryFile(fname,&f);
   if (filename == 0)
      return MMC_NOT_FOUND;
   found = FindDirEntry(filename,f);
   if (!found)
   {
      gFiles[f].Free = TRUE;
      return MMC_NOT_FOUND;
   }

   pDir = (DIR*)(&(gFiles[f].IOpuffer[32*(int16)gFAT32Vars.gDirEntryIdx]));
   pDir->sName[0] = 0xE5;
   for (i=1;i<8;i++)
      pDir->sName[i] = ' ';
   for (i=0;i<3;i++)
      pDir->spam[i] = ' ';
   WriteSector(gFAT32Vars.gDirEntrySector,gFiles[f].IOpuffer);
   currentcluster = ComposeCluster(f);
   while (currentcluster != 0x0FFFFFFF && nextcluster != 0)
   {
      nextcluster = GetNextCluster(currentcluster);
      ClearClusterEntry(currentcluster);
      currentcluster = nextcluster;
   }
   ClearClusterEntry(currentcluster);
   SetClusterEntry(currentcluster,0);
   currentcluster = gFAT32Vars.gStartSector+DiskInfo.Reserved1 + gFAT32Vars.FATstartidx;
   WriteSector(currentcluster,FATTable);
   currentcluster += DiskInfo.hSectorsPerFat;
   WriteSector(currentcluster,FATTable);
   gFiles[f].Free = TRUE;

   return MMC_OK;
}


// Function: Gets the size of a file
MMCResponse getfsize(char *fname, int32 *fsiz)
{
   char found;
   char f;
   DIR *pDir;
   char *filename;

   filename = TryFile(fname,&f);
   if (filename == 0)
      return MMC_NOT_FOUND;
   found = FindDirEntry(filename,f);
   if (!found)
   {
      gFiles[f].Free = TRUE;
      return MMC_NOT_FOUND;
   }
   pDir = (DIR*)(&(gFiles[f].IOpuffer[32*(Int16)gFAT32Vars.gDirEntryIdx]));
   gFiles[f].Free = TRUE;
   *fsiz = pDir->wSize;
   return MMC_OK;
}



MMC_SPI_FAT32.h

Code:

#define MAXFILES 1 // This define specifies the maximum number
               // of simultaneously open files, more files
               // requires more ram. The maximun number of
               // this define is 8, this is because of my
               // error handlig.. but that should be more
               // then enough..

// This enable functions and variables needed for filelisting
// If you aren't going to use it, comment this line out to
// save some RAM
#define ENABLE_FILELISTNG

typedef struct _diskinforec
{
   char   hJumpCode[3];
   char  OEMName[8];
   int16   hBytesPerSector;
   char   bSectorsPerCluster;
   int16 Reserved1;
   char   FATCopies;
   int16 hMaxRootEntries;
   int16 hSectors;
   char   Descriptor;
   int16 holdSectorsPerFat;
   int16 hSectorsPerTrack;
   int16 hNumberofHeads;
   int32   hNumberofHidden;
   int32   hNumberofSectors;

   int32 hSectorsPerFat;
   int16 hFlags;
   int16 hFAT32Version;
   int32 hRootStartCluster;
} diskinforec;

typedef struct _direntry
{
   char   sName[8];
   char   spam[3];
   char   bAttr;
   char   bReserved[8];
      int16 hClusterH;
   int16   hTime;
   int16   hDate;
   int16   hCluster;
   int32   wSize;
} DIR;

typedef struct
{
   char    IOpuffer[512];
   DIR    DirEntry;
   int32 CurrentCluster;
   int16 posinsector;
   int32   position;
   int32 dirSector;
   int8   dirIdx;
   char   mode;
   BOOLEAN   Free;
} FILE;

typedef struct
{
   int32 MMCAddress;
   int32 FATstartidx;
   int32 gStartSector;
   int32 gFirstDataSector;
   int8 gDirEntryIdx;
   int32 gDirEntrySector;
   int8 gFirstEmptyDirEntry;
   int32 gFirstDirEntryCluster;
} FAT32Vars;

typedef struct
{
   unsigned long   Year;
   char         Month;
   char            Day;   
   char            Hour;   
   char            Minute;     
   char            Second;     
} TimeRecord;

typedef struct
{
   int32 dirSector;
   int32 CurrentCluster;
   int dirIdx;
} ListPos;

typedef struct
{
   char *name;
   char *shortName;
   BOOLEAN isDir;
   BOOLEAN isLong;
} LongFileName;

typedef char MMCResponse;

MMCResponse MMCInit();
MMCResponse ReadSector(int32 sector, char *hova);
MMCResponse WriteSector(int32 sector, char *honnan);

void      InitFAT();
char      FindDirEntry(char *fname, char f);

#ifdef ENABLE_FILELISTNG
   MMCResponse InitList(char *path);
   int8      ListFiles(char f);
   MMCResponse NextPage(char f);
   MMCResponse SetPage(char f, int32 page);
   MMCResponse CloseList(char f);
   void      FreeList();
#endif

MMCResponse fopen(char *fname, char mode);
MMCResponse fclose(char f);
MMCResponse fflush(char f);
char      cwd(char *fname, char f);
MMCResponse fputch(char be, char f);
MMCResponse fgetch(char *ki, char f);
MMCResponse fputstring(char *be, char f); // fputs is reserved in CCS C
int16      fread(char *buffer, int16 leng, char f);
MMCResponse fwrite(char *buffer, int16 leng, char f);
MMCResponse remove(char *fname);
MMCResponse getfsize(char *fname, int32 *fsiz);
[/url]
Ttelmah



Joined: 11 Mar 2010
Posts: 19375

View user's profile Send private message

PostPosted: Thu Mar 14, 2013 4:15 am     Reply with quote

Ignoring the code for now, what is the chip you have between the PIC and the MMC card?. Can't read the number for sure in the picture. Looks like 4050?.

There are problems with the circuit though. SPI, _requires_ the pull-ups on the lines. Different reasons on different lines, but the card SDO line must have one to avoid it floating when the card is not there, or deselected (you have this), while on the other lines they ensure (first) in the case of the clock line that it is high before the chip wakes up, and on both the SDI, and clock lines, they just speed the rising edges a fraction. You need at least a pull up on the line between the PIC and the buffer you are using, so that when the PIC is waking, and isn't yet driving the line it goes high.

There is then the big problem. The DO line _will not reliably pull the signal high enough to be used as the SPI input on a 5v PIC. The PIC SDI input requires the signal to go up to 4v, when running from 5v.

Then if this is a 4050, presumably it is being driven from 3.3v?. If so, it's inputs will be being driven above it's supply rail. It's inputs clamp at supply+0.5v. Result lots of current drawn on the PIC outputs, and potential problems....

Seriously, throw away the circuit.
Either use resistive dividers from the PIC outputs to the SD card pins, or add a proper level translator chip in this direction. Then going the other way, use a 5v buffer with a warranted TTL input threshold, or some other circuit to bring the signal up to the required level.

Get the hardware right before worrying about the code.....

Best Wishes
thenorthstar



Joined: 06 Mar 2010
Posts: 24

View user's profile Send private message

PostPosted: Thu Mar 14, 2013 7:29 am     Reply with quote

First of all, thank you for your concern
I used to M54HC4050 chip voltage levels. I found this too from the internet.
The problem caused by from hardware.?
If so, Can you recommend me a schema.

http://www.datasheetcatalog.org/datasheet2/c/0hy5pjjfi77eduq1s8sq1ii7y07y.pdf


Very nice work with FAT16 when I try the same circuit. However, working with FAT32.

Experiment with FAT16

ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Mar 14, 2013 3:12 pm     Reply with quote

For some example schematics you can have a look at the website of Brush Electronics from one our other forum members, Andrew.

Easiest solution to get the interface working is to change your PIC to 3.3V, perhaps you need the LF version of the PIC instead of the 'F' version, but Proteus doesn't care. That your schematic is running this far probably has to do with the bad simulation of Proteus too.

I do see the text "Hello" in the failed FAT32 version you posted, but it is written with two bytes for each character instead of 1.

A long shot, but this could have to do with your Windows language settings. I don't know which country you are from, is it a Scandinavian language?
Like I said, a long shot, but I suspect your computer is running with another code page setting than ANSI code page 1252 as used for English and most European languages.

The editor you are using, is it set to save the source code as pure ASCII? When set to UTF-16 that would explain the corrupted file contents.
farouk_baya



Joined: 18 Jun 2010
Posts: 27

View user's profile Send private message

PostPosted: Tue Mar 24, 2015 10:31 am     Reply with quote

Hello,

I'm using the same code with ISIS simulation. I have the file created but the data are "0000000000000".

Anybody have an idea?

Thanks.
temtronic



Joined: 01 Jul 2010
Posts: 9176
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Mar 24, 2015 10:40 am     Reply with quote

THE solution has been given..

Use a 3V PIC !! Any of the xxLFyyyy WILL work 'out of the box'.

Your 'interface' will NEVER work and software(code) can NEVER make it work...

Please, BUY an 'L' PIC.

Jay
fbtech



Joined: 25 Mar 2015
Posts: 7

View user's profile Send private message

PostPosted: Wed Mar 25, 2015 10:19 am     Reply with quote

Thanks.

Everything is OK.
The problem was the configuration when I formated the SD.
mdemuth



Joined: 16 Apr 2007
Posts: 71
Location: Stuttgart, Germany

View user's profile Send private message Visit poster's website

PostPosted: Thu Apr 02, 2015 1:36 am     Reply with quote

I am using PIC18F46K22 with 3.3V supply and CCS Version 5.040) trying to get your files running for my project with no success.
Terminal output is:

MMC CONTROL MMC init OK
FAT init OK
Creating Files
Created SAMPLE.TXT
Writing Began
Written data=Hello World
Writing Done

But nothing on the MMC when I put it into my PC.
How did you format the SD Card and which type did you use?
Thanks for help.
Ttelmah



Joined: 11 Mar 2010
Posts: 19375

View user's profile Send private message

PostPosted: Thu Apr 02, 2015 2:21 am     Reply with quote

Lets step through the various problems people have with SD.

1) (Commonest), trying to use an SD with a 5v PIC without the proper interfacing. Hurrah!. You've avoided this one. Smile

2) Card size. The standard CCS supplied code, is for SD, not SDHC. 2GB or smaller cards. There is a patch for SDHC, in the code library. There were a few 4GB SD cards made, but these were a temporary 'rarity'. So if your card is larger than 2GB, this may be the problem.

3) Format. The standard CCS drivers are written to use a card formatted effectively like a floppy. This was how quite a few cameras format the cards, but Windows by default does not now format them this way (there are free downloadable programs that will format the cards like this - look for programs that talk about formatting SD for cameras). Alternative is to let the CCS drivers format the card. There is also a patch to support the hard disk format in the code library.

4) Speed. SD requires the SPI bus to change speed after 'asking' the card what speeds are supported. Some third party codes try to ignore this. It'll work with some cards, but not with others.

5) Resistors. Even with a 3.3v PIC, certain resistors are still needed on the bus. The following lines should all be pulled up. CS. To ensure it goes _high_ immediately, before the SD card actually wakes. DI, DO, and CLK. There are slightly different reasons. On all the lines, the resistors help improve the rising edge speeds. On the DI line, it again ensures that the card wakes in the right mode when power is applied. On DO, it ensures the PIC sees the line as 'high' when the card is not there. 10KR on all is in spec.

6) Power. The SD card draws quite surprising currents at times. Just for a moment during writes etc.. There can be spikes up to about 200mA, and unless there is very good smoothing close to the card this can cause problems. I use a 100uF OSCON paralleled with 0.1uF ceramic, right adjacent to the card connector, and have never seen problems.

I'd suspect 2 or 3, but look at all (except 1...).
temtronic



Joined: 01 Jul 2010
Posts: 9176
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Apr 02, 2015 5:14 am     Reply with quote

hmm...
Isn't his PIC SPI input 'wrong'? He's got a pullup tied to 3v3, yet using a 5V PIC. pretty sure the SPI input is Schmitt type, needs 80% of Vdd, so 4 volts.
Now I admit I haven;t wired up that config and tested it but .............

Jay
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Apr 02, 2015 5:43 am     Reply with quote

temtronic wrote:
hmm...
Isn't his PIC SPI input 'wrong'? He's got a pullup tied to 3v3, yet using a 5V PIC. pretty sure the SPI input is Schmitt type, needs 80% of Vdd, so 4 volts.
Be careful, this thread has now been hijacked by two different people.

The last poster, mdemuth, is using a 3.3V PIC.
The pull-up is not for 5V/3.3V adaptation but is required because the MMC/SD cards start in an open-collector output-mode. Only after the init-phase has passed this is switched to an active driven output where the pull-up has little influence.
temtronic



Joined: 01 Jul 2010
Posts: 9176
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Apr 02, 2015 6:57 am     Reply with quote

Thanks for info ! I haven't used SD card(PITA) used Vinculum based USB flashdrive when I needed a logger. It was a whole lot easier, client got unit in less than a week.

Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19375

View user's profile Send private message

PostPosted: Fri Apr 03, 2015 1:47 am     Reply with quote

I have to just put 'in perspective' the 'PITA' comment. Smile

I've used SD for several years on the PIC. First circuit with a 5v PIC, level translators and the CCS code. It worked. Then switched to 3.3v PIC's and discovered just how much easier these were. Then needed SDHC. I looked at going DIY (at this time the patch wasn't there for the CCS drivers), but time was important, so bought the Brush drivers.
In every case I managed to get the card working without problems.
None of the cards has taken more than a very few minutes work to actually get going.The first unit I did, had the card working in less than 48 hours, including making the PCB. I do implement things that are not normally thought of (since my cards are usually 'logging' with writes at intervals I always have an 'eject mode' switch - sometimes just on the cover that opens to allow access to the card, and a 'ready' LED. So you open the cover, and the LED changes from red to green a few mSec later, and you then take the card out. When the LED is green, the logging code has flushed any pending writes, to ensure the file system is clean before you remove the card. This is particularly important since I don't actually write to the card till I have a complete page of data ready. Also have the WP detection available as well, and warnings about this.

The PITA comment, really is slightly unfair, I'm sure if Temtronic actually used an SD with the PIC, he'd not find it that hard. The problem is that so many people 'plunge' in without taking the time to actually investigate what is needed, perhaps using faulty 'designs' that have (unfortunately) been published on the web....
temtronic



Joined: 01 Jul 2010
Posts: 9176
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Apr 03, 2015 5:08 am     Reply with quote

OK, IF you use a 3V rated PIC , it's really straight forward, have to agree but 99% of the applications here seam to deal with 5V PICs.
I have the same response with other 3V peripherals like GPSes(sp), WIFIs, etc. The technology 'favours' the 3V market, so 3V PICs should be the first choice. As well, for the penny pinchers there's less parts to buy, stuff onto a PCB,inventory, troubleshoot,etc.
I suppose these days every PC comes with an SD card reader. Mine didn't,it's old like me and has real comports. Using the Vinc/Flashdrive made a quick easy logger for the client. Also, at the time the SD driver was limited to <2GB.I could have crammed in the data,or modified the driver but with FD I could save the data in dotCSV format which allowed client to instantly open as a spreadsheet. Something he really likes.

Life could be made a LOT simpler and more fun if the posters used 3 Volt PICs.

Temtronic
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group