Fatfs文件系统常用函数


本文将介绍Fatfs文件系统的常用函数,学过C语言文件函数的小伙伴们就可以跳过了,因为两者之间基本没有什么区别:

返回值枚举:

下文提到的大多数函数都会返回FRESULT枚举,可以通过返回值来调试程序,找出程序出错的原因,FRESULT枚举如下:

typedef enum {FR_OK = 0,                /* (0) Succeeded */FR_DISK_ERR,         /* (1) A hard error occurred in the low level disk I/O layer */FR_INT_ERR,              /* (2) Assertion failed */FR_NOT_READY,         /* (3) The physical drive cannot work */FR_NO_FILE,             /* (4) Could not find the file */FR_NO_PATH,                /* (5) Could not find the path */FR_INVALID_NAME,       /* (6) The path name format is invalid */FR_DENIED,             /* (7) Access denied due to prohibited access or directory full */FR_EXIST,             /* (8) Access denied due to prohibited access */FR_INVALID_OBJECT,      /* (9) The file/directory object is invalid */FR_WRITE_PROTECTED,       /* (10) The physical drive is write protected */FR_INVALID_DRIVE,       /* (11) The logical drive number is invalid */FR_NOT_ENABLED,           /* (12) The volume has no work area */FR_NO_FILESYSTEM,     /* (13) There is no valid FAT volume */FR_MKFS_ABORTED,     /* (14) The f_mkfs() aborted due to any parameter error */FR_TIMEOUT,               /* (15) Could not get a grant to access the volume within defined period */FR_LOCKED,               /* (16) The operation is rejected according to the file sharing policy */FR_NOT_ENOUGH_CORE,        /* (17) LFN working buffer could not be allocated */FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */FR_INVALID_PARAMETER   /* (19) Given parameter is invalid */
} FRESULT;

f_mount:

挂载和取消挂载文件系统

FRESULT f_mount (FATFS*       fs,    /* [IN] File system object */const TCHAR* path,  /* [IN] Logical drive number */BYTE         opt    /* [IN] Initialization option */
);

fs: 文件系统句柄(注意区别于文件句柄),要提前定义一个FATFS类型变量,然后把它的
地址传给此参数

path: 这个参数决定了你要挂载哪个文件系统,在下文将统一叫它“逻辑驱动器”如果已经在diskio.c文件中有了如下定义:

/* Definitions of physical drive number for each drive */
#define ATA     2   /* Example: Map ATA harddisk to physical drive 0 */
#define MMC     3   /* Example: Map MMC/SD card to physical drive 1 */
#define USB     4   /* Example: Map USB MSD to physical drive 2 */
#define SD_CARD   0
#define FLASH_SPI 1

这个时候如果把path传入"1:"那就表示要挂载FLASH_SPI 这个文件系统,当然前提是你必须提前移植好了FLASH_SPI

opt: 给0会取消挂载path指定的文件系统,给1会挂载path指定的文件系统


f_mkfs:

格式化文件系统

FRESULT f_mkfs (const TCHAR* path,       /* Logical drive number */const MKFS_PARM* opt, /* Format options */void* work,             /* Pointer to working buffer (null: use heap memory) */UINT len             /* Size of working buffer [byte] */
)

path : 逻辑驱动器

sfd :分区规则,一般给0即可(给1貌似是不会创建文件分配表,被称为超级软盘(SFD)格式化)

au :以字节数或扇区数指定分配单元(聚集)的大小。当值介于 1 到 128 之间时,它指定扇区数。当值为 >= _MIN_SS 时,它指定字节数。如果给出了任何无效值(零或非 2 的幂),则根据卷大小自动确定簇大小。(所以一般给0即可)

注意!!!:格式化文件系统之后,必须使用f_mount取消挂载,再重新挂载。


f_open:

打开文件(指定文件权限,完成文件句柄初始化)

FRESULT f_open (FIL* fp,           /* [OUT] Pointer to the file object structure */const TCHAR* path, /* [IN] File name */BYTE mode          /* [IN] Mode flags */
);

