Fatfs文件系统常用函数

这篇具有很好参考价值的文章主要介绍了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_LOCK
	UINT	lockid;			/* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFN
	WCHAR*	lfn;			/* 指向长文件名的工作数组 */
	WORD	lfn_idx;		/* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FIND
	const 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_LFN
	TCHAR*	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_LOCK
	UINT	lockid;			/* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFN
	WCHAR*	lfn;			/* 指向长文件名的工作数组 */
	WORD	lfn_idx;		/* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FIND
	const 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_LFN
	TCHAR*	lfname;			/* Pointer to the LFN buffer */		//长文件(夹)名
	UINT 	lfsize;			/* Size of LFN buffer in TCHAR */	//长文件(夹)大小
#endif
} FILINFO;

这个函数通常会被封装成一个递归函数来实现类似Linux系统中的ls命令功能.
官方给出的递归函数如下:文章来源地址https://www.toymoban.com/news/detail-753528.html

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_LFN
    static char lfn[_MAX_LFN + 1];   /* Buffer to store the LFN */
    fno.lfname = lfn;
    fno.lfsize = sizeof lfn;
#endif


    res = 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_LFN
            fn = *fno.lfname ? fno.lfname : fno.fname;
#else
            fn = fno.fname;
#endif
            if (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文件系统常用函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32-基本知识梳理8-FATFS文件系统移植

    一、基本概念 1,为什么需要文件系统? 在没有文件系统的存储器中,一般通过手工记录,那些变量存放在那些位置,很难有系统的管理 难以记录有效数据的位置 、难以确定存储介质的剩余空间、 不明确应以何种格式来解读数据 加入文件系统后,就可以引导区、目录等对内

    2024年02月03日
    浏览(43)
  • 【STM32】文件系统FATFS与Flash的初步使用

    简介可以不看,直接看移植步骤 文件系统是介于应用层和底层间的模糊层。底层提供API,比如说使用SDIO或者SPI等读写一个字节。文件系统把这些API组合包装起来,并且提供一些列函数,我们可以使用这些函数进行更进一步的对存储设备的操作。 底层:操作单片机外设,读写

    2024年02月10日
    浏览(37)
  • 【STM32】FATFS文件系统f_mkfs卡死

    最近调试FATFS,通过STM32对SPI Flash进行读写操作。昨天晚上调通了,今天早上再调试,发现f_mount返回FR_NOFILESYSTEM。 依据网上所说,对磁盘格式化f_mkfs,卡死在FATFS库的ff.c-f_mkfs()的某个for循环里。 f_mkfs卡死的for循环代码位置 最后对SPI Flash进行了全片擦除命令,之后就可以正常

    2024年02月02日
    浏览(42)
  • STM32CubeMX教程28 SDIO - 使用FatFs文件系统读写SD卡

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 SDIO使用FatFs中间件读写4线SD卡,并实现以轮询方式读写SD卡或以DMA方式读取SD卡 FatFs文件系统相关知识请读者

    2024年02月19日
    浏览(51)
  • STM32CubeMX系列09——SDIO(SD卡读写、SD卡移植FATFS文件系统)

    ==== 文章汇总(有代码汇总) ==== 准备看看这方面的知识,一时间还没不清有什么区别,先补补课,不需要的跳过。 参考文章(内容来源):http://www.360doc.com/content/21/1125/22/59057945_1005908465.shtml 主要写这两个:SD卡、TF卡 共同点:SD、TF、MMC都是在MMC基础上演化发展不同的规范,

    2024年02月09日
    浏览(49)
  • STM32CubeMX教程26 FatFs 文件系统 - W25Q128读写

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 使用FatFs中间件通过SPI通信协议对W25Q128芯片进行读写等操作 关于STM32F407使用SPI通信协议对W25Q128 FLASH芯片读写

    2024年02月19日
    浏览(55)
  • STM32CubeMX教程29 USB_HOST - 使用FatFs文件系统读写U盘

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 USB_OTG_FS为工作在Mass Storage Host Class(大容量存储主机类)模式下的USB_HOST(USB主机),并使用FatFs文件系统对

    2024年02月19日
    浏览(45)
  • STM32F429 Discovery开发板应用:实现SPI-SD Card文件写入(搭载FatFS文件系统)

    MCU:STM32F429ZIT6 开发环境:STM32CubeMX+MDK5   外购了一个SPI接口的SD Card模块,想要实现SD卡存储数据的功能。 首先需要打开STM32CubeMX工具。输入开发板MCU对应型号,找到开发板对应封装的MCU型号,双击打开(图中第三)。   此时,双击完后会关闭此界面,然后打开一个新界面。

    2024年02月08日
    浏览(59)
  • STM32使用HAL库SPI驱动W25Q16 使用FATFS文件系统+USB虚拟U盘

    使用stm32F407驱动W25Q16,使用FATFS文件系统,USB虚拟优盘功能,W25Q16一共512个扇区,其中128作为flash存取相关数据,其他的384个扇区用作虚拟U盘使用 W25Q16.c W25Q16.h user_diskio.c usbd_storage_if.c main.c STORAGE_BLK_NBR 表示扇区数量 STORAGE_BLK_SIZ 表示扇区大小 电脑上的U盘容量跟这两个参数密

    2024年04月28日
    浏览(45)
  • 【Linux操作系统】举例解释Linux系统编程中文件io常用的函数

    在Linux系统编程中,文件IO操作是非常常见和重要的操作之一。通过文件IO操作,我们可以打开、读取、写入和关闭文件,对文件进行定位、复制、删除和重命名等操作。本篇博客将介绍一些常用的文件IO操作函数。 1.1 原型、参数及返回值说明 1.1.1 原型: open()函数是Linux系统

    2024年02月12日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包