FATFS:一个兼容windows的嵌入式文件系统API使用详解

2023-11-03

FATFS:一个兼容windows的嵌入式文件系统API使用详解



FATFS官网:http://elm-chan.org/fsw/ff/00index_e.html

本篇博客不讲解移植教程,只讲解常用API如何使用。


(1)API分类

文件操作类:

目录操作类:

文件和目录管理:

文件系统管理:


(2)常用API说明

2.1 挂载文件系统与解除挂载


/**
 * 挂载文件系统
 * @param  fs   文件系统句柄
 * @param  path 逻辑驱动器号码
 * @param  opt  初始化属性,=0:在第一次访问文件系统的时候挂载,=1:立刻挂载
 * @return      成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 *
 * FATFS fs;
 * 示例:f_mount(&fs, "0:/", 1);
 */
FRESULT f_mount(FATFS* fs, const TCHAR* path, BYTE opt);


/**
 * 解除挂载
 * @param  path 逻辑驱动器号码
 * @return      成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 *
 * 示例:f_unmount("0:/");
 */
FRESULT f_unmount (const TCHAR* path);

注意:旧版本的FATFS没有f_unmount函数,取消挂载是使用f_mount函数:

f_mount(NULL, "0:/", 1);

2.2 文件操作

2.2.1 文件的打开和关闭
/**
 * 打开文件
 * @param  fp   文件句柄
 * @param  path 文件路径
 * @param  mode 打开模式
 * @return      成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 *
 * FIL fp;
 * 示例:f_open(&fp, "0:/helloworld.txt", FA_CREATE_ALWAYS | FA_WRITE | FA_READ)
 */
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);

/**
 * 关闭文件
 * @param  fp 文件句柄
 * @return    成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 */
FRESULT f_close (FIL* fp);

mode参数说明:

  • FA_READ:只读
  • FA_WRITE:只写
  • FA_OPEN_EXISTING:打开已经存在的文件,如果文件不存在则打开失败
  • FA_CREATE_NEW:创建文件,如果文件已存在则创建失败
  • FA_CREATE_ALWAYS:始终创建文件,如果文件已存在则会清空文件
  • FA_OPEN_ALWAYS:始终打开文件,如果文件不存在则创建
  • FA_OPEN_APPEND:以追加的形式打开文件

以上参数可以组合使用。

2.2.2 读写文件和获取文件大小

读文件:

/**
 * 从文件中读数据
 * @param  fp   文件句柄
 * @param  buff 存放读取到的数据
 * @param  btr  要读取的字节数
 * @param  br   实际读取到的字节数
 * @return      成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 *
 * 示例:
 * FIL fp;
 * char buf[128];
 * UINT nread = 0;
 * f_read(&fp, buf, sizeof(buf), &nread);
 */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);

写文件:

/**
 * 向文件写数据
 * @param  fp   文件句柄
 * @param  buff 待写入的数据
 * @param  btw  待写入的数据字节数
 * @param  bw   实际写入的字节数
 * @return      成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 *
 * 示例:
 * FIL fp;
 * const char* str = "helloworld";
 * UINT nwrite = 0;
 * f_write(&fp, str, strlen(buf), &nwrite);
 */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);

获取打开的文件大小:

/**
 * 获取文件大小
 * @param  fp 文件句柄
 * @return    成功返回FR_OK,失败返回其他值,具体看FRESULT定义
 */
FSIZE_t f_size (FIL* fp);

注意:f_size只能用于文件被打开后,它其实是一个宏定义:

#define f_size(fp) ((fp)->obj.objsize)

(3)FATFS二次接口

//
/**
 * @file  fops.c
 * @autor lakun@qq.com
 * @data  2020/3/5
 */
//
#include "fops.h"
#include <stdio.h>

FILINFO USERFileInfo;	//文件信息
DIR USERDir;  			//目录