*fp: 文件句柄地址

path:逻辑驱动器

mode :文件模式(权限),详见下表

参数 描述
FA_READ 读权限
FA_WRITE 写权限
FA_OPEN_EXISTING 如果文件存在,则打开;否则打开失败,返回FR_NO_FILE
FA_OPEN_ALWAYS 如果文件存在,则打开,如果不存在则创建一个文件并打开
FA_CREATE_NEW 创建一个文件,如果文件存在,则创建失败,返回FR_EXIST
FA_CREATE_ALWAYS 创建一个文件,如果文件存在,则覆盖原文件

f_write:

写文件

FRESULT f_write (FIL* fp,          /* [IN] Pointer to the file object structure */const void* buff, /* [IN] Pointer to the data to be written */UINT btw,         /* [IN] Number of bytes to write */UINT* bw          /* [OUT] Pointer to the variable to return number of bytes written */
);

*fp:文件句柄地址

*buff:要写入的数据地址(字符数组首地址,普通数组首地址或者字符串),这个参数应该传入const类型的实参

btw:要写入的字节数

*bw:传入一个指针,函数调用之后,将把成功写入的字节数传入该指针指向的变量,可以用来检查是否成功写入


f_printf:

int f_printf (FIL* fp,          /* [IN] File object */const TCHAR* fmt, /* [IN] Format stirng */...
);

此函数不必多说了,用法与printf函数一摸一样,只不过多了第一个参数*fp而已.


f_read:

FRESULT f_read (FIL* fp,     /* [IN] File object */void* buff,  /* [OUT] Buffer to store read data */UINT btr,    /* [IN] Number of bytes to read */UINT* br     /* [OUT] Number of bytes read */
);

* fp: 文件句柄地址

* buff:存放读取结果的数组

btr:要读取的字节数(通常和f_size配合使用)

* br:成功读取到的字节数

补充:在此说明一下br究竟有什么用,想象一下这样的场景:你要读取一个文件,文件很大,buff每次只能存放256个字节,那就只能每次读取256个字节咯!所以你不得不多次读取文件,但是如何确定读取到文件末尾了呢?读取到文件末尾,f_read就不会再读取了,所以此时br必定小于btr,因此,在多次读取的时候,可以用br来判断是否读取到文件末尾。


f_size:

传入文件句柄地址,返回该文件内容包含的字节数


f_lseek:

改变文件指针(光标)的位置
这个函数很简单,但是很不简单,新手经常碰到写入失败,读取失败,很大一部分原因就是不能正确的理解文件指针位置导致的,所以不要小看这个函数

FRESULT f_lseek (FIL* fp,   /* [IN] File object */DWORD ofs  /* [IN] File read/write pointer */
);

* fp:文件句柄地址

ofs 文件指针新的位置


f_getfree:

FRESULT f_getfree (const TCHAR* path,  /* [IN] Logical drive number */DWORD* nclst,       /* [OUT] Number of free clusters */FATFS** fatfs       /* [OUT] Corresponding file system object */
);

path:
指向指定逻辑驱动器的空终止字符串的指针。空字符串表示默认驱动器。

*nclst:
指向 DWORD 变量的指针,用于存储剩余簇的数量。
文件系统句柄的csize成员表示每个簇含有几个扇区,可以搭配两者使用来计算剩余空间;而n_fatent成员表示总空间的个数+2,所以还可以通过总空间减去剩余空间来计算已用空间
补充:一个扇区多少个字节,这个由ffconf.h配置文件的_MAX_SS宏决定,比如我的是4096,那就表示一个扇区4096个字节即4KB

** fatfs:
文件系统指针的指针(其实我不太明白为什么这里要用二级指针,感觉完全没必要啊,可能我这个菜鸟还不知道大佬的别有用心吧)

