Fatfs

STM32进阶笔记——FATFS文件系统(上)_stm32 fatfs-CSDN博客

STM32进阶笔记——FATFS文件系统(下)_stm32 文件系统怎样获取文件大小-CSDN博客

STM32——FATFS文件基础知识_stm32 fatfs-CSDN博客

021 - STM32学习笔记 - Fatfs文件系统(三) - 细化与总结_fatfs遍历文件-CSDN博客

希望这几篇文章不会莫名消失吧。

Fatfs


在嵌入式系统中,对于数据的存储和管理至关重要。STMicroelectronics的STM32系列微控制器提供了丰富的外设和功能,使得与外部存储设备(如SD卡)进行交互变得更加简单高效。


了解FatFs文件系统


FatFs是一款用于嵌入式系统的开源文件系统库,支持FAT12、FAT16、FAT32格式的文件系统。它提供了一套简单易用的API,能够方便地在嵌入式系统中实现对SD卡等存储设备的文件操作。


FATFS文件系统特点

  • 1、Windows兼容的FAT文件系统(支持FAT12、FAT16和FAT32)
  • 2、与平台无关,移植简单。全C语言编写
  • 3、代码量少、效率高
  • 4、多种配置选项
  • 1)支持多卷(物理驱动器或分区,最多10卷)
  • 2)多个AHSI/OEM代码页包括DBCS
  • 3)支持长文件名、ANSI/OEM或Unicode
  • 4)支持RTOS
  • 5)支持多种扇区大小
  • 6)只读、最小化的API和I/O缓冲区等

FATFS模块的层次结构图

1、底层接口,包括存储媒介读或写接口(disk I/O)和供给文件创建修改时间的实时时钟,需要我们根据平台和存储介质编写移植代码。

2、中间层FATFS模块,实现了FAT文件读或写协议。FATFS模块提供的是ff.c和ff.h。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。

3、最顶层是应用层,使用者无需理会FATFS的内部结构和复杂的FAT协议,只需要调用FATFS模块提供给用户的一系列应用接口函数,如f_open  f_read  f_write和f_close等,就可以像在PC上读/写文件那样简单



大部分的可以移植的小系统或者应用,都是采用类似这种将与底层打交道的源码开发给用户编写,然后提供顶层配置文件供配置

diakio.c和diskio.h是硬件层

ff.c和ff.h是FATFS的文件系统层和文件系统的API层。


FATFS移植步骤

FATFS模块在移植的时候,一般只需要修改2个文件,即ffconf.h和diskio.c。FATFS模块的所有配置项都是存放在ffconf.h里面,可以通过配置里面的一些选项来满足自己的要求。disk.c是硬件层,负责与底层硬件接口适配。

1、数据类型:在integer.h里面去定义好的数据类型。需要了解用的编译器的数据类型,并根据编译器定义好数据类型。

为支持简体中文长文件名称需要添加ff_convert和ff_wtoupper 函数,实际这两个已经在cc936.c 文件中实现,我们只要直接把cc936.c文件添加到工程中就可以。

2、配置:通过ffconf.h配置FTAFS的相关功能,以满足需要。

FatFs 文件系统与底层介质的驱动分离开来,对底层介质的操作都要交给用户去实现,它仅仅是 提供了一个函数接口而已。

表FatFs移植需要用户支持函数为FatFs移植时用户必须支持的函数。 通过表FatFs 移植需要用户支持函数我们可以清晰知道很多函数是在一定条件下才需要添加的, 只有前三个函数是必须添加的。我们完全可以根据实际需求选择实现用到的函数。

前三个函数是实现读文件最基本需求。接下来三个函数是实现创建文件、修改文件需要的。为实 现格式化功能,需要在disk_ioctl添加两个获取物理设备信息选项。我们一般只要实现前面六个 函数就可以了,已经足够满足大部分功能。


  disk_initalize函数


disk_status函数


disk_write函数


disk_ioctl函数


get_fattime函数