void exf_getfree(SDCard_InfoTypedef *sdinfo)
{
    FATFS *fs = NULL;
    DWORD fre_clust = 0;
    if (sdinfo != NULL)
    {
        memset(sdinfo, 0X00, sizeof(SDCard_InfoTypedef));
        if (f_getfree(USERPath, &fre_clust, &fs) == FR_OK)
        {
            sdinfo->tot_sect = (fs->n_fatent - 2) * fs->csize;		// 总扇区数
            sdinfo->fre_sect = fre_clust * fs->csize;				// 空闲扇区数
            sdinfo->tol_capacity = sdinfo->tot_sect >> 11;		// 转为MB
            sdinfo->fre_capacity = sdinfo->fre_sect >> 11;		// 转为MB
        }
    }
}

FRESULT exf_mount(void)
{
#if _USE_LFN
    static char LFNAME[_MAX_LFN * 2 + 1];  /* 一个汉字占用2个字节 */
    USERFileInfo.lfsize = sizeof(LFNAME);
    USERFileInfo.lfname = LFNAME;
#endif
    FATFS_LinkDriver(&USER_Driver, USERPath);
    return f_mount(&USERFatFS, USERPath, 1);
}

FRESULT exf_format(
    BYTE sfd,			/* Partitioning rule 0:FDISK, 1:SFD */
    UINT au				/* Size of allocation unit in unit of byte or sector */
)
{
    return f_mkfs(USERPath, sfd, au);
}

FRESULT exf_unmount(void)
{
    FATFS_UnLinkDriver(USERPath);
    return f_mount(NULL, USERPath, 1);
}

FRESULT exf_open(const void *filename, BYTE mode)
{
    return f_open(&USERFile, filename, mode);
}

uint32_t exf_get_open_file_size(void)
{
    return USERFile.fsize;
}

int exf_write(const void *buf, uint32_t len)
{
    FRESULT res = FR_OK;
    UINT btw = 0;
    res = f_write(&USERFile, (uint8_t*) buf, len, &btw);
    if(res != FR_OK)
    {
        return -1;
    }
    return (int)btw;
}

int exf_read(void *buf, uint32_t len)
{
    FRESULT res = FR_OK;
    UINT btr = 0;
    res = f_read(&USERFile, buf, len, &btr);
    if(res != FR_OK)
    {
        return -1;
    }
    return (int)btr;
}

bool exf_gets(void* buf, uint32_t len)
{
    return f_gets((TCHAR *)buf, len, &USERFile) == NULL ? false : true;
}

FRESULT exf_scan_files (char* path)
{
    FRESULT res;
    DIR dir;                //目录信息,注意这个结构很大
	FILINFO USERFileInfo;	//文件信息,注意这个结构很大
    UINT i;
    char *fn;   /* This function is assuming non-Unicode cfg. */
    res = f_opendir(&dir, path);                       /* Open the directory */
    if (res == FR_OK)
    {
        for (;;)
        {
            res = f_readdir(&dir, &USERFileInfo);                   /* Read a directory item */
            if (res != FR_OK || USERFileInfo.fname[0] == 0) break;  /* Break on error or end of dir */
			//if (USERFileInfo.fname[0] == '.') continue;             /* 忽略上级目录 */
            if (USERFileInfo.fattrib & AM_DIR)                      /* It is a directory */
            {
                i = strlen(path);
#if _USE_LFN
                fn = *USERFileInfo.lfname ? USERFileInfo.lfname : USERFileInfo.fname;
#else
                fn = USERFileInfo.fname;
#endif
                sprintf(&path[i], "/%s", fn);
                res = exf_scan_files(path);                    /* Enter the directory */
                if (res != FR_OK) break;
                path[i] = 0;
            }
            else                                           /* It is a file. */
            {
#if _USE_LFN
                fn = *USERFileInfo.lfname ? USERFileInfo.lfname : USERFileInfo.fname;
#else
                fn = USERFileInfo.fname;
#endif
                printf("%s/%s\n", path, fn);
            }
        }
        f_closedir(&dir);
    }

    return res;
}

