Writing into a SD card over SPI with PIC18F25K80

Discussion in 'Embedded Systems and Microcontrollers' started by Sangam Singh, Jun 23, 2015.

  1. Sangam Singh

    Thread Starter New Member

    Jun 23, 2015
    9
    0
    I have, in the code below, initialized the SD card and have found the address of the Root section. I now want to write data into the SD card. I am stuck at this point as to how should i use this info to write. I am refering to this site for information on SD card operation. I am attaching my code below.


    Code (Text):
    1. #include <xc.h>
    2. #include <p18cxxx.h>
    3. #include <stdio.h>
    4. #include <stdlib.h>
    5. #include <plib/pconfig.h>
    6. #include <spi.h>
    7.  
    8. void init_Device(void) //Initializes the device, setting the    scialltor    speed, pin direction, and pull-ups
    9. {
    10.       OSCCON=0b01110111; //Oscillator 8 Mhz
    11.       TRISA=0; // all Port A output
    12.       TRISB=0; // all Port B output
    13.       TRISB5=1; // make serial port reception pin input
    14.       TRISB4=1; //make SDI reception pin input
    15.       TRISC=0; // all Port C output
    16.       TRISC3=1; // Make RC3 input
    17.       PEIE=1; //enable interrupts for RCIF
    18.       SBOREN=0; //disable brown out reset
    19. }
    20.  
    21. void init_SPI(void)
    22. {
    23.     CKP=0; //0=idle clock state is low
    24.     CKE=1; //0=Data transmitted on falling edge of SCK
    25.     SMP=1; //1=SPI mode-Input data sampled at end of data output time
    26.     SSPM3=0; //FOSC/64
    27.     SSPM2=0; //FOSC/64
    28.     SSPM1=0; //FOSC/4 - "1" for /64
    29.     SSPM0=0; //FOSC/64
    30. }
    31.  
    32. void Delay(long x)
    33. {
    34.     while (x>0){x--;}
    35. }
    36.  
    37.      void InitializeSPIMode(void)
    38.      {
    39.         char x; //used for "while" loops
    40.         unsigned long Address=0;
    41.         unsigned short BytesPerSector=0;
    42.         char ReservedSectors=0;
    43.         char FATCount=0;
    44.         unsigned short SectorsPerFat=0;
    45.         unsigned long FatSpace=0;
    46.  
    47.        char AddressL=0; //Low byte of address
    48.       char AddressM=0; //Mid byte of address
    49.       char AddressH=0; //High byte of address
    50.  
    51.       Delay(25000); //Wait one millisecond
    52.  
    53.       //////////////// Slow Oscillator/SPI down for initialization ///////////////
    54.  
    55.      OSCCON=0b01000111; //Oscillator 8 Mhz 0b01110111 for 8mhz
    56.      SSPM1=1; //SPI - FOSC/64
    57.  
    58.        //////////////////// Initialize SPI Mode ///////////////////
    59.      Delay(1);
    60.      WriteSPI(0xFF);
    61.      WriteSPI(0xFF);
    62.      WriteSPI(0xFF);
    63.      WriteSPI(0xFF);
    64.      WriteSPI(0xFF);
    65.      WriteSPI(0xFF);
    66.      WriteSPI(0xFF);
    67.      WriteSPI(0xFF);
    68.      WriteSPI(0xFF);
    69.      WriteSPI(0xFF); //Wake up the card (80 clock pulses)
    70.  
    71.      RA5=0; Delay(5);//Assert CS
    72.  
    73.      WriteSPI(0x40);
    74.      WriteSPI(0x00);
    75.      WriteSPI(0x00);
    76.      WriteSPI(0x00);
    77.      WriteSPI(0x00);
    78.      WriteSPI(0x95); //CMD0
    79.      WriteSPI(0);
    80.      WriteSPI(0);
    81.  
    82.          WriteSPI(0x48);
    83.          WriteSPI(0x00);
    84.          WriteSPI(0x00);
    85.          WriteSPI(0x01);
    86.          WriteSPI(0b10101010);
    87.          WriteSPI(0x87); //CMD8
    88.          WriteSPI(0);
    89.          WriteSPI(0);
    90.  
    91.          while(SSPBUF!=0) //ACMD 41 to initialize SD Card - keep doing until you get 0 meaning it's not busy
    92.         {
    93.           RA5=1; //deassert CS
    94.           Delay(5);
    95.           RA5=0; //assert CS
    96.  
    97.        WriteSPI(0xFF);
    98.  
    99.        WriteSPI(0b0111011);
    100.         WriteSPI(0x00);
    101.         WriteSPI(0x00);
    102.         WriteSPI(0x00);
    103.        WriteSPI(0x00);
    104.        WriteSPI(0xFF); //CMD55
    105.        WriteSPI(0xFF);
    106.        WriteSPI(0xFF);
    107.  
    108.        RA5=1; //deassert CS
    109.        RA5=0; //assert CS
    110.  
    111.        WriteSPI(0xFF);
    112.        WriteSPI(0b01101001);
    113.        WriteSPI(0b00000000);
    114.        WriteSPI(0b00000000);
    115.        WriteSPI(0x00);
    116.        WriteSPI(0x00);
    117.        WriteSPI(0xFF); //ACMD41
    118.        WriteSPI(0xFF);
    119.        WriteSPI(0xFF);
    120.     }
    121.  
    122.       /////////// Speed Oscillator and SPI back up after initialization  ///////////
    123.  
    124.      OSCCON=0b01110111; //Oscillator 8 Mhz 0b01110111 for 8mhz
    125.      SSPM1=0;
    126.  
    127.     ///////////// Find Address of FAT16 Partition Entry ////////
    128.  
    129.      RA5=1; //deassert CS
    130.      RA5=0; //assert CS
    131.  
    132.      WriteSPI(0xFF);
    133.  
    134.      WriteSPI(0b01010000);
    135.      WriteSPI(0);
    136.      WriteSPI(0);
    137.      WriteSPI(0);
    138.      WriteSPI(4);
    139.      WriteSPI(0xFF); //CMD16 4 byte block - want a return of "0"
    140.      WriteSPI(0xFF);
    141.      WriteSPI(0xFF);
    142.      WriteSPI(0xFF);
    143.  
    144.      WriteSPI(0b01010001);
    145.      WriteSPI(0x00);
    146.      WriteSPI(0x00);
    147.      WriteSPI(0x01);
    148.      WriteSPI(0xC6);
    149.       WriteSPI(0xFF); //CMD17 (Read Single Block) - want a response of XFE  signaling that data is coming
    150.  
    151.       while(SSPBUF!=0xFE) //Keep clocking until we get valid info (Follows 0xFE)
    152.      {
    153.         WriteSPI(0xFF);
    154.      }
    155.  
    156.      WriteSPI(0xFF);
    157.      Address=SSPBUF; //Loads LSB of address
    158.      WriteSPI(0xFF);
    159.      Address=Address+SSPBUF*256; //loads second bytes into address
    160.      WriteSPI(0xFF);
    161.      AddressH=Address+SSPBUF*65536; //loads third bytes into address
    162.      WriteSPI(0xFF);
    163.      WriteSPI(0xFF); //two dummy blocks at end to get through check sums
    164.      WriteSPI(0xFF);
    165.  
    166.       ////////////// Find Address of Root //////////////
    167.  
    168.       RA5=1; //deassert CS
    169.       Delay(5);
    170.       RA5=0; //assert CS
    171.  
    172.      Address=Address*2; //Since address is in sectors, multiply by 2 then shift a byte over
    173.      Address=Address<<8;
    174.      AddressL=Address;
    175.      AddressM=Address>>8;
    176.      AddressH=Address>>16;
    177.  
    178.      WriteSPI(0b01010000);
    179.      WriteSPI(0);
    180.      WriteSPI(0);
    181.      WriteSPI(0);
    182.      WriteSPI(13);
    183.      WriteSPI(0xFF); //CMD16 13 byte block - want a return of "0"
    184.      WriteSPI(0xFF);
    185.      WriteSPI(0xFF);
    186.      WriteSPI(0xFF);
    187.  
    188.      WriteSPI(0b01010001);
    189.      WriteSPI(0);
    190.      WriteSPI(AddressH);
    191.      WriteSPI(AddressM);
    192.      WriteSPI(11);
    193.      WriteSPI(0xFF); //CMD17 (Read single Block) - want a response of XFE    signaling that data is coming
    194.  
    195.     while(SSPBUF!=0xFE) //Keep clocking until we get valid info (Follows 0xFE)
    196.     {
    197.       WriteSPI(0xFF);
    198.     }
    199.  
    200.     WriteSPI(0xFF);
    201.     BytesPerSector=SSPBUF; //LSB of Bytes per Sector
    202.     WriteSPI(0xFF);
    203.     BytesPerSector=BytesPerSector+SSPBUF*256; //MSB of Bytes per sector
    204.     WriteSPI(0xFF); //sectors per cluster, unused
    205.     WriteSPI(0xFF);
    206.     ReservedSectors=SSPBUF; //LSB of reserved sectors
    207.     WriteSPI(0xFF); //MSB of reserved sectors (ignore)
    208.     WriteSPI(0xFF);
    209.     FATCount=SSPBUF; //number of FATs
    210.     WriteSPI(0xFF); //number of root entries, unused
    211.     WriteSPI(0xFF); //number of root entries, unused
    212.     WriteSPI(0xFF); //small sectors, unused
    213.     WriteSPI(0xFF); //small sectors, unused
    214.     WriteSPI(0xFF); //Media Type, unused
    215.     WriteSPI(0xFF);
    216.     SectorsPerFat=SSPBUF; //LSB of sectors per FAT
    217.     WriteSPI(0xFF);
    218.     SectorsPerFat=SectorsPerFat+SSPBUF*256; //MSB of sectors per FAT
    219.     WriteSPI(0xFF); //Two dummy bytes to clear the CRC
    220.     WriteSPI(0xFF);
    221.  
    222.     Address=Address+BytesPerSector*ReservedSectors; //Adds the number of    reserved sectors to the starting address
    223.     FatSpace=FATCount;
    224.     FatSpace=FatSpace*BytesPerSector;
    225.     FatSpace=FatSpace*SectorsPerFat;
    226.  
    227.     Address=Address+FatSpace; //add FAT data space to the address to get to the    root directory
    228.  
    229.  
    230.  
    231.       /****Writing into the disk*****/
    232.  
    233.       WriteSPI(0xFE);
    234.       int i;
    235.       for(i=0;i<400;i++)
    236.        WriteSPI(0xDE);
    237.  
    238.      }
    239.  
    240.      void main(void){
    241.  
    242.      init_Device(); //initialize device
    243.      init_SPI(); //initialize SPO module
    244.      PORTA=0;
    245.      PORTB=0;
    246.      PORTC=0;
    247.  
    248.      RB6=0; //Set clock to low
    249.      RA5=1; //set CS to high
    250.  
    251.      InitializeSPIMode();
    252.  
    253.      for(;;)
    254.      {
    255.      }
    256. }
     
  2. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,605
    Do yourself a favor and dig thru Microchip's application libraries and find their code for doing this. You will get a FAT compliant file system, meaning you can take the SD card out of your PIC and plug it into your PC and read and write to it there.

    I've done this a dozen times so far and only had trouble on the very first one where I naively connected the OUT to OUT and In to IN on the SPI lines.

    Unfortunately, since Microchip "improved" their libraries I can no longer find the awesome code I once used so easily. Perhaps going back to the archives would help.
     
  3. Sangam Singh

    Thread Starter New Member

    Jun 23, 2015
    9
    0
    I did check the archived libraries but the problem with them i am having is that when i compile the code i am getting the makefle error. On referring i got that it is getting confused between XC8 and C18 compiler. Presently I am using XC8 compiler but the libraries are for C18 compilers.
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,605
    The C18 compiler is still available. Ive been using that for years now with no issues.
     
  5. Sangam Singh

    Thread Starter New Member

    Jun 23, 2015
    9
    0
    I have my entire code in XC8, making the entire code C18 compatible will be a big trouble now. Is there a way I can write into the card using XC8 compiler.
     
  6. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,605
    The Microchip MPLAB Harmony Integrated Software Framework has this code. You will just have to dig thru it and find it for yourself.

    They do have some sample apps you can study to see how to use it.
     
  7. Sangam Singh

    Thread Starter New Member

    Jun 23, 2015
    9
    0
    he Microchip MPLAB Harmony Integrated Software Framework works with XC32 and not with XC8 or C18. I shifted my project to C18 so that I can use the MDD libraries but the I am getting a weird problem. It is not able to include the header file even though it exists in the directory.

    Code (Text):
    1. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:38:Error [1027] unable to locate 'Compiler.h'
    2. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:39:Error [1027] unable to locate 'HardwareProfile.h'
    3. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:40:Error [1027] unable to locate 'MDD File System/SD-SPI.h'
    4. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:41:Error [1027] unable to locate 'MDD File System/CF-PMP.h'
    5. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSDefs.h:38:Error [1027] unable to locate 'GenericTypeDefs.h'
    6. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:38:Error [1027] unable to locate 'Compiler.h'
    7. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:39:Error [1027] unable to locate 'HardwareProfile.h'
    8. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:40:Error [1027] unable to locate 'MDD File System/SD-SPI.h'
    9. C:\Program Files (x86)\Microchip\mplabc18\v3.47\h\FSconfig.h:41:Error [1027] unable to locate 'MDD File System/CF-PMP.h'
    That is the error.
     
  8. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,605
    When using C18 inside MPLAB you need to add the oddball paths by hitting Project in the menu and choose Build Options | Project, and on the directories tab "Show directories for:" select "Include Search Path" and add the folder where each of those resides. If multiple files reside in the same area you need to include it just once.

    MPLAB-X must have something similar but I am not as familiar with that IDE as of yet.

    If you simply do not have these files they are all available for downloading from the legacy Microchip Applications Library (MAL)

    http://www.microchip.com/pagehandler/en-us/devtools/mla/legacy-mla.html

    (MPLAB and C18 are by BFF.)
     
    Last edited: Jun 24, 2015
    Sangam Singh likes this.
  9. Sangam Singh

    Thread Starter New Member

    Jun 23, 2015
    9
    0
    I swtiched to MPLAB and C18. I downloaded the Legacy MLA library.
    I moved all the required header files(.h) and .c file to the separate folder and set the build path to it. I am still having issues with the code. I am putting forth how I exactly did it all. If you maylet me know the if I am doing something wrong

    This is how I am placing the files in a folder.
    Screenshot 2015-06-25 14.40.42.png
    Screenshot 2015-06-25 14.40.52.png

    This is how i included the search paths.
    Capture.PNG

    And this is my code. (I have excluded the Configuration bits.)

    Code (Text):
    1. // Header Files
    2. #include <p18F25K80.h>
    3. #include <stdio.h>
    4. #include <stdlib.h>
    5. #include <spi.h>
    6. #include <FSIO.h>
    7.  
    8. #define bfrSize 5
    9.  
    10. void main(void)
    11.     {
    12.     FSFILE *pOldFile;
    13.     FSFILE *pNewFile;
    14.     char myData[20];
    15.     char bfr [6];
    16.     int bytesRead, bytesWritten;
    17.     char newFile[] = "newfile.txt";
    18.     char writeArg = 'w';
    19.     // Must initialize the FAT16 library. It also initializes SPI and other related pins.
    20.     while( !FSInit() )
    21.     // Failed to initialize FAT16 – do something…
    22.     //return 1; // Card not present or wrong format
    23.     // Create a new file
    24.     pNewFile = FSfopen (newFile, 'w');
    25.     // Open an existing file to read
    26.     pOldFile = FSfopenpgm ("myfile.txt", 'r');
    27.  
    28.     // Read 10 bytes of data from the file.
    29.     bytesRead = FSfread((void*)myData, 10, 1, pOldFile);
    30.     // read bfrSize (5) items (of size 1 byte). returns items count
    31.     bytesRead = FSfread( (void *)bfr, 1, bfrSize, pOldFile );
    32.     // Write those fifteen bytes to the new file
    33.     bytesWritten = FSfwrite ((void *) myData, 10, 1, pNewFile);
    34.     bytesWritten = FSfwrite ((void *) bfr, 1, bfrSize, pNewFile);
    35.     // After processing, close the file.
    36.     FSfclose( pOldFile );
    37.     FSfclose (pNewFile);
    38. }

    - Thanks.
     
  10. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,392
    1,605
    I've never had to move these files around, I reference them from where they live in the MAL folders. That is especially true as the relative paths are sometimes hard coded into Microchip's code.

    The sole exception to this is I believe the fs configuration file, which is custom to your project. I don't remember offhand which files have to be customized (and thus should live in your main project folder)

    Sorry to say I don't have this setup where I am and I am leaving the country for a vacation tomorrow, and I doubt I will have time to look for you befoer I go. But you should be able to find some reference projects inside the MLA that can be used as a guide.
     
Loading...