<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
3、搭建框架
因为在命令处理函数中调用了f_open等函数,所以先要包含头文件ff.h。
然后在interg.h文件中做了如下改变:
//typedef enum { FALSE = 0, TRUE } BOOL;
#define BOOL bool;//因为stm32的库中已经定义过TRUE和FALSE。
void UartCmdFRead(u8 argc,void **argv)
{ FIL FileInf;
u8 FileBuf[512];
u16 i;
UINT ByteToRead,ByteRead;
FRESULT res;
res=f_open(&FileInf,argv[1],FA_READ|FA_OPEN_ALWAYS);
if ( res!=FR_OK) { Uart_PutString( "File Open Error!");return;}
do {
res=f_read(&FileInf,FileBuf,ByteToRead,&ByteRead); //要进去看一看,读后有没有自动调整指针。
if ( res!=FR_OK) { Uart_PutString( "File Read Error!");return;}
for(i=0;i<512;i++){Uart_PutChar(FileBuf);}
}while ( Uart_GetChar()!=0x1B );
}
然后单独编译fileop.c,成功。
4、加入文件系统文件
接下来在工程里面加入fatfs文件中,将ff.c和diskio.c两个文件加入,然后单独进行编译,看有没有什么问题。
#define BOOL bool;这个后面千万不能加分号,否则就会出问题。
#include "stm<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />32f10x_type.h" 在integer.h前面要加入stm32库中数据类型的定义,因为#define BOOL bool这句定义要用到bool的原定义。
然后单独编译ff.c,成功,没有错误。
单独编译diskio.c,没有错误,但有很多警告,主要是底层驱动函数还没有定义和声明。
接下来的工作就是编写底层驱动了。
五、diskio.c中底层驱动程序的编写。
首先删除有关USB、MMC、ATA的定义,因为我这个板上只有SD卡。
1、disk_initialize函数
DSTATUS disk_initialize ( BYTE drv /* Physical drive nmuber (0..) */)
这个函数的参数是物理驱动号,在我的文件系统中逻辑盘和物理盘号都设为0,所以这个参数基本不用理会。
这个函数的返回值是DSTATUS类型,它是这样定义的:
typedef BYTE DSTATUS;
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
//#define STA_SUCCESS 0x00 /
成功时返回0.所以用户自己的磁盘初始化函数返回0、1、2、4几个值就行了。
我在前面已经编写过SD的操作函数了,在sduser.c文件中,SD_Config()函数就是用于SD卡的初始化的。所以只要在文件头部包含sdcard.h文件,就可以调用该函数了。
以下是最终函数:
{ int result;
result = SD_Config();
if ( result==0 ) return 0;
return STA_NOINIT; }
2、disk_status函数获取磁盘状态,如果初始化成功,磁盘时钟处于可用状态,直接返回0。
DSTATUS disk_status ( BYTE drv /* Physical drive nmuber (0..) */)
3、disk_read函数的编写
DRESULT disk_read ( BYTE drv, /* Physical drive nmuber (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */)
实际上是三个参数:缓冲区地址、起始扇区和扇区的个数,最多255个扇区。我在sduser.c文件中编写了SD卡读多个扇区的函数u8 SD_ReadMultiBlock( u32 BlockIndex, u32 BlockNum, u8* ReadBuf ),只是顺序优点不同,稍微改一下。
其返回参数是DRESULT类型,这个数据是这么定义的:
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
{ u8 result;
result = SD_ReadMultiBlock(sector,count,buff ); //要遵循定义的参数顺序。
if ( result==0 ) return RES_OK;
return RES_ERROR;}
4、disk_write函数与读函数类似,不再多说。
{ u8 result;
result = SD_WriteMultiBlock(sector,count,buff ); //要遵循定义的参数顺序。
if ( result==0 ) return RES_OK;
return RES_PARERR;}
5、disk_ioctl函数,直接返回RES_OK.
对diskio.c进行单独编译,成功通过。
对整个工程进行编译,显示get_fattime这个函数没有定义。添加函数定义,直接返回0,整个工程编译通过。
六、下载、测试
将程序下载后,进行测试,发现显示读文件错误,才想起来,还没有进行文件系统安装呢,也就是要调用f_mount函数。
添加好f_mount函数后,编译下载。
出现了一个奇怪的问题:每次调用f_read()函数时,就会出错,并且SD卡只有重新上电才能读出。通过设置断点,发现每次读取文件躲在目录的扇区时,都会错误返回。
最好发现问题是一个变量没有正确的初始化造成的:
u8 SD_ReadMultiBlock( u32 BlockIndex, u32 BlockNum, u8* ReadBuf ){
u16 i="0",j; //就是这里的这个i变量的初始化,花了我两个钟头的时间才调试出来。
u8 TmpByte;
BlockIndex <<=9;
if ( SD_CmdReadMulti( BlockIndex ) ) //发出读单块命令17,这是不能将片选除能
{ SD_CSDisable( ); SPI_PutByte( 0xFF ); return 1; }
编译成功后,可以正确读出文件了。
用户377235 2012-7-27 19:53