我正在尝试使用 FatFS ( http://elm-chan.org/fsw/ff/00index_e.html ) 作为使用 SPI 与 SD 卡进行通信的一种方式。
FatFS 网站有许多示例,但我发现它们并不容易理解或遵循。可下载的 zip 中有两个示例适用于我,一个用于“通用”微控制器,另一个用于 PIC24。虽然 PIC24 看起来与我的 dsPIC33F 非常相似,但代码非常难以理解,具有我不关心的特定应用程序。
通用代码更容易理解,并且执行一个非常简单的应用程序:创建一个 txt 文件,写入它,然后关闭它。但是,我很难更改代码以使用我的 PIC。
我有 dsPIC33FJ128GP802。我在通用示例中添加了代码来重新映射 SPI 引脚、设置内部振荡器以及设置和启动 SPI 模块:
// 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到SD卡是:
- RP15,SPI时钟输出,到SCK
- RP14,SPI 数据输入,到 DO(数据输出)。
- RP13,SPI 从机选择,至 CS。
- RP12,SPI数据输出,到DI(数据输入)。
- SD 卡 CD 未连接。
有FatFS经验的人可以帮我做必要的改动。到目前为止,运行代码一直到 f_open,它返回错误 FR_NOT_READY。
现在我不想做任何花哨的事情,只是创建一个文件并写入它。我见过许多使用外部晶体振荡器的应用程序,而我没有。这是SPI的必需品吗?我是 SPI 新手,在此之前一直在使用 I2C。
在通用示例的 mmcbb.c 文件中,我必须进行一些更改以消除我遇到的一些错误,我用我自己的函数替换了他们的延迟函数,以创建与引发错误的时间相似的延迟,我还删除了出现在 disk_initialize(BYTE pdrv) 中的 INIT_PORT(),因为它引发了错误,并且我在进入任何 FatFS 代码之前初始化了端口,就在 main 的开头。在 mmcbb.c 的顶部有 #define 需要将相应的端口添加到我设置 SPI 的方式中,我这样做了(RBx 引脚与我在上面设置的 RPx 相同):
#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) */
位运算符已经存在,我只是添加了 PORTBbits.RBxx。
这就是我所做的所有更改,但我发现在线查找有关使用任何库进行 SD 卡操作的信息特别困难(FatFS 和 MDDFS)。任何帮助将不胜感激!