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文件系统移植过程及中度分析相关推荐

  1. 2021-08-11 TM32F103 Buffer FatFs 文件系统移植

    FatFs 本文展示了STM32 FatFs文件系统移植 内容涉及 : FatFs 文件系统移植 SPI函数移植过程 SPI字节数据模拟输出独写 缓存读写 USART串口的识别 IO口输入输出 按键的 ...

  2. elm FatFs文件系统移植总结

    1 前言 本文将根据我的一些理解,针对elm FatFs文件系统做一个初步总结. 2 elm FatFs文件系统介绍 顾名思义FatFs文件系统就是针对FAT文件系统来的,主要是应用于MCU中,STM ...

  3. FATFS文件系统框架及源码分析

    FATFS是一个为小型嵌入式系统设计的通用FAT(File Allocation Table)文件系统模块.FatFs 的编写遵循ANSI C,并且完全与磁盘I/O层分开.因此,它独立(不依赖)于硬件 ...

  4. 模拟SPI进行TF卡操作+Fatfs文件系统移植

    FATFS版本:FATFS R0.13b SD卡容量:16G 概述 本文的重点是进行Fatfs文件系统的移植和初步的使用.TF卡的操作实际上是指令操作,即你想它发送固定的CMD指令,它接收到指令给你返 ...

  5. STM32+雷龙SD NAND(贴片SD卡)完成FATFS文件系统移植与测试

    一.前言 在STM32项目开发中,经常会用到存储芯片存储数据. 比如:关机时保存机器运行过程中的状态数据,上电再从存储芯片里读取数据恢复:在存储芯片里也会存放很多资源文件.比如,开机音乐,界面上的菜单 ...

  6. 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试

    一.前言 在STM32项目开发中,经常会用到存储芯片存储数据. 比如:关机时保存机器运行过程中的状态数据,上电再从存储芯片里读取数据恢复:在存储芯片里也会存放很多资源文件.比如,开机音乐,界面上的菜单 ...

  7. 基于stm32、spi协议的Fatfs文件系统移植(附完整代码下载)

    开发环境:Window 7 32bit 开发工具:Keil uVision4 硬件:stm32f103vct6 目录 1.硬件设计: 2.软件设计 1.SPI收发数据 2.向SD卡发送的命令格式: 3 ...

  8. JFFS2文件系统挂载过程优化的分析报告

    一 问题描述 在上电启动优化中发现Linux系统下挂载JFFS2文件系统耗时较长,以128M的NOR FLASH为例,用时接近20秒.后续单板的FLASH容量为256M,时间会更长.如此长的挂载时间, ...

  9. 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试(中篇)

    3.2 SPI硬件时序方式 上面的3.1小节是采用SPI模拟时序驱动SD NAND,STM32本身集成有SPI硬件模块,可以直接利用STM32硬件SPI接口读写. 下面贴出底层的适配代码. 上面贴出的 ...

最新文章

  1. ActivityLifecycleCallbacks
  2. sparkcore写mysql_spark读写mysql
  3. hdu2553 N皇后问题-dfs回溯剪枝+打表
  4. linux系统下聊天工具,linux系统环境下如何使用amsn聊天工具_linux教程
  5. Java安全 – JCE (Blowfish算法报错)
  6. 快递跟踪地图_基于百度地图的物流跟踪系统设计
  7. ANSYS——模态分析的理论基础
  8. 怎么计算机械需要的电机,比方说一个90kw的电机它的最大电流应该是多少?应该用多少平方的铜线?怎么计算呀?...
  9. css鼠标移入变小手
  10. MySQL 数据归档清理方法
  11. iOS 工具篇一一如何导出ipa文件和ipa文件安装在手机
  12. 香山处理器仿真环境搭建
  13. 又十一了,唠唠程序员回家相亲那些段子
  14. 您的计算机配置已更改,你的硬件设置已更改请重启电脑怎么回事
  15. 一键查询自己名下所有微信账户
  16. 【硬件深似海】磁珠选型规范
  17. python随手记自动记账_随手记 怎么实现自动记账
  18. Lasso回归理论及代码实现
  19. Altium Designer 批量修改器件名
  20. DSA-数据签名算法(理论)

热门文章

  1. VBA:Excel工作簿所有子表数据一键汇总
  2. asp.net书籍推荐
  3. grunt 压缩 html,如何使用 grunt 插件压缩合并 js ?减少页面请求数的秘诀
  4. 如何成为卓有成效的管理者?
  5. Linux 【权限,粘滞位】
  6. 微信小程序右上角胶囊按钮尺寸
  7. cocos性能优化之spine动画
  8. hp工作站 安装服务器系统,HP工作站操作系统安装说明.pdf
  9. jQuerychicun
  10. 正多边形的数学推导及绘制