FatFs 是一个通用的文件系统(FAT/exFAT)模块,用于在小型嵌入式系统中实现FAT文件系统。 FatFs 组件的编写遵循ANSI C(C89),完全分离于磁盘 I/O 层,因此不依赖于硬件平台。它可以嵌入到资源有限的微控制器中,如 8051, PIC, AVR, ARM, Z80, RX等等,不需要做任何修改。
如果要进行移植的话可以直接看后面的移植步骤,前面是对文件系统中的一些常见的代码进行简单介绍。本文比较长,可以先收藏再看。
首先大致看看文件系统源码的目录结构。
在下载好文件系统的源码包解压之后,文件结构如下
documents目录中包含一些介绍以及文件系统各种操作函数的介绍以及示例,大家可以在documents目录下的doc目录中找到各种函数的操作方法。以下是部分截图。
source目录中包含所有的源文件以及头文件
Fatfs源文件及头文件
diskio.c和.h文件:与存储器读写控制有关文件
ff.c和.h文件:文件系统核心文件
ffconf.h:文件系统的配置文件
ffsystem.c:示例,移植时不需要这个
ffunicode.c:万国码,可以自行裁剪
interger.h:文件系统数据类型定义文件,新版没这个了
接下来是对一些常用的配置参数和结构体等的简单介绍
ffconf.h中的宏定义介绍
宏定义 | 功能 |
---|---|
FF_FS_READONLY | 0:可读可写;1:只读 |
FF_FS_MINIMIZE | 定义最小化级别:0,1,2,3四个等级 |
FF_USE_FIND | 是否使能 f_findfirst() 和 f_findnext() 函数 |
FF_USE_MKFS | 是否使能 f_mkfs() 函数 |
FF_USE_FASTSEEK | 是否使能快速寻找功能 |
FF_USE_EXPAND | 是否使能 f_expand() 函数 |
FF_USE_CHMOD | 控制一些属性操作函数,要有读写权限 |
FF_USE_LABEL | 使能卷标函数,设置卷标和获取卷标 |
FF_USE_FORWARD | 使能 f_forward() 函数功能 |
FF_USE_STRFUNC | 配置是否支持字符串相关函数:f_gets(), f_putc(), f_puts(),f_printf() |
FF_PRINT_LLI | 配置 f_printf() 支持long long型数据 |
FF_PRINT_FLOAT | 配置 f_printf() 支持浮点型数据 |
FF_STRF_ENCODE | 配置字符集,有四种 |
FF_CODE_PAGE | 指定要在目标系统上使用的OEM代码页,在文件ffunicode.c文件中,该文件可裁剪 |
FF_USE_LFN | 配置是否支持长文件名,可动态/静态,在堆区或栈区配置 |
FF_MAX_LFN | 长文件名的最大长度 |
FF_LFN_UNICODE | 配置启用LFN时,API上的字符编码 |
FF_LFN_BUF | 定义了FILINFO结构中文件名成员的大小(支持长文件名时) |
FF_SFN_BUF | 定义了FILINFO结构中文件名成员的大小(不支持长文件名时) |
FF_FS_RPATH | 配置对相对路径的支持,0:不支持,1,2:支持(被使能的函数不同) |
FF_VOLUMES | 配置要使用的卷的数量 |
FF_STR_VOLUME_ID | 配置驱动器号,默认为0。设置为1或2时,路径名中可以使用任意字符串作为驱动器号 |
FF_MULTI_PARTITION | 配置对物理驱动器上多个卷的支持,默认0,配置为1可支持多个卷,并被记录在VolToPart[]中 |
FF_MIN_SS | 配置一个扇区的最小值 |
FF_MAX_SS | 配置一个扇区的最大值 |
FF_LBA64 | 配置是否支持64位LBA寻址方式 |
FF_MIN_GPT | 配置 f_mkfs() 和 f_fdisk() 中切换GPT分区格式的最小扇区数 |
FF_USE_TRIM | 配置是否支持ATA-TRIM(貌似是用来优化磁盘存储空间的) |
FF_FS_TINY | 配置缓冲区,normal 或者 tiny |
FF_FS_EXFAT | 配置是否使用exFAT文件系统 |
FF_FS_NORTC | 配置时间戳功能,0:enable,1:disable |
FF_NORTC_MON | 时间戳的月 |
FF_NORTC_MDAY | 时间戳的日 |
FF_NORTC_YEAR | 时间戳的年 |
FF_FS_NOFSINFO | 配置读取FAT32上的空闲空间大小的功能 |
FF_FS_LOCK | 配置文件锁定功能,当FF_FS_READONLY 为1时,必须将FF_FS_LOCK配置为0 |
FF_FS_REENTRANT | 配置fatf的可重入性(线程安全)(用了操作系统时) |
FF_FS_TIMEOUT | 超时时间(用了操作系统时) |
FF_SYNC_t | O/S相关的同步对象类型(用了操作系统时) |
ffunicode.c文件
万国码文件,用户可以自行剪裁。例如:在只需要简体中文时,将 uni2oem936[] 剪裁出来。
ffsystem.c文件
在OS上操作文件系统的示例
integer.h文件
文件系统的数据类型的重定义
diskio.c文件介绍
该文件将硬件存储器和文件系统相互连接起来,源文件中包含以下函数:
函数1:获取磁盘状态
//在正点原子的例程中,该函数直接返回了一个RES_OK,并没有做其他操作
DSTATUS disk_status (
BYTE pdrv /* 用于识别驱动器的物理驱动器号 */
)
{
DSTATUS stat;
int result;
switch (pdrv) {
case DEV_RAM :
result = RAM_disk_status();
// translate the reslut code here
return stat;
case DEV_MMC :
result = MMC_disk_status();
// translate the reslut code here
return stat;
case DEV_USB :
result = USB_disk_status();
// translate the reslut code here
return stat;
}
return STA_NOINIT;
}
函数2:硬件设备初始化
DSTATUS disk_initialize (
BYTE pdrv /* 用于识别驱动器的物理驱动器号 */
)
{
DSTATUS stat; //初始化状态位
int result; //初始化返回值
//判断驱动器号(需要自己定义)
switch (pdrv) {
case DEV_RAM : //RAM存储设备
result = RAM_disk_initialize();
// 在这里转换结果代码
return stat;
case DEV_MMC : //MMC存储设备
result = MMC_disk_initialize();
// 在这里转换结果代码
return stat;
case DEV_USB : //UUSB存储设备
result = USB_disk_initialize();
// 在这里转换结果代码
return stat;
case SD_CARD :
result = SD_disk_initialize();
// 在这里转换结果代码
return stat;
}
return STA_NOINIT; //以上设备均没有,则返回未初始化标识
}
函数3:读扇区
DRESULT disk_read (
BYTE pdrv, /* 磁盘编号0~9 */
BYTE *buff, /* 数据接收缓冲首地址 */
LBA_t sector, /* 扇区地址 */
UINT count /* 需要读取的扇区数 */
)
{
DRESULT res;
int result;
//判断读取哪个存储设备
switch (pdrv) {
case DEV_RAM :
//放入存储设备读取扇区的函数取代下面的函数
//放入的函数最好要有返回值,以帮助判断读取成功或失败
result = RAM_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_read(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_read(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
/*--------------------------以下是原子的例程,简化为只有SD卡存储设备--------------------------*/
DRESULT disk_read (
BYTE pdrv,
BYTE *buff,
DWORD sector,
UINT count
)
{
u8 res=0; //用来存放初始化的返回值
if (!count)
return RES_PARERR;//count不能等于0,否则返回参数错误
switch(pdrv)
{
case SD_CARD://SD卡,宏定义卷标为0
res=SD_ReadDisk(buff,sector,count);
while(res)//读出错,原子对于其他存储设备写法并没判断是否读取正确
{
SD_Init(); //重新初始化SD卡
res=SD_ReadDisk(buff,sector,count);
}
break;
default:
res=1;
}
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
//即将SD卡初始化中的返回值用ff.c文件中的返回值取代
if(res==0x00)
return RES_OK;
else
return RES_ERROR;
}
函数4:写扇区
//如果在ffconf.h文件中将FF_FS_READONLY配置为0,则文件系统对文件具有读写权限
#if FF_FS_READONLY == 0
DRESULT disk_write (
BYTE pdrv, /* 磁盘编号0~9 */
const BYTE *buff, /* 发送数据首地址 */
LBA_t sector, /* 扇区地址 */
UINT count /* 需要写入的扇区数 */
)
{
DRESULT res;
int result;
//判断将数据写入哪个存储设备
switch (pdrv) {
case DEV_RAM :
//放入存储设备写扇区的函数取代下面的函数
//放入的函数最好要有返回值,以帮助判断读取成功或失败
result = RAM_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_MMC :
// translate the arguments here
result = MMC_disk_write(buff, sector, count);
// translate the reslut code here
return res;
case DEV_USB :
// translate the arguments here
result = USB_disk_write(buff, sector, count);
// translate the reslut code here
return res;
}
return RES_PARERR;
}
#endif
/*--------------------------以下是原子的例程,简化为只有SD卡存储设备--------------------------*/
DRESULT disk_write (
BYTE pdrv,
const BYTE *buff,
DWORD sector,
UINT count
)
{
u8 res=0;
if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
switch(pdrv)
{
case SD_CARD://SD卡
res=SD_WriteDisk((u8*)buff,sector,count);
while(res)//写出错,原子对于其他存储设备写法并没判断是否写入正确
{
SD_Init(); //重新初始化SD卡
res=SD_WriteDisk((u8*)buff,sector,count);
//printf("sd wr error:%d\r\n",res);
}
break;
default:
res=1;
}
//处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
if(res == 0x00)return RES_OK;
else return RES_ERROR;
}
函数5:辅助功能
DRESULT disk_ioctl (
BYTE pdrv, /* 磁盘编号0~9 */
BYTE cmd, /* 控制代码 */
void *buff /* 发送/接收缓冲区指针 */
)
{
DRESULT res;
int result;
switch (pdrv) {
case DEV_RAM :
//填入一些指令,并执行相应指令的操作
// Process of the command for the RAM drive
return res;
case DEV_MMC :
// Process of the command for the MMC/SD card
return res;
case DEV_USB :
// Process of the command the USB drive
return res;
}
return RES_PARERR;
}
diskio.h文件介绍
包含磁盘操作函数的状态位,磁盘操作函数的返回值,磁盘操作函数的函数声明,磁盘状态位,以及一些操作命令表
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
/* 硬盘功能状态 */
typedef BYTE DSTATUS;
/* 磁盘功能返回值 */
typedef enum {
RES_OK = 0, /* 0: 成功 */
RES_ERROR, /* 1: 读/写错误 */
RES_WRPRT, /* 2: 写保护了 */
RES_NOTRDY, /* 3: 未准备好 */
RES_PARERR /* 4: 无效参数 */
} DRESULT;
/*---------------------------------------*/
/* 函数声明 */
DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* 磁盘状态位 (DSTATUS) */
#define STA_NOINIT 0x01 /* 设备未初始化 */
#define STA_NODISK 0x02 /* 驱动器中没有介质 */
#define STA_PROTECT 0x04 /* 写保护了 */
/* disk_ioctrl函数的指令码 */
/* 常用指令 (FatFs使用的) */
#define CTRL_SYNC 0 /* Complete pending write process (需要 _FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* 获取存储介质大小 (needed at _USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* 获取扇区大小 (needed at _MAX_SS != _MIN_SS) */
#define GET_BLOCK_SIZE 3 /* 获取擦除块的大小 (needed at _USE_MKFS == 1) */
#define CTRL_TRIM 4 /* 通知设备扇区块上的数据不再使用 (needed at _USE_TRIM == 1) */
/* 常用指令 (非FatFs使用的) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* 弹出设备 */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* 以下是一些特殊功能的指令码 */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
#endif
#endif
ff.c和ff.h文件介绍
这个文件是Fatfs的核心文件之一,所有的我们平常用到的操作文件的函数都在这个文件中
函数表如下所示(FRESULT是函数的返回类型,是一个结构体,结构体中定义了在文件操作过程中各种状况的返回值)
函数 | 功能 |
---|---|
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode) | 打开或创建一个文件 |
FRESULT f_close (FIL* fp) | 关闭一个已打开的文件 |
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br) | 从文件中读取数据 |
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw) | 将数据写入文件中 |
FRESULT f_lseek (FIL* fp, FSIZE_t ofs) | 移动文件对象的文件指针 |
FRESULT f_truncate (FIL* fp) | |
FRESULT f_sync (FIL* fp) | 刷新正在写入的文件的缓存数据 |
FRESULT f_opendir (DIR* dp, const TCHAR* path) | 打开目录 |
FRESULT f_closedir (DIR* dp) | 关闭目录 |
FRESULT f_readdir (DIR* dp, FILINFO* fno) | 读取目录 |
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern) | 找到第一个文件 |
FRESULT f_findnext (DIR* dp, FILINFO* fno) | 查找下一个文件 |
FRESULT f_mkdir (const TCHAR* path) | 创建子目录 |
FRESULT f_unlink (const TCHAR* path) | 删除一个已有的文件或目录 |
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new) | 重命名或移动一个文件或目录 |
FRESULT f_stat (const TCHAR* path, FILINFO* fno) | 获取文件状态 |
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask) | 更改文件或目录的属性 |
FRESULT f_utime (const TCHAR* path, const FILINFO* fno) | 更改文件或目录的时间戳 |
FRESULT f_chdir (const TCHAR* path) | 更改当前目录 |
FRESULT f_chdrive (const TCHAR* path) | 更改当前存储驱动器 |
FRESULT f_getcwd (TCHAR* buff, UINT len) | 获取当前目录 |
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs) | 获取驱动器上空闲簇的数量 |
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn) | 获取磁盘卷标 |
FRESULT f_setlabel (const TCHAR* label) | 设置磁盘卷标 |
FRESULT f_forward (FIL* fp, UINT(func)(const BYTE,UINT), UINT btf, UINT* bf) | 将数据转发到流 |
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt) | 为文件分配一个连续的块 |
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt) | 挂载或卸载存储器 |
FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len) | 创建FAT卷 |
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work) | 将物理磁盘划分为几个分区 |
FRESULT f_setcp (WORD cp) | 设置当前代码页 |
int f_putc (TCHAR c, FIL* fp) | 将一个字符放入文件中 |
int f_puts (const TCHAR* str, FIL* cp) | 将一个字符串放入文件中 |
int f_printf (FIL* fp, const TCHAR* str, …) | 将格式化字符串放入文件中 |
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp) | 从文件中获取字符串 |
简单一下ff.h中常见的结构体
先看看这些结构体记录了什么东西才好进一步看源码
FATFS(文件系统对象结构体)
是一些与文件系统核心和配置相关的一些参数。这个结构体要结合前面的ffconf.h文件中的配置信息来看
FIL(文件对象结构体)
typedef struct {
FFOBJID obj; /* 对象标识符 (必须是用于检测无效对象的指针的第一个成员) */
BYTE flag; /* 文件状态标志 */
BYTE err; /* 中止标志(错误代码) */
FSIZE_t fptr; /* 文件读/写指针(打开文件时置零) */
DWORD clust; /* 当前fptr所处的簇(当fptr为0时无效) */
LBA_t sect; /* 扇区号,保存在一个数组中 (0:invalid) */
#if !FF_FS_READONLY
LBA_t dir_sect; /* 包含目录条目的扇区号(不在exFAT中使用) */
BYTE* dir_ptr; /* 指向win[]中的目录条目的指针(不在exFAT中使用) */
#endif
#if FF_USE_FASTSEEK
DWORD* cltbl; /* 指向簇链接映射表的指针(打开时为空,由应用程序设置) */
#endif
#if !FF_FS_TINY
BYTE buf[FF_MAX_SS]; /* 文件私有数据读写窗口 */
#endif
} FIL;
FRESULT(文件函数返回码结构体)
由这个结构体可以看出,在对文件进行各种操作时,可能会产生各种错误或状态,这个结构体将这些状态全都封装在了一起
typedef enum {
FR_OK = 0, /* (0) 成功 */
FR_DISK_ERR, /* (1) 低一级的磁盘I/O层发生错误 */
FR_INT_ERR, /* (2) 断言失败 */
FR_NOT_READY, /* (3) 物理设备不工作 */
FR_NO_FILE, /* (4) 找不到文件 */
FR_NO_PATH, /* (5) 找不到路径 */
FR_INVALID_NAME, /* (6) 路径名格式无效 */
FR_DENIED, /* (7) 由于禁止访问或目录已满而拒绝访问 */
FR_EXIST, /* (8) 由于禁止访问而拒绝访问 */
FR_INVALID_OBJECT, /* (9) 文件/目录对象无效*/
FR_WRITE_PROTECTED, /* (10) 物理磁盘处于写保护状态 */
FR_INVALID_DRIVE, /* (11) 逻辑驱动器号无效 */
FR_NOT_ENABLED, /* (12) 卷没有被分配工作区 */
FR_NO_FILESYSTEM, /* (13) 没有有效的FAT卷 */
FR_MKFS_ABORTED, /* (14) f_mkfs()由于任何问题而中止 */
FR_TIMEOUT, /* (15) 无法获得在规定时间内访问该卷的授权 */
FR_LOCKED, /* (16) 根据文件共享策略,操作被拒绝 */
FR_NOT_ENOUGH_CORE, /* (17) 无法分配LFN工作缓冲区 */
FR_TOO_MANY_OPEN_FILES, /* (18) 打开的文件数 > FF FS LOCK */
FR_INVALID_PARAMETER /* (19) 给定参数无效 */
} FRESULT;
FILINFO(文件信息结构体)
typedef struct {
FSIZE_t fsize; /* 文件大小 */
WORD fdate; /* 修改日期 */
WORD ftime; /* 修改时间 */
BYTE fattrib; /* 文件属性 */
//如果支持长文件名
#if FF_USE_LFN
TCHAR altname[FF_SFN_BUF + 1];/* 替代文件名 */
TCHAR fname[FF_LFN_BUF + 1]; /* 主要文件名 */
//不支持长文件名
#else
TCHAR fname[12 + 1]; /* 文件名 */
#endif
} FILINFO;
其他的一些结构体在看到的时候再去分析一下就好。
FatFS文件系统的移植
第1步:
先配置好底层存储介质的驱动,然后准备好所需的文件。
例如:先配置好SD卡的驱动程序,然后将ff.c、ff.h、ffconf.h、diskio.c、diskio.h、ffunicode.c和integer.h这些文件放入fatfs文件夹中(新版本没有interger.h文件),
再在keil中添加group,如下:
将fatfs中的C文件导入该目录。再在main.c文件中包含 ff.h 头文件。
第2步:
在ffconf.h文件中配置文件系统的相关参数,例如编码格式,是否支持长文件名等,各种参数的介绍可看我前面对ffconf.h文件的介绍
第3步:
在diskio.c文件中将文件系统和存储设备的底层驱动链接起来,具体的链接方式可以见我前面对diskio.c文件的介绍。
第4步:
插上存储介质,编写想使用的文件操作函数,进行测试。
一些文件操作函数的例子
遍历目录
FATFS fs; /* FatFs文件系统对象 */
FIL fnew; /* 文件对象 */
FRESULT res_sd; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0}; /* 读缓冲区 */
/*------------------- 遍历目录(支持长文件名) ---------------------*/
void testDirScan(u8* dirpath)
{
int index = 0; //文件数量
char *fn; //文件名指针
char lfn[50]; //用于存放文件名的数组
res_sd = f_opendir(&dirobj,(const TCHAR*)dirpath);
if(res_sd == FR_OK)
{
//如果支持长文件名
#if _USE_LFN
fireinfoobj.lfname=lfn;
fireinfoobj.lfsize = sizeof(lfn);
#endif
while(1)
{
//获取读取目录的状态
res_sd = f_readdir(&dirobj,&fireinfoobj);
//如果没有存放的文件名了,那么说明文件遍历结束
if(!fireinfoobj.fname[0]&&!fireinfoobj.lfname[0])
break;
//如果支持长文件名
#if _USE_LFN
//如果是文件名是长文件名
if(*fireinfoobj.lfname != NULL)
fn = fireinfoobj.lfname;
//如果不是
else
fn = fireinfoobj.fname;
#endif
index++;
//当目录下文件超过10个时停止遍历
if(index > 10)
break;
printf("filename %d = %s\r\n", index, fn);
}
}
//关闭文件,每次对文件进行操作后都要记得关闭文件
f_closedir(&dirobj);
}
读取文件数据
FATFS fs; /* FatFs文件系统对象 */
FIL fnew; /* 文件对象 */
FRESULT res_sd; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0}; /* 读缓冲区 */
void testRead(const TCHAR* path)
{
res_sd = f_open(&fnew, path, FA_OPEN_EXISTING | FA_READ);
//res_sd = f_open(&fnew, "0:FatFs读写测试文件.txt", FA_OPEN_EXISTING | FA_READ);
if(res_sd == FR_OK)
{
printf("打开文件成功\r\n");
res_sd = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum);
if(res_sd==FR_OK)
{
printf("文件读取成功,读到字节数据:%d\r\n",fnum);
printf("读取得的文件数据为:\r\n%s \r\n", ReadBuffer);
}
else
{
printf("文件读取失败:(%d)\n",res_sd);
}
}
else
{
printf("打开文件失败\r\n");
}
/* 不再读写,关闭文件 */
f_close(&fnew);
}
向文件写入数据
FATFS fs; /* FatFs文件系统对象 */
FIL fnew; /* 文件对象 */
FRESULT res_sd; /* 文件操作结果 */
UINT fnum; /* 文件成功读写数量 */
void testWrite(const TCHAR* path,BYTE WriteBuffer[])
{
/* 打开文件,如果文件不存在则创建它 */
res_sd = f_open(&fnew, path, FA_CREATE_ALWAYS | FA_WRITE );
if ( res_sd == FR_OK )
{
/* 将指定存储区内容写入到文件内 */
res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
if(res_sd==FR_OK)
{
printf("文件写入成功,写入字节数据:%d\n",fnum);
printf("向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
}
else
{
printf("!!文件写入失败:(%d)\n",res_sd);
}
/* 不再读写,关闭文件 */
f_close(&fnew);
}
else
{
printf("打开/创建文件失败。\r\n");
}
}