bool exf_lseek(DWORD offset)
{
    if(f_lseek(&USERFile, offset) == FR_OK)
    {
        return true;
    }
    return false;
}

void exf_close(void)
{
    f_close(&USERFile);
}


//
/**
 * @file  fops.h
 * @autor lakun@qq.com
 * @data  2020/3/5
 * @note  FatFs操作SD卡API
 */
//

#ifndef __FOPS_H
#define __FOPS_H

#include "main.h"
#include "fatfs.h"
#include <string.h>
#include <stdbool.h>

typedef struct
{
    DWORD fre_sect;        /* 空闲扇区数 */
    DWORD tot_sect;        /* 总扇区数 */
    DWORD fre_capacity;    /* 空闲容量,单位MB */
    DWORD tol_capacity;    /* 总容量,单位MB */
} SDCard_InfoTypedef;

void exf_getfree(SDCard_InfoTypedef* sdinfo);
FRESULT exf_mount(void);
FRESULT exf_unmount(void);
FRESULT exf_open(const void* filename, BYTE mode);
int exf_write(const void *buf, uint32_t len);
int exf_read(void* buf, uint32_t len);
bool exf_gets(void* buf, uint32_t len);
bool exf_lseek(DWORD offset);
void exf_close(void);
FRESULT exf_format(BYTE sfd, UINT au);
uint32_t exf_get_open_file_size(void);
FRESULT exf_scan_files (char* path);

extern FILINFO USERFileInfo;	//文件信息
extern DIR USERDir;  			//目录

#endif

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FATFS:一个兼容windows的嵌入式文件系统API使用详解 的相关文章

