Fatfs文件系统常用函数
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文件系统常用函数相关推荐
- FAFTS文件系统常用函数学习
一.FATFS文件系统基础知识 1.简介 文件系统可以从官网进行下载 官网地址:http://elm-chan.org/fsw/ff/00index_e.html FATFS是一个完全免费开源的FAT ...
- Zynq Fatfs文件系统应用笔记
Zynq Fatfs文件系统应用笔 Hello,panda 笔记介绍基于所描述的Zynq Fatfs基于Xilinx xilffsv3.0和Sdpsv2.4,文件系统采用在Bare-Metal和轻量级 ...
- fatfs 文件属性_Zynq Fatfs文件系统应用笔记
Zynq Fatfs文件系统应用笔 Hello,panda 笔记介绍基于所描写叙述的Zynq Fatfs基于Xilinx xilffsv3.0和Sdpsv2.4,文件系统採用在Bare-Metal和轻 ...
- 学习 stm32 FATFS 系统文件函数使用和学习查看说明以及常用函数例程
学习 stm32 FATFS 文件的日常操作,本次通过SDIO模式进行存储卡的设备连接,进行数据的读取操作.之前介绍过一起SD卡的读取操作, stm32 SD(SDSC)卡的学习与SPI 模式应用(卡 ...
- fatfs文件系统详解之f_mkfs函数分析
前序 前面两篇文章分析了FAT文件系统,没有代码总感觉很空虚寂寞冷,fatfs正好是一个开源专门应对fat文件系统的代码,从这篇文章开始分析fatfs代码,"理论+实践"才是悟道的 ...
- FatFs文件系统Nandflash驱动函数详解
FatFs文件系统Nandflash驱动函数详解 转载 2015-08-06 14:43:27 标签:nandflash驱动函数详fatfs文件系统nandfla 本文讲解FatFs文件系统 下需要的 ...
- fatfs文件系统详解之f_write函数分析
前序 本篇分析f_write()函数,fatfs文件系统对应的不知道文件的读写,也对应了文件的其他的操作,也有文件夹的操作,函数分析确实是一个非常耗时耗精力的事情,此函数分析完之后,就结束函数分析. ...
- FatFs文件系统的移植
FatFs 的底层可以写一次命令,读写多个扇区.FatFs的设计的读写的思想就很好,小块的数据,我就经过Buffer来存储,大块的数据,我就直接进行存取,那样速度,效率高了很多,看图: FatFs文件 ...
- FatFs文件系统移植过程及中度分析
FatFs 是一个通用的文件系统(FAT/exFAT)模块,用于在小型嵌入式系统中实现FAT文件系统. FatFs 组件的编写遵循ANSI C(C89),完全分离于磁盘 I/O 层,因此不依赖于硬件平 ...
最新文章
- 2022-2028年中国ABS管行业市场全景调研及发展趋势分析报告
- 如何用Pandas处理文本数据?
- 项目分享三:页面之间的传值
- java映射文件是哪一种xml_java解析xml的几种方式哪种最好?
- hdfs du命令是算的一份数据
- 《Pro ASP.NET MVC 3 Framework》学习笔记之二十七【视图1】
- 私有句柄表(内核对象,并非用户对象),全局句柄表
- mysql pow函数怎么用_pow函数怎么用
- 数字化转型之道:如何减少BI建设资源的浪费,缩短项目实施周期
- 同一个SQL语句,为啥性能差异咋就这么大呢?
- DBCC--SHRINKDATABASE
- Android学习笔记---26_采用JSON格式返回数据给资讯客户端,效率上要高于xml文件解析和传输
- [毕业生的商业软件开发之路]系列文章目录规划
- 我什么时候应该真正使用noexcept?
- 编程之美读书笔记2.15 - 子数组之和的最大值(二维)
- [Search Engine] 搜索引擎技术之倒排索引
- 软件工程期末试题及答案(史上最全)
- 不定积分24个基本公式整理
- 目标检测网络的知识蒸馏
- win7事件查看器事件id_使用免费工具从事件查看器中查找事件ID
热门文章
- 【Linux篇】第十一篇——动静态库(动静态库的介绍+动静态库的打包与使用)
- 南工大计算机录取分数线,南京工业大学2016年录取分数线
- pyppeteer 绕过selenium检测,实现淘宝登陆
- RFID如何实现酒类防伪溯源?
- vue-seamless-scroll无缝循环滚动时二轮图片不渲染
- vivo手机怎么恢复信息_vivo手机短信删除了怎么恢复?如何查看误删的数据短信...
- 谈结构体struct 初始化多出的点号“.”,数组[]初始化多出的逗号“,”
- Java推箱子小游戏
- 桌面宠物鹅 DesktopGoose下载
- 史上十大最笨网上创业点子