参考官方例程:

 FATFS *fs;DWORD fre_clust, fre_sect, tot_sect;/* Get volume information and free clusters of drive 1 */res = f_getfree("1:", &fre_clust, &fs);/* Get total sectors and free sectors */tot_sect = (fs->n_fatent - 2) * fs->csize;fre_sect = fre_clust * fs->csize;/* Print the free space (assuming 512 bytes/sector) */printf("%10lu KiB total drive space.\n%10lu KiB available.\n",tot_sect / 2, fre_sect / 2);

f_close:

关闭文件,不用多说了,文件使用完之后,肯定要关闭吧,

FRESULT f_close (FIL* fp     /* [IN] Pointer to the file object */
);

f_opendir:

打开一个已存在的目录,并创建一个目录对象,如果不存在指定目录,则返回FR_NO_PATH

FRESULT f_opendir (DIR* dp,           /* [OUT] Pointer to the directory object structure */const TCHAR* path  /* [IN] Directory name */
);

*dp:创建的目录对象存放在此指针

* path:目录名字

DIR结构体定义如下:

typedef struct {FATFS*   fs;             /*指向文件系统的指针(禁止更改*/WORD   id;             /* 文件系统的逻辑驱动器ID(禁止更改) */WORD  index;          /* 当前读/写索引号*/DWORD  sclust;         /* Table start cluster (0:Root dir) */DWORD clust;          /* Current cluster */DWORD  sect;           /* Current sector */BYTE*   dir;            /* Pointer to the current SFN entry in the win[] */BYTE*    fn;             /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCKUINT    lockid;         /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFNWCHAR*  lfn;            /* 指向长文件名的工作数组 */WORD   lfn_idx;        /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FINDconst TCHAR*   pat;    /* 指向匹配路径的指针 */
#endif
} DIR;

f_closedir:

关闭打开的目录对象。函数成功后,目录对象将不再有效,可以丢弃。

FRESULT f_closedir (DIR* dp     /* [IN] Pointer to the directory object */
);

f_mkdir:

在指定路径创建目录

FRESULT f_mkdir (const TCHAR* path /* [IN] Directory name */
);

* path:指定路径和新文件的名字


f_unlink:

删除文件

FRESULT f_unlink (const TCHAR* path  /* [IN] Object name */
);

f_rename:

移动,重命名文件或子目录

FRESULT f_rename (const TCHAR* old_name, /* [IN] Old object name */const TCHAR* new_name  /* [IN] New object name */
)

old_name :旧文件名(包括路径)
new_name:新文件名(包括路径)


f_stat:

检查文件或子目录是否存在,如果存在,则将文件的信息储存在fno指针指向的FILINFO结构体中

FRESULT f_stat (const TCHAR* path,  /* [IN] Object name */FILINFO* fno        /* [OUT] FILINFO structure */
);

*path:指定文件或子目录路径
*fno: 存储文件信息的FILINFO结构体指针

FILINFO结构体如下:

typedef struct {DWORD    fsize;          /* File size */                     //文件(夹)大小(WORD fdate;          /* Last modified date */            //文件(夹)上次修改日期WORD ftime;          /* Last modified time */            //文件(夹)上次修改时间BYTE fattrib;        /* Attribute */                     //文件(夹)权限TCHAR    fname[13];      /* Short file name (8.3 format) */  //文件(夹)名
#if _USE_LFNTCHAR*  lfname;         /* Pointer to the LFN buffer */     //长文件(夹)名UINT     lfsize;         /* Size of LFN buffer in TCHAR */   //长文件(夹)大小
#endif
} FILINFO;

fattrib成员的所有位的含义如下:

/* File attribute bits for directory entry */#define AM_RDO  0x01    /* Read only */
#define AM_HID  0x02    /* Hidden */
#define AM_SYS  0x04    /* System */
#define AM_VOL  0x08    /* Volume label */
#define AM_LFN  0x0F    /* LFN entry */
#define AM_DIR  0x10    /* Directory */     //文件夹
#define AM_ARC  0x20    /* Archive */       //档案文件(压缩文件)
#define AM_MASK 0x3F    /* Mask of defined bits */