随机推荐

  • 010 - STM32学习笔记 - SysTick系统定时器

    010 STM32学习笔记 SysTick系统定时器 1 SysTick简介 SysTick是属于Cortex M内核的一个外设 嵌套在NVIC中 系统定时器是一个24位的递减计数器 每次计数事件位1 SYSCLK 在F429中之前配置的S
  • 最多变的混合模式-实色混合HardMix

    最多变的混合模式 实色混合HardMix 之前写过一篇介绍27种图层混合模式的非常详细 如果你想完全了解底层的原理 这篇文章不会让你失望 PS图层混合模式超详细解答 图层混合模式的原理 王先生的副业的文章 知乎 https zhuanlan
  • 合并两个无序数组java_Java实现把两个数组合并为一个的方法总结

    Java实现把两个数组合并为一个的方法总结 发布时间 2020 10 25 10 40 46 来源 脚本之家 阅读 76 作者 jaycee110905 本文实例讲述了Java实现把两个数组合并为一个的方法 分享给大家供大家参考 具体如下
  • 数据处理技巧(7):MATLAB 读取数字字符串混杂的文本文件txt中的数据

    MATLAB 读取数字字符串混杂的文本文件txt中的数据 目标 介绍 纯数字的情况 需要读取的文本文件 判断文件路径 matlab 读取数据的结果 代码块 文字开头 数字在后的情况 需要读取的文本文件 matlab 读取数据的结果 代码块
  • cmake--编译器设置

    前言 cmake支持多种不同方式设置编译器标志 1 使用 target compile definitions 设置编译器标志 2 使用CMAKE C FLAGS和CMAKE CXX FLAGS设置编译标志 一 目录结构 CMakeList
  • 复习C语言指针---函数指针

    复习C语言指针 函数指针 文章目录 复习C语言指针 函数指针 函数 函数指针 函数指针数组 回调函数 结束语 函数 一个函数表达式其实是不存在直接的 操作符的 操作符要求操作数是函数指指针 或者一些类类型 实际上 当用 f1 这样调用f1时
  • 华为服务器系统崩了怎么办,服务器崩溃重装系统

    服务器崩溃重装系统 内容精选 换一换 裸金属服务器操作系统无法正常启动 操作系统中毒 或裸金属服务器系统运行正常 但需要对系统进行优化 使其在最优状态下工作时 用户可以使用重装裸金属服务器的操作系统功能 重装操作系统是以原镜像进行系统重装
  • jackson 驼峰注解_springboot jackjson驼峰转下划线

    有如下几种方法 1 通过ObjectMapper设置 mapper setPropertyNamingStrategy com fasterxml jackson databind PropertyNamingStrategy SNAKE
  • C++ 模板

    模板是泛型编程的基础 泛型编程即以一种独立于任何特定类型的方式编写代码 模板是创建泛型类或函数的蓝图或公式 库容器 比如迭代器和算法 都是泛型编程的例子 它们都使用了模板的概念 每个容器都有一个单一的定义 比如 向量 我们可以定义许多不同类
  • springboot整合Redis时spring.redis.database参数不生效

    问题描述 配置配件中配置redis的database参数无论配置什么值时都是默认的0 网上查阅大量资料没有查到原因 解决 在网上找到了此网友的回答 虽然没有直接帮助我们解决问题 但给我提供了解决问题的思路 从这图阔以看出redis的data
  • PCL分割方法:区域生长分割算法(RegionGrowing)

    转载 有梦想的田园犬 https blog csdn net AmbitiousRuralDog article details 80267519
  • 数字信号处理基础----傅里叶级数

    1 傅里叶级数的余弦形式 1 1 正交的三角函数集 三角函数集 1 2 2 1 2 3 内的函数在区间 上彼此正交 也即 任意两个不同的函数的内积为0 函数和自身的内积不为零 因此 函数可以由该正交函数集唯一的表示 1 2 傅里叶级数的定义
  • vite+vue3打包部署问题

    最近使用vite vue3写了个小的demo 发现打包部署后页面出不来 如果是正常把包放在服务器的根目录中 项目页面是可以打开的 但是我要部署的是根目录dist包里面 外面多了一层文件夹 解决 vite config ts文件 base z
  • 横向手风琴效果

    html
  • 华硕a501lb5200加内存和固盘并装上win7系统并设置固盘为第一启动

    华硕a501lb5200加内存和固盘并装上win7系统并设置固盘为第一启动 最近入手一只华硕a501lb5200 然后某宝上买内存 固盘 接着拆机加内存和固盘并装上win7系统 于是想分享下自己的经验 大家多多补充 1 拆机加内存和固盘 内
  • Redis集群主从复制不生效的问题分析及解决

    一 集群信息 Redis版本 5 0 集群规模 三主三从 二 基本情况 在项目中为了达到高可用的目的 使用了Redis集群 搭建过程同Redis Cluster集群原理 三主三从交叉复制实战 故障切换 但是在实际使用中发现 集群方式比单点模
  • discuz未登录情况下首页tdk显示“首页”

    问题 discuz未登录状态下首页tdk与后台设置的不符 如图问题keywords和description变成了门户 也有部分变成了首页 解决办法 用编辑器打开 source class helper下的helper seo php文件 找
  • LeetCode#88. 合并两个有序数组(Python)

    题目 来源力扣 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2 另有两个整数 m 和 n 分别表示 nums1 和 nums2 中的元素数目 请你 合并 nums2 到 nums1 中 使合并后的数组同样按 非递减顺序
  • 很全的 Java 权限认证框架

    今天给大家推荐的这个开源项目超级棒 可能是史上功能最全的 Java 权限认证框架 这个开源项目就是 sa token Sa Token是什么 sa token是一个轻量级Java权限认证框架 主要解决 登录认证 权限认证 Session会话
  • FATFS:一个兼容windows的嵌入式文件系统API使用详解

    FATFS 一个兼容windows的嵌入式文件系统API使用详解 目录 FATFS 一个兼容windows的嵌入式文件系统API使用详解 1 API分类 2 常用API说明 2 1 挂载文件系统与解除挂载 2 2 文件操作 2 2 1 文件