Question

I'm attempting to use FatFS (http://elm-chan.org/fsw/ff/00index_e.html) as a means to communicate with an SD card, using SPI.

The FatFS website has a number of examples, however I'm not finding them easy to understand or follow. Two examples apply to me in the downloadable zip, one for 'generic' microcontrollers and another for a PIC24. Although the PIC24 would seem ideally similar to my dsPIC33F the code is very hard to understand, with a specific application which I don't care for.

The generic code is much easier to understand, and performs a very simple application of creating a txt file, writing to it, then closing it. However, I'm having difficulty altering the code to work with my PIC.

I've got the dsPIC33FJ128GP802. I've added code to the generic example to remap the SPI pins, set up the internal oscillator, and set up and start the SPI module:

// Configure Oscillator to operate the device at 40Mhz
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// Fosc= 8M*40/(2*2)=80Mhz for 8M input clock
PLLFBD = 38; // M=40
CLKDIVbits.PLLPOST = 0; // N1=2
CLKDIVbits.PLLPRE = 0;  // N2=2
OSCTUN = 0;             // Tune FRC oscillator, if FRC is used

// Unlocks PPS, make change, and locks again.
__builtin_write_OSCCONL(OSCCONL & ~(1 << 6));

// OUTPUT
RPOR6bits.RP12R = 7; // RP12 = SDO1 which is SPI1 DATA OUTPUT.
RPOR7bits.RP15R = 8; // RP15 = SCK1OUT which is SPI1 CLOCK OUTPUT.

// INPUT
RPINR21bits.SS1R = 13; // RP13 = SS1R which is SPI1 SLAVE/CHIP SELECT.
RPINR20bits.SDI1R = 14; // RP14 = SDI1R which is SPI DATA INTPUT.

__builtin_write_OSCCONL(OSCCONL | (1 << 6));

SPI1STAT = 0;
SPI1STATbits.SPIEN = 0; // Disable SPI module.
SPI1STATbits.SPISIDL = 0; // Continue in idle mode.
SPI1STATbits.SPIROV = 0; // No overflow.
SPI1STATbits.SPITBF = 0; // Transmit started, SPIxTXB is empty.
SPI1STATbits.SPIRBF = 0; // Receive is not complete, SPIxRXB is empty.

SPI1CON1 = 0;
SPI1CON1bits.DISSCK = 0; // Internal clock enabled.
SPI1CON1bits.DISSDO = 0; // SD0 controlled by the module.
SPI1CON1bits.MODE16 = 0; // 8 bit mode.
SPI1CON1bits.SMP = 0; // Input data sampled at middle of data output time.
SPI1CON1bits.CKE = 1; // Serial output data changes on transition from idle.
SPI1CON1bits.SSEN = 0; // Slave select is not used by the module. 
SPI1CON1bits.CKP = 0; // Idle state for clock is low.
SPI1CON1bits.MSTEN = 1; // Master mode enabled.
SPI1CON1bits.SPRE = 0b000; // Secondary prescale 8:1
SPI1CON1bits.PPRE = 0b01; // Primary prescale 16:1.

SPI1CON2 = 0;
SPI1CON2bits.FRMEN = 0; // Framed SPI disabled.
SPI1CON2bits.SPIFSD = 0; // Framed sync pulse output.(N/A)
SPI1CON2bits.FRMPOL = 0; // Framed sync pulse is active-low.(N/A)
SPI1CON2bits.FRMDLY = 0; // Framed sync pulse precedes first bit clock.(N/A)

SPI1STATbits.SPIEN = 1; // Enable SPI module.

PIC to SD card is:

  • RP15, SPI clock output, to SCK
  • RP14, SPI data input, to DO (data out).
  • RP13, SPI slave select, to CS.
  • RP12, SPI data output, to DI (data in).
  • SD card CD not connected.

Could someone that's experienced with FatFS please help me make the necessary alterations. Running the code so far gets as far as f_open where it returns the error FR_NOT_READY.

For now I'm not trying to do anything fancy, just create a file and write to it. I've seen many applications which use external crystal oscillators, which I don't have. Is this a necessity for SPI? I'm new to SPI, been using I2C before this.

Within the mmcbb.c file for the generic example I had to make some changes to remove some errors I was getting, the delay function of theirs I replaced with my own function to create a delay of a similar timing as it was throwing an error, I also removed the INIT_PORT() that appears in disk_initialize(BYTE pdrv) as it was throwing an error and I initialised the ports before getting into any of the FatFS code, right at the start of the main. At the top of mmcbb.c there are #define which needed the corresponding ports to be added to how I set up the SPI, which I did (RBx pins are the same as the RPx I set above):

#define CS_H()      PORTBbits.RB13 |= 0x01  /* Set MMC CS "high" */
#define CS_L()      PORTBbits.RB13 &= 0xFE  /* Set MMC CS "low" */
#define CK_H()      PORTBbits.RB15 |= 0x02  /* Set MMC SCLK "high" */
#define CK_L()      PORTBbits.RB15 &= 0xFD  /* Set MMC SCLK "low" */
#define DI_H()      PORTBbits.RB14 |= 0x04  /* Set MMC DI "high" */
#define DI_L()      PORTBbits.RB14 &= 0xFB  /* Set MMC DI "low" */
#define DO      (PORTBbits.RB12 & 0x08) /* Test for MMC DO ('H':true, 'L':false) */

The bitwise operators were already there, I merely added the PORTBbits.RBxx.

That's all the changes I've made, but I've found finding information on using any library for SD card manipulation particularly hard online (FatFS and MDDFS). Any help will be most appreciated!

Était-ce utile?

La solution

Sorted. Lots has changed so watch this space, I'll be uploading the code and some info shortly so hopefully it'll help others in this situation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top