f_readdir:

输入目录对象,将目录中第一个文件(夹)信息存储在参数二指针指向的地址;如果再次调用,则输出目录中第二个文件(夹)信息,以此类推

FRESULT f_readdir (DIR* dp,      /* [IN] Directory object */FILINFO* fno  /* [OUT] File information structure */
);

DIR和FILINFO结构体如下:

typedef struct {FATFS*   fs;             /*指向文件系统的指针(禁止更改*/WORD   id;             /* 文件系统的逻辑驱动器ID(禁止更改) */WORD  index;          /* 当前读/写索引号*/DWORD  sclust;         /* Table start cluster (0:Root dir) */DWORD clust;          /* Current cluster */DWORD  sect;           /* Current sector */BYTE*   dir;            /* Pointer to the current SFN entry in the win[] */BYTE*    fn;             /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCKUINT    lockid;         /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFNWCHAR*  lfn;            /* 指向长文件名的工作数组 */WORD   lfn_idx;        /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FINDconst TCHAR*   pat;    /* 指向匹配路径的指针 */
#endif
} DIR;
typedef struct {DWORD    fsize;          /* File size */                     //文件(夹)大小(WORD fdate;          /* Last modified date */            //文件(夹)上次修改日期WORD ftime;          /* Last modified time */            //文件(夹)上次修改时间BYTE fattrib;        /* Attribute */                     //文件(夹)权限TCHAR    fname[13];      /* Short file name (8.3 format) */  //文件(夹)名
#if _USE_LFNTCHAR*  lfname;         /* Pointer to the LFN buffer */     //长文件(夹)名UINT     lfsize;         /* Size of LFN buffer in TCHAR */   //长文件(夹)大小
#endif
} FILINFO;

这个函数通常会被封装成一个递归函数来实现类似Linux系统中的ls命令功能.
官方给出的递归函数如下:

FRESULT scan_files (char* path        /* Start node to be scanned (also used as work area) */
)
{FRESULT res;FILINFO fno;DIR dir;int i;char *fn;   /* This function assumes non-Unicode configuration */
#if _USE_LFNstatic char lfn[_MAX_LFN + 1];   /* Buffer to store the LFN */fno.lfname = lfn;fno.lfsize = sizeof lfn;
#endifres = f_opendir(&dir, path);                       /* Open the directory */if (res == FR_OK) {i = strlen(path);for (;;) {res = f_readdir(&dir, &fno);                   /* Read a directory item */if (res != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */if (fno.fname[0] == '.') continue;             /* Ignore dot entry */
#if _USE_LFNfn = *fno.lfname ? fno.lfname : fno.fname;
#elsefn = fno.fname;
#endifif (fno.fattrib & AM_DIR) {                    /* It is a directory */sprintf(&path[i], "/%s", fn);res = scan_files(path);path[i] = 0;if (res != FR_OK) break;} else {                                       /* It is a file. */printf("%s/%s\n", path, fn);}}f_closedir(&dir)}return res;
}

