一、FATFS文件系统基础知识
1.简介
文件系统可以从官网进行下载
官网地址:http://elm-chan.org/fsw/ff/00index_e.html
FATFS是一个完全免费开源的FAT 文件系统模块,FatFs模块是按照ANSI C(C89)编写的,并且与磁盘I / O层完全分开,它支持FATl2、FATl6 和FAT32,支持多个存储媒介,有独立的缓冲区,可以对多个文件进行读/写,并特别对8 位单片机和16 位单片机做了优化,。因此,它独立于平台。它可以并入资源有限的小型微控制器中,例如8051,PIC,AVR,ARM,Z80,RX等,具有良好的硬件平台独立性。
2.特征
- DOS / Windows兼容的FAT / exFAT文件系统。
- 平台无关。容易移植。
- 程序代码和工作区的占用空间非常小。
- 支持以下各种配置选项:
- ANSI / OEM或Unicode中的长文件名。
- exFAT文件系统,64位LBA和GPT可存储大量数据。
- RTOS的线程安全。
- 多个卷(物理驱动器和分区)。
- 可变扇区大小。
- 多个代码页,包括DBCS。
- 只读,可选API,I / O缓冲区等
二、文件接口
1.f_open
函数作用:
f_open`函数打开一个文件,并创建一个文件对象。文件对象用于随后对文件的读/写操作以标识文件。访问文件的会话之后,应使用f_close函数关闭打开的文件。如果对文件进行了任何更改并且在关闭电源之前未关闭文件,则介质移除或重新安装或文件可能会折叠。
函数体:
FRESULT f_open(
FIL * fp, / * 指向文件对象结构的指针* /
const TCHAR * path,/ * 文件名* /
BYTE mode / * 模式标志* /
);
参数含义:
fp:指向空白文件对象结构的指针。
路径:指向以空值结尾的字符串的指针,该字符串指定要打开或创建的文件名。如:“0:message.txt"
模式:
标志 | 含义 |
FA_READ | 指定对对象的读取访问权限。可以从文件中读取数据。 |
FA_WRITE | 指定对对象的写访问。数据可以写入文件。与 |
FA_OPEN_EXISTING | 打开文件。如果文件不存在,该功能将失败。(默认) |
FA_CREATE_NEW | 创建一个新文件。如果该文件存在,则函数失败并显示 |
FA_CREATE_ALWAYS | 创建一个新文件。如果文件已存在,它将被截断并覆盖。 |
FA_OPEN_ALWAYS | 打开文件(如果存在)。如果没有,将创建一个新文件。 |
FA_OPEN_APPEND | 与 |
举例:
2.f_close
函数作用:
f_close函数关闭一个打开的文件对象。如果文件已更改,则文件的缓存信息将写回到该卷。函数成功后,文件对象不再有效,可以将其丢弃。
函数体
FRESULT f_close (
FIL* fp /* 指向文件对象的指针 */
);
3.f_read
函数作用:
该函数以读/写指针指向的文件偏移量开始从文件中读取数据。读/写指针随着读取的字节数而增加。函数成功后,应检查* br以检测文件结尾。如果* br < btr,则意味着在读操作期间读/写指针到达文件的末尾。
FRESULT f_read(
FIL * fp, / * [IN]文件对象* /
void * buff, / * [OUT]存储读取数据的缓冲区* /
UINT btr, / * [IN]要读取的字节数* /
UINT * br / * [OUT]读取的字节数* /
);
4.f_write
函数作用 :
函数开始在读/写指针指向的文件偏移量处向文件写入数据。读/写指针随着写入的字节数而增加。函数成功后,应检查bw以检测磁盘已满。如果bw<btw,则表示写入操作期间卷已满。当卷已满或接近满时,此功能可能需要一段时间。
函数体:
FRESULT f_write(
FIL * fp, / * [IN]指向文件对象结构的指针* /
const void * buff,/ * [IN]指向要写入的数据的指针* /
UINT btw, / * [IN]要写入的字节数* /
UINT * bw / * [OUT]指向变量的指针,以返回写入的字节数* /
);
5.f_gets
函数作用:
读取操作将继续进行,直到存储了一个'\ n',到达文件末尾或缓冲区中的len-1个字符为止。读取的字符串以'\ 0'终止。当没有字符要读取或在读取操作期间发生任何错误时,它将返回空指针。可以使用f_eof和f_error函数检查EOF和错误的状态。
函数体:
TCHAR * f_gets(
TCHAR * buff,/ * [OUT]读取缓冲区* /
int len, / * [IN]读取缓冲区的大小* /
FIL * fp / * [IN]文件对象* /
);
6.f_puts
函数作用:
成功写入字符串后,它将返回写入文件的字符编码单元数。当功能由于磁盘已满或任何错误而失败时,将返回EOF(-1)。
函数体:
int f_puts(
const TCHAR * str,/ * [IN]字符串* /
FIL * fp / * [IN]文件对象* /
);
读/写一个字符和读/写一个字符串大致相同,将要读/写入的变量定义成TCHAR即可。
7.f_eof
函数作用:
f_eof函数测试文件的文件结尾,如果读/写指针已到达文件的结束则返回一个非零值; 否则返回零。
函数体:
int f_eof(
FIL * fp / * [IN]文件对象* /
);
8.f_error
函数作用:
检测文件系统是否发生硬件错误,若未发生异常返回一个非零值,发生异常则返回0。
函数体:
int f_error (
FIL* fp /* [IN] File object */
);
整体应用:
/* Read a text file and display it */
FATFS FatFs; /* Work area (filesystem object) for logical drive */
int main (void)
{
FIL fil; /* File object */
char line[100]; /* Line buffer */
FRESULT fr; /* FatFs return code */
/* Gives a work area to the default drive */
f_mount(&FatFs, "", 0);
/* Open a text file */
fr = f_open(&fil, "message.txt", FA_READ);
if (fr) return (int)fr;
/* Read every line and display it */
while (f_gets(line, sizeof line, &fil)) {
printf(line);
}
/* Close the file */
f_close(&fil);
return 0;
}
/* Copy a file "file.bin" on the drive 1 to drive 0 */
int main (void)
{
FATFS fs0, fs1; /* Work area (filesystem object) for logical drives */
FIL fsrc, fdst; /* File objects */
BYTE buffer[4096]; /* File copy buffer */
FRESULT fr; /* FatFs function common result code */
UINT br, bw; /* File read/write count */
/* Gives work area to each logical drive */
f_mount(&fs0, "0:", 0);
f_mount(&fs1, "1:", 0);
/* Open source file on the drive 1 */
fr = f_open(&fsrc, "1:file.bin", FA_READ);
if (fr) return (int)fr;
/* Create destination file on the drive 0 */
fr = f_open(&fdst, "0:file.bin", FA_WRITE | FA_CREATE_ALWAYS);
if (fr) return (int)fr;
/* Copy source to destination */
for (;;) {
f_read(&fsrc, buffer, sizeof buffer, &br); /* Read a chunk of data from the source file */
if (br == 0) break; /* error or eof */
f_write(&fdst, buffer, br, &bw); /* Write it to the destination file */
if (bw < br) break; /* error or disk full */
}
/* Close open files */
f_close(&fsrc);
f_close(&fdst);
/* Unregister work area prior to discard it */
f_mount(0, "0:", 0);
f_mount(0, "1:", 0);
return (int)fr;
}
三、目录接口
1.f_opendir
函数作用:
打开已存在的目录,并且为随后使用到的f_readdir函数创建一个目录对象。
函数体:
FRESULT f_opendir (
DIR* dp, /* [OUT] Pointer to the directory object structure */
const TCHAR* path /* [IN] Directory name */
);
2.f_clodedir
函数作用:
关闭一个打开的目录,当函数作用成功后,目录对象不再有效,可以被丢弃。
函数体:
FRESULT f_closedir (
DIR* dp /* [IN] Pointer to the directory object */
);
3.f_findfirst
函数作用:
在可以打开路径指定的目录后,它开始搜索目录中具有模式指定的匹配模式的项目。如果找到第一个项,则有关该项的信息将存储在文件信息结构fno 中。
函数体:
FRESULT f_findfirst (
DIR* dp, /* [OUT] Poninter to the directory object */
FILINFO* fno, /* [OUT] Pointer to the file information structure */
const TCHAR* path, /* [IN] Pointer to the directory name to be opened */
const TCHAR* pattern /* [IN] Pointer to the matching pattern string */
);
参数:
Dp:
指向空白目录对象的指针。
fno:
指向文件信息结构的指针,以存储有关找到的项的信息。
path:
指向指定要打开的目录名称的空终止字符串的指针。
mode:
指向 nul 终止字符串的指针,该字符串指定要搜索的名称匹配模式。它由后续函数f_findnext引用,因此字符串在连续函数调用时必须有效。
4.f_findnext
函数作用:
它继续搜索从上一个调用到f_findfirst或f_findnext函数。如果找到,有关该对象的信息将存储在文件信息结构中。如果没有要读取的项,则空字符串将返回到fno->fname= 中。
函数体:
FRESULT f_findnext (
DIR* dp, /* [IN] Poninter to the directory object */
FILINFO* fno /* [OUT] Pointer to the file information structure */
);
应用示例:
/* Search a directory for objects and display it */
void find_image_file (void)
{
FRESULT fr; /* Return value */
DIR dj; /* Directory object */
FILINFO fno; /* File information */
fr = f_findfirst(&dj, &fno, "", "dsc*.jpg"); /* Start to search for photo files */
while (fr == FR_OK && fno.fname[0]) { /* Repeat while an item is found */
printf("%s\n", fno.fname); /* Print the object name */
fr = f_findnext(&dj, &fno); /* Search for next item */
}
f_closedir(&dj);
}
对于其中的f_findfirst函数调用,可以使用通配符匹配,包含通配符(? 和 *)。例如,与任何字符匹配,* 匹配长度为零或更长的任何字符串,并且???* 匹配长度为 3 个字符或更长的任何字符串,例中dsc*.jpg就是指dsc开头,后面任意长度内容最后以.jpg结尾的字符串。
四、卷管理和系统配置接口
1.f_mount
函数作用:
FatFs 需要每个逻辑驱动器(FAT 卷) 的工作区 ( 文件系统对象 )。在执行任何文件/目录操作之前,需要向逻辑驱动器的f_mount注册文件系统对象。此过程后,文件/目录 API 函数即可开始工作。某些卷管理函数f_mkfs,f_fdisk,f_setcp和文件,不需要文件系统对象。
f_mount将文件系统对象注册/取消注册到 FatF 模块,如下所示:
- 确定由路径指定的逻辑驱动器。
- 清除和取消注册卷的重新注册工作区(如果存在)。
- 如果fs不是 NULL,则清除新工作区并注册到卷。
- 如果指定了强制装载,则对卷执行卷装载过程。
如果逻辑驱动器上有任何打开的文件或目录对象,则该对象将因此函数而失效。
如果未指定强制安装(选择= 0),则无论物理驱动器状态如何,此功能始终成功。它只清除(去初始化)给定工作区,并将其地址注册到内部表,并且此函数中的物理驱动器没有活动。如果未初始化文件系统对象,则将在后续文件/直接函数上尝试卷装载过程。(延迟安装)卷装载进程,初始化相应的物理驱动器,查找其中 FAT 卷,然后初始化工作区,在后续文件/目录函数中执行,当以下任一条件为真时。
- 文件系统对象尚未初始化。它由函数f_mount初始化。
- 物理驱动器未初始化。它通过系统重置或介质移除而取消初始化。
如果强制安装(opt = 1) FR_NOT_READY失败,则表示文件系统对象已成功注册,但卷当前尚未准备好工作。将在后续文件/直接函数上尝试卷装载过程。
如果磁盘 I/O 层的实现缺少异步介质更改检测,则应用程序需要在每次介质更改后执行 f_mount函数以强制清除文件系统对象。
要取消注册工作区,指定一个 NULL 到fs,然后可以丢弃工作区。
简言之就是起到一个挂载作用。
函数体:
FRESULT f_mount (
FATFS* fs, /* [IN] Filesystem object */
const TCHAR* path, /* [IN] Logical drive number */
BYTE opt /* [IN] Initialization option */
);
参数:
fs:
指向要注册和清除的文件系统对象的指针。空指针取消注册文件系统对象。
path:
指向指定逻辑驱动器的空终止字符串的指针。不带驱动器号的字符串表示默认驱动器。
opt:
安装选项。0:现在不要装载(要装载在第一次访问卷上),1:强制装载卷以检查卷是否已准备好工作。
实例:
int main (void)
{
FATFS *fs; /* Ponter to the filesystem object */
fs = malloc(sizeof (FATFS)); /* Get work area for the volume */
f_mount(fs, "", 0); /* Mount the default drive */
f_open(... /* Here any file API can be used */
...
f_mount(fs, "", 0); /* Re-mount the default drive to reinitialize the filesystem */
...
f_mount(0, "", 0); /* Unmount the default drive */
free(fs); /* Here the work area can be discarded */
...
}
2.f_mkfs
函数作用:该f_mkfs在逻辑驱动器上创建 FAT/exFAT 卷。
函数体:
FRESULT f_mkfs (
const TCHAR* path, /* [IN] Logical drive number */
const MKFS_PARM* opt,/* [IN] Format options */
void* work, /* [-] Working buffer */
UINT len /* [IN] Size of working buffer */
);
参数:
- path:
指向空终止字符串的指针指定要格式化的逻辑驱动器。如果它没有驱动器号,则意味着指定默认驱动器。逻辑驱动器可能已装载,也可能未为格式进程安装。
- opt:
指定保存格式选项的结构。如果给定一个空指针,它将为函数提供默认值中的所有选项。格式选项结构有五个成员,描述如下:
- BYTE fmt:
指定 FAT 类型标志、FM_FAT、FM_FAT32、FM_EXFAT和位或这三个标记的组合FM_ANY。 FM_EXFAT启用 exFAT 时,将忽略此错误。这些标志指定要在卷上创建的 FAT 类型。如果指定了两种或两种类型,则将选择其中一种类型,这取决于卷大小和au_size。标志FM_SFD指定以 SFD 格式在驱动器上创建卷。默认值为FM_ANY。
- DWORD au_size:
指定以字节单位表示分配单位(cluter)的大小。有效值是扇区大小之间的 2 和 128 * 扇区大小的功率,包括 FAT/FAT32 卷和高达 16 MB 的 exFAT 卷。如果给出零(默认值)或任何无效值,则默认分配单位大小取决于使用的卷大小。
- UINT n_align:
指定卷数据区域(文件分配池,通常擦除闪存介质的块边界)在扇区单位中的对齐方式。此成员的有效值介于 1 和 32768 之间,包括 2。如果给出零(默认值)或任何无效值,则函数会从具有"一个函数"的较低层disk_ioctl大小。
- BYTE n_fat:
指定 FAT/FAT32 卷上的 FAT 副本数。此成员的有效值为 1 或 2。默认值 (0) 和任何 invaid 值给出 1。如果 FAT 类型为 exFAT,则此成员不起作用。
- UINT n_root:
指定 FAT 卷上的根目录条目数。此成员的有效值高达 32768,与扇区大小 / 32 对齐。默认值 (0) 和任何 invaid 值给出 512。如果 FAT 类型为 FAT32 或 exFAT,则此成员不起作用。
- work:
指向用于格式化过程的工作缓冲区的指针。当一个空指针被用FF_USE_LFN==3进行赋值时,函数将在此函数中为工作缓冲区获取内存块。
- len:
工作缓冲区的大小(以字节单位表示)。它至少需要FF_MAX_SS一点。大量工作缓冲区减少了驱动器的写入事务数,并且格式过程将快速完成。
实例:
/* Format default drive and create a file */
int main (void)
{
FATFS fs; /* Filesystem object */
FIL fil; /* File object */
FRESULT res; /* API result code */
UINT bw; /* Bytes written */
BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */
/* Format the default drive with default parameters */
res = f_mkfs("", 0, work, sizeof work);
if (res) ...
/* Gives a work area to the default drive */
f_mount(&fs, "", 0);
/* Create a file as new */
res = f_open(&fil, "hello.txt", FA_CREATE_NEW | FA_WRITE);
if (res) ...
/* Write a message */
f_write(&fil, "Hello, World!\r\n", 15, &bw);
if (bw != 15) ...
/* Close the file */
f_close(&fil);
/* Unregister work area */
f_mount(0, "", 0);
...
3.f_getfree
函数作用:
获取卷上可用的集群数。
函数体:
FRESULT f_getfree (
const TCHAR* path, /* [IN] Logical drive number */
DWORD* nclst, /* [OUT] Number of free clusters */
FATFS** fatfs /* [OUT] Corresponding filesystem object */
);
参数:
path:
指向指定逻辑驱动器的空终止字符串的指针。空字符串表示默认驱动器。
nclst:
指向DWORD 类型的指针以存储可用群集的数量。
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);
if (res) die(res);
/* 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);