FatFs文件系统移植过程及中度分析
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 herereturn stat;case DEV_MMC :result = MMC_disk_status();// translate the reslut code herereturn stat;case DEV_USB :result = USB_disk_status();// translate the reslut code herereturn 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 herereturn res;case DEV_MMC :// translate the arguments hereresult = MMC_disk_read(buff, sector, count);// translate the reslut code herereturn res;case DEV_USB :// translate the arguments hereresult = USB_disk_read(buff, sector, count);// translate the reslut code herereturn 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卡,宏定义卷标为0res=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 herereturn res;case DEV_MMC :// translate the arguments hereresult = MMC_disk_write(buff, sector, count);// translate the reslut code herereturn res;case DEV_USB :// translate the arguments hereresult = USB_disk_write(buff, sector, count);// translate the reslut code herereturn 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 drivereturn res;case DEV_MMC :// Process of the command for the MMC/SD cardreturn res;case DEV_USB :// Process of the command the USB drivereturn 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_READONLYLBA_t dir_sect; /* 包含目录条目的扇区号(不在exFAT中使用) */BYTE* dir_ptr; /* 指向win[]中的目录条目的指针(不在exFAT中使用) */
#endif
#if FF_USE_FASTSEEKDWORD* cltbl; /* 指向簇链接映射表的指针(打开时为空,由应用程序设置) */
#endif
#if !FF_FS_TINYBYTE 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_LFNfireinfoobj.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;//如果不是elsefn = 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");}
}
FatFs文件系统移植过程及中度分析相关推荐
- 2021-08-11 TM32F103 Buffer FatFs 文件系统移植
FatFs 本文展示了STM32 FatFs文件系统移植 内容涉及 : FatFs 文件系统移植 SPI函数移植过程 SPI字节数据模拟输出独写 缓存读写 USART串口的识别 IO口输入输出 按键的 ...
- elm FatFs文件系统移植总结
1 前言 本文将根据我的一些理解,针对elm FatFs文件系统做一个初步总结. 2 elm FatFs文件系统介绍 顾名思义FatFs文件系统就是针对FAT文件系统来的,主要是应用于MCU中,STM ...
- FATFS文件系统框架及源码分析
FATFS是一个为小型嵌入式系统设计的通用FAT(File Allocation Table)文件系统模块.FatFs 的编写遵循ANSI C,并且完全与磁盘I/O层分开.因此,它独立(不依赖)于硬件 ...
- 模拟SPI进行TF卡操作+Fatfs文件系统移植
FATFS版本:FATFS R0.13b SD卡容量:16G 概述 本文的重点是进行Fatfs文件系统的移植和初步的使用.TF卡的操作实际上是指令操作,即你想它发送固定的CMD指令,它接收到指令给你返 ...
- STM32+雷龙SD NAND(贴片SD卡)完成FATFS文件系统移植与测试
一.前言 在STM32项目开发中,经常会用到存储芯片存储数据. 比如:关机时保存机器运行过程中的状态数据,上电再从存储芯片里读取数据恢复:在存储芯片里也会存放很多资源文件.比如,开机音乐,界面上的菜单 ...
- 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试
一.前言 在STM32项目开发中,经常会用到存储芯片存储数据. 比如:关机时保存机器运行过程中的状态数据,上电再从存储芯片里读取数据恢复:在存储芯片里也会存放很多资源文件.比如,开机音乐,界面上的菜单 ...
- 基于stm32、spi协议的Fatfs文件系统移植(附完整代码下载)
开发环境:Window 7 32bit 开发工具:Keil uVision4 硬件:stm32f103vct6 目录 1.硬件设计: 2.软件设计 1.SPI收发数据 2.向SD卡发送的命令格式: 3 ...
- JFFS2文件系统挂载过程优化的分析报告
一 问题描述 在上电启动优化中发现Linux系统下挂载JFFS2文件系统耗时较长,以128M的NOR FLASH为例,用时接近20秒.后续单板的FLASH容量为256M,时间会更长.如此长的挂载时间, ...
- 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试(中篇)
3.2 SPI硬件时序方式 上面的3.1小节是采用SPI模拟时序驱动SD NAND,STM32本身集成有SPI硬件模块,可以直接利用STM32硬件SPI接口读写. 下面贴出底层的适配代码. 上面贴出的 ...
最新文章
- ActivityLifecycleCallbacks
- sparkcore写mysql_spark读写mysql
- hdu2553 N皇后问题-dfs回溯剪枝+打表
- linux系统下聊天工具,linux系统环境下如何使用amsn聊天工具_linux教程
- Java安全 – JCE (Blowfish算法报错)
- 快递跟踪地图_基于百度地图的物流跟踪系统设计
- ANSYS——模态分析的理论基础
- 怎么计算机械需要的电机,比方说一个90kw的电机它的最大电流应该是多少?应该用多少平方的铜线?怎么计算呀?...
- css鼠标移入变小手
- MySQL 数据归档清理方法
- iOS 工具篇一一如何导出ipa文件和ipa文件安装在手机
- 香山处理器仿真环境搭建
- 又十一了,唠唠程序员回家相亲那些段子
- 您的计算机配置已更改,你的硬件设置已更改请重启电脑怎么回事
- 一键查询自己名下所有微信账户
- 【硬件深似海】磁珠选型规范
- python随手记自动记账_随手记 怎么实现自动记账
- Lasso回归理论及代码实现
- Altium Designer 批量修改器件名
- DSA-数据签名算法(理论)