Fatfs文件系统常用函数相关推荐

  1. FAFTS文件系统常用函数学习

    一.FATFS文件系统基础知识 1.简介 文件系统可以从官网进行下载 官网地址:http://elm-chan.org/fsw/ff/00index_e.html FATFS是一个完全免费开源的FAT ...

  2. Zynq Fatfs文件系统应用笔记

    Zynq Fatfs文件系统应用笔 Hello,panda 笔记介绍基于所描述的Zynq Fatfs基于Xilinx xilffsv3.0和Sdpsv2.4,文件系统采用在Bare-Metal和轻量级 ...

  3. fatfs 文件属性_Zynq Fatfs文件系统应用笔记

    Zynq Fatfs文件系统应用笔 Hello,panda 笔记介绍基于所描写叙述的Zynq Fatfs基于Xilinx xilffsv3.0和Sdpsv2.4,文件系统採用在Bare-Metal和轻 ...

  4. 学习 stm32 FATFS 系统文件函数使用和学习查看说明以及常用函数例程

    学习 stm32 FATFS 文件的日常操作,本次通过SDIO模式进行存储卡的设备连接,进行数据的读取操作.之前介绍过一起SD卡的读取操作, stm32 SD(SDSC)卡的学习与SPI 模式应用(卡 ...

  5. fatfs文件系统详解之f_mkfs函数分析

    前序 前面两篇文章分析了FAT文件系统,没有代码总感觉很空虚寂寞冷,fatfs正好是一个开源专门应对fat文件系统的代码,从这篇文章开始分析fatfs代码,"理论+实践"才是悟道的 ...

  6. FatFs文件系统Nandflash驱动函数详解

    FatFs文件系统Nandflash驱动函数详解 转载 2015-08-06 14:43:27 标签:nandflash驱动函数详fatfs文件系统nandfla 本文讲解FatFs文件系统 下需要的 ...

  7. fatfs文件系统详解之f_write函数分析

    前序 本篇分析f_write()函数,fatfs文件系统对应的不知道文件的读写,也对应了文件的其他的操作,也有文件夹的操作,函数分析确实是一个非常耗时耗精力的事情,此函数分析完之后,就结束函数分析. ...

  8. FatFs文件系统的移植

    FatFs 的底层可以写一次命令,读写多个扇区.FatFs的设计的读写的思想就很好,小块的数据,我就经过Buffer来存储,大块的数据,我就直接进行存取,那样速度,效率高了很多,看图: FatFs文件 ...

  9. FatFs文件系统移植过程及中度分析

    FatFs 是一个通用的文件系统(FAT/exFAT)模块,用于在小型嵌入式系统中实现FAT文件系统. FatFs 组件的编写遵循ANSI C(C89),完全分离于磁盘 I/O 层,因此不依赖于硬件平 ...

最新文章

  1. 2022-2028年中国ABS管行业市场全景调研及发展趋势分析报告
  2. 如何用Pandas处理文本数据?
  3. 项目分享三:页面之间的传值
  4. java映射文件是哪一种xml_java解析xml的几种方式哪种最好?
  5. hdfs du命令是算的一份数据
  6. 《Pro ASP.NET MVC 3 Framework》学习笔记之二十七【视图1】
  7. 私有句柄表(内核对象,并非用户对象),全局句柄表
  8. mysql pow函数怎么用_pow函数怎么用
  9. 数字化转型之道:如何减少BI建设资源的浪费,缩短项目实施周期
  10. 同一个SQL语句,为啥性能差异咋就这么大呢?
  11. DBCC--SHRINKDATABASE
  12. Android学习笔记---26_采用JSON格式返回数据给资讯客户端,效率上要高于xml文件解析和传输
  13. [毕业生的商业软件开发之路]系列文章目录规划
  14. 我什么时候应该真正使用noexcept?
  15. 编程之美读书笔记2.15 - 子数组之和的最大值(二维)
  16. [Search Engine] 搜索引擎技术之倒排索引
  17. 软件工程期末试题及答案(史上最全)
  18. 不定积分24个基本公式整理
  19. 目标检测网络的知识蒸馏
  20. win7事件查看器事件id_使用免费工具从事件查看器中查找事件ID

热门文章

  1. 【Linux篇】第十一篇——动静态库(动静态库的介绍+动静态库的打包与使用)
  2. 南工大计算机录取分数线,南京工业大学2016年录取分数线
  3. pyppeteer 绕过selenium检测,实现淘宝登陆
  4. RFID如何实现酒类防伪溯源?
  5. vue-seamless-scroll无缝循环滚动时二轮图片不渲染
  6. vivo手机怎么恢复信息_vivo手机短信删除了怎么恢复?如何查看误删的数据短信...
  7. 谈结构体struct 初始化多出的点号“.”,数组[]初始化多出的逗号“,”
  8. Java推箱子小游戏
  9. 桌面宠物鹅 DesktopGoose下载
  10. 史上十大最笨网上创业点子