3、函数编写:打开diskio.c进行底层驱动编写,一般需要编写6个接口函数底层设备驱动函数是存放在diskio.c文件,我们的目的就是把diskio.c中的函数接口与SPIFlash芯 片驱动连接起来。总共有五个函数,分别为设备状态获取(disk_status)、设备初始化(disk_initialize)、 扇区读取(disk_read)、扇区写入(disk_write)、其他控制(disk_ioctl)。

4.  f fconf.h 文件是 FatFs 功能配置文件,我们可以对文件内容进行修改,使得FatFs更符合我们的要 求。

ffconf.h 对每个配置选项都做了详细的使用情况说明。下面只列出修改的配置,其他配置采 用默认即可。

  • 1) _USE_MKFS:格式化功能选择,为使用FatFs格式化功能,需要把它设置为1。
  • 2) _CODE_PAGE:语言功能选择,并要求把相关语言文件添加到工程宏。为支持简体中文文件名 需要使用“936”,正如在图添加FatFS文件到工程的操作,我们已经把cc936.c文件添加到工程 中。 3) _USE_LFN:长文件名支持,默认不支持长文件名,这里配置为2,支持长文件名,并指定使 用栈空间为缓冲区。
  • 4) _VOLUMES:指定物理设备数量,这里设置为2,包括预留SD卡和SPIFlash芯片。
  • 5) _MIN_SS 、_MAX_SS:指定扇区大小的最小值和最大值。SD卡扇区大小一般都为512字节, SPI Flash 芯片扇区大小一般设置为4096字节,所以需要把_MAX_SS改为4096。
  • 6)_USE_STRFUNC。这个用来设置是否支持字符串类操作,比如f_putc,f_puts等。

FATFS开放函数

f_mount-注册/注销一个工作区域(Work Area)

f_open-打开/创建一个文件  

f_close-关闭一个文件

f_read-读文件

f_write-写文件

f_Iseek-移动文件读/写指针

f_truncate-截断文件

f_sync-冲洗缓冲数据Flush Cached Data

f_forward-直接转移文件数据到一个数据流

f_stat-获取文件状态

f_opendir-打开一个目录

f_closedir-关闭一个已经打开的目录

f_readdir-读取目录条目

f_mkdir-创建一个目录

f_unlink-删除一个文件或目录

f_chmod-改变属性(Attribute)

f_utime-改变时间戳(Timestamp)

f_rename-重命名/移动一个文件或文件夹

f_chdir-改变当前目录

f_chdrive-改变当前驱动器

f_getcwd-获取当前工作目录

f_getfree-获取空闲簇Get Free Clusters

f_getlabel-Get volume label

f_setlabel-Set Volume label

f_mkfs-Divide a physical drive

f_gets-读取一个字符串

f_putc-写一个字符

f_puts-写一个字符串

f_printf-写一个格式化的字符串        f_printf函数是格式化写入函数,需要把ffconf.h文件中的                                                                    _USE_STRFUNC配置为1才支持。 f_printf函数用法类似C库                                                            函数printf函数,只是它将数据直接写入到文件中。

f_tell-获取当前读/写指针

f_eof-测试文件结束

f_size-获取文件大小

f_error-测试文件上的错误

程序细化

获取FLASH空间信息

static FRESULT miscellaneous(void)
{FATFS *fs;DWORD fre_clust,fre_sect,tot_sect;printf("\r\n--------------------获取设备信息--------------------\r\n");/* 获取卷3的设备信息 */res = f_getfree("3:",&fre_clust,&fs);if(res){printf("\r\n未获取到设备信息!\r\n");return res;}/* 计算得到的总的扇区个数和空扇区个数 */tot_sect = (fs->n_fatent -2) * fs->csize;fre_sect = fre_clust * fs->csize;/* 打印信息(4096字节/扇区) */printf("》设备总空间:%10lu KB。\n》可用空间::%10lu KB。\n",tot_sect*4 , fre_sect*4);return res;
}

文件定位操作

	printf("\r\n--------------------文件定位操作--------------------\r\n");res = f_open(&fp,"3:FatFs文件系统测试例程.txt",FA_OPEN_EXISTING | FA_READ );if(res == FR_OK){res = f_lseek(&fp,fp.fsize/2);					//使用文件结构体的成员属性fsize获取文件大小,将文件指针定位到文件内容的中间//res = f_lseek(&fp,f_size(&fp)/2);				//使用f_size()获取文件大小,将文件指针定位到文件内容的中间	printf("\r\n文件打开成功,准备读取数据!\r\n");res = f_read(&fp,&readBuffer,sizeof(readBuffer),&fnum);if(res==FR_OK){printf("》文件读取成功,读到字节数据:%d\r\n",fnum);printf("》读取得的文件数据为:\r\n%s \r\n", readBuffer);	}else{printf("!!文件读取失败:(%d)\n",res);}	f_close(&fp);        }else{printf("\r\n文件打开失败,失败代码 = %d\r\n",res);}

创建目录及重命名

printf("\r\n--------------------目录创建和重命名--------------------\r\n");
res = f_opendir(&dir,"3:Hello");
if(res != FR_OK)
{printf("\r\n不存在该目录,将创建新的Hello文件夹\r\n");res = f_mkdir("3:Hello");               //如果目录不存在,则创建目录
}
else
{printf("\r\n存在该目录,关闭目录并删除!\r\n");res = f_closedir(&dir);f_unlink("3:Hello/testdir.txt");
}
if(res == FR_OK)
{printf("\r\n将FatFs文件系统测试例程.txt复制到Hello下,并重命名为testdir.txt\r\n");res = f_rename("3:FatFs文件系统测试例程.txt","3:Hello/testdir.txt");
}
readFile(&fp,"3:Hello/testdir.txt");


文件/文件夹信息获取

static FRESULT file_check(const TCHAR *path)
{FILINFO fInfo;/* 获取文件信息 */res = f_stat(path,&fInfo);if(res == FR_OK){printf("“%s”文件信息:\n",path);printf("》文件大小:%ld(字节)\n",fInfo.fsize);printf("》时间戳:%u/%02u/%02u,%02u:%02u\n",(fInfo.fdate >> 9)+1980,fInfo.fdate >> 5&15,fInfo.fdate & 31,fInfo.ftime>>11,fInfo.ftime >>5 &63);printf("》属性:%c%c%c%c%c\n\n",(fInfo.fattrib & AM_DIR)?'D':'-',                //目录(fInfo.fattrib & AM_RDO)?'R':'-',                //只读文件(fInfo.fattrib & AM_HID)?'H':'-',                //隐藏文件(fInfo.fattrib & AM_SYS)?'S':'-',                //系统文件(fInfo.fattrib & AM_ARC)?'A':'-');               //档案文件}elsec{printf("\r\n文件打开失败,失败代码 = %d\r\n",res);}return res;
}
res = file_check("3:Hello/testdir.txt");

在主函数中调用函数


文件遍历

static FRESULT Scan_files(char *path)
{FRESULT res;FILINFO fInfo;DIR dir;int i;char *fn;  
#if _USE_LFN					//如果使用长文件名static char lfn[_MAX_LFN*2+1];fInfo.lfname = lfn;fInfo.lfsize = sizeof(lfn);
#endifres = f_opendir(&dir,path);				//打开目录if(res == FR_OK){i = strlen(path);for(;;){res = f_readdir(&dir,&fInfo);			 //读取目录下的内容,再读会自动读到下一个文件if(res != FR_OK||fInfo.fname[0] == 0)break;
#if _USE_LFN/*这里其实不用看的,我们之前已经启用长文件名了,但是需要注意的是,虽然启用了长文件名,当存储文件名不够13个字节时,文件系统仍然会将文件名存储到fname中,只有文件名超过13时,才会存储到lfname中*/fn = *fInfo.lfname ? fInfo.lfname:fInfo.fname;	
#elsefn = fInfo.name;
#endifif(*fn == '.')            //如果遇到点,则表示当前目录,跳过即可continue;if(fInfo.fattrib & AM_DIR)			//遇到目录时,递归调用{sprintf(&path[i],"/%s",fn);		//将获取到的文件名合成为完整文件名(即包含卷标和目录名的)res = Scan_files(path);                //递归遍历path[i] = 0;if(res != FR_OK) 				//如果打开失败,跳出循环break;}else{printf("%s/%s\r\n",path,fn);}}}return res;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/21793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

godot.bk4:how to make NPC roam and attack player with global variable‘s usage

1.为什么会有重力的影响:因为CharacterBody2D默认的代码是重力影响的,删掉即可 只需要添加 extends CharacterBody2Dconst SPEED 200.0 var directionfunc _physics_process(delta):direction Input.get_vector("ui_left", "ui_right&…

第一周:计算机网络概述(上)

一、计算机网络基本概念 1、计算机网络通信技术计算机技术 计算机网络就是一种特殊的通信网络,其特殊之处就在于它的信源和信宿就是计算机。 2、什么是计算机网络 在计算机网络中,我们把这些计算机统称为“主机”(上图中所有相连的电脑和服…

【Java】---- SpringBoot 统一数据返回格式

目录 1. 统一数据返回格式介绍2. 实际应用2.1 添加前后的返回结果区别2.2 存在问题 3. 统一数据返回格式的优点 1. 统一数据返回格式介绍 通过使用ControllerAdvice和引用ResponseBodyAdvice接口来进行实现。 ResponseBodyAdvice这个接口里面有两个方法,分别是: s…

【专利 超音速】基于分类模型的轻量级工业图像关键点检测方法

申请号CN202311601629.7公开号(公开)CN117710683A申请日2023.11.27申请人(公开)超音速人工智能科技股份有限公司发明人(公开)张俊峰(总); 杨培文(总); 沈俊羽; 张小村 摘要 本发明涉及一种基于分类模型的…

外星人Alienware m16R1 原厂Windows11系统 oem系统

装后恢复到您开箱的体验界面,包括所有原机所有驱动AWCC、Mydell、office、mcafee等所有预装软件。 最适合您电脑的系统,经厂家手调试最佳状态,性能与功耗直接拉满,体验最原汁原味的系统。 原厂系统下载网址:http://w…

VB.net实战(VSTO):Excel插件设计Ribbon界面

1. 新建Ribbon 1.1 开发环境 Visual Studio 2022 1.2 解决方案资源管理器中右击My Project 1.3 添加》新建项 1.4 office/SharePoint》功能区(可视化设计器),双击 2.调出工具箱 Visual Studio 2022》视图》工具箱 3.设计界面 3.1 添加功能区选项卡 3.2拖动Group…

深度强化学习+大模型综述Survey on Large Language Model-Enhanced Reinforcement Learning

论文地址:[2404.00282] Survey on Large Language Model-Enhanced Reinforcement Learning: Concept, Taxonomy, and Methods (arxiv.org) 摘要 对 LLM 增强 RL 中现有文献进行了全面的回顾,并总结了其与传统 RL 方法相比的特征,旨在阐明未…

混合A*算法详解(一)路径搜索

描述 为了学习一下混合A*算法,我前面介绍了车辆运动学及非完整约束、差速轮及阿克曼运动学模型、Dubins曲线和RS曲线,现在终于可以看一下混合A*算法的相关内容了。 原文名称:Practical Search Techniques in Path Planning for Autonomous D…

Mac解决command not found:mvn 保姆级

1.背景 mac电脑已经安装了jdk1.8。如果不清楚自己jdk安装位置的可以到idea查看。但是命令行执行 mvn 会报 command not found 2.解决方案 默认安装的 jdk 是没有配置环境变量,因此需要手动配置 通常如果是默认安装则路径都会一样直接复制即可,只需更…

驱动开发之设备树语法

0.设备树由来 通过前面platform实验,使用platform总线,device与driver需要匹配才可以,device主要是存储一些硬件信息的,传递给driver使用。这样就会导致大量的硬件信息在linux内核源码里面,arch/arm/mach-xxx 和 arch…

undefined symbol: _ZN3c104impl8GPUTrace13gpu mmcv

这里写自定义目录标题 ImportError: //python3.8/site-packages/mmcv/_ext.cpython-38-x86_64-linux-gnu.so: undefined symbol: _ZN3c104impl8GPUTrace13gpuTraceStateEERROR conda.cli.main_run:execute(49): 这样的问题往往都是版本不匹配导致的 pytorch的版本,m…

【C++】类和对象1.0

本鼠浅浅介绍一些C类和对象的知识,希望能得到读者老爷们的垂阅! 目录 1.面向过程和面向对象 2.类的引入 3.类的定义 4.类的访问限定符及封装 4.1.类的访问限定符 4.2.封装 5.C中struct和class的区别 6.类域 7.类的实例化 8.类对象模型 8.1.类…

线性代数|机器学习-P5特征值和特征向量

文章目录 1. 特征值和特征向量1.1 特征向量1.2 向量分解 2. 矩阵相似2.1 特征值求解法-相似2.2 特殊特征值2.3 反对称矩阵 3.对称矩阵 1. 特征值和特征向量 1.1 特征向量 假设有一个n行n列的方阵A,有 n 个不相同的特征值为 λ \lambda λ,特征向量为 x 1 , x 2 , …

(2022,扩散模型,评分函数,数据流形的内在维度,SVD)使用扩散模型估计数据流形的维度

Your diffusion model secretly knows the dimension of the data manifold 公和众和号:EDPJ(进 Q 交流群:922230617 或加 VX:CV_EDPJ 进 V 交流群) 目录 0. 摘要 1. 引言 2. 相关工作 3. 背景:基于评…

【YOLOv5/v7改进系列】引入Slimneck-GSConv

一、导言 GSConv旨在平衡模型的准确度与速度,针对自动驾驶车辆中目标检测任务设计。从类脑研究中得到的直观理解是,具有更多神经元的模型能够获得更强的非线性表达能力。但是,不容忽视的是生物大脑处理信息的强大能力和低能耗远远超过计算机…

二、Nginx目录结构与基本运行原理

目录 一、目录结构 二、运行原理 一、目录结构 我们使用tree 命令查看nginx的目录。如果tree 命令失效,需要安装tree工具 [rootlocalhost local]# yum install -y tree[rootlocalhost /]# tree /usr/local/nginx /usr/local/nginx ├── client_body_temp # PO…

C语言 | Leetcode C语言题解之第129题求根节点到叶节点数字之和

题目: 题解: int sumNumbers(struct TreeNode* root) {if (root NULL) {return 0;}int sum 0;struct TreeNode* nodeQueue[2000];int numQueue[2000];int leftQueue 0, rightQueue 0;nodeQueue[rightQueue] root;numQueue[rightQueue] root->v…

Vue——初识组件

文章目录 前言页面的构成何为组件编写组件组件嵌套注册 效果展示 前言 在官方文档中,对组件的知识点做了一个很全面的说明。本篇博客主要写一个自己的案例讲解。 vue 官方文档 组件基础 页面的构成 说到组件之前,先大致说明下vue中页面的构成要素。 在…

手写数据集minist基于pytorch分类学习

1.Mnist数据集介绍 1.1 基本介绍 Mnist数据集可以算是学习深度学习最常用到的了。这个数据集包含70000张手写数字图片,分别是60000张训练图片和10000张测试图片,训练集由来自250个不同人手写的数字构成,一般来自高中生,一半来自工…

MTU相关随笔

一、MTU的概念 MTU(最大传输单元):用来通知对方所能接受数据服务单元的最大尺寸,说明发送方能够接受的有效载荷大小。MTU是包或帧的最大长度,一般以字节记,如果过大在碰到路由器时会被拒绝转发&#xff0c…