021 - STM32学习笔记 - Fatfs文件系统(三) - 细化与总结

news2024/10/6 6:00:28

021 - STM32学习笔记 - Fatfs文件系统(三) - 细化与总结

上节内容中,初步实现了FatFs文件系统的移植,并且实现了设备的挂载、文件打开/关闭与读写功能,这里对上节遗留的一些问题进行总结,并且继续完善文件系统的一些操作。

一、问题汇总

1、文件名过长

上节例程中,文件名为3:1.txt,文件打开、读写都没有问题,后来更改了一下文件名为3:TestDomefile.txt后,文件不能正常打开。

在这里插入图片描述

这里需要在ffconf.h中将长文件名支持设置为1

#define	_USE_LFN	1					//0:默认设置,不支持长文件名;1:支持长文件名,最长可支持到255个字符。
#define	_MAX_LFN	255

关于长文件名设置,可选的设置参数有0-3四种模式

模式说明
0默认模式,不支持长文件名
1模式1,支持长文件名,工作空间存储在BSS(段)中
2模式2,支持长文件名,工作空间存储在栈中
3模式3,支持长文件名,工作空间存储在堆中

这里设置完成后,编译会报如下错误:

.\Objects\YH-429.axf: Error: L6218E: Undefined symbol ff_convert (referred from ff.o).
.\Objects\YH-429.axf: Error: L6218E: Undefined symbol ff_wtoupper (referred from ff.o).

启用长文件支持后,会包含一些操作,这些函数是定义在ccsbsc.c中,这里只需要将ccsbsc.c文件加入工程中即可。

2、无FAT文件系统

当挂载文件系统的时候,可能会出现f_mount之后返回FR_NO_FILESYSTEM(13)的情况,这种大概率是FLASH没有格式话造成的,当出现这个情况的时候,就需要堆FLASH进行格式化。具体操作如下:

res = f_mount(&flash_fs,"3:",1);				//挂载FLASH,卷标为3,立即挂载
if(res == FR_NO_FILESYSTEM)						//若返回值为无FAT文件系统,则进行格式化
    {
        res = f_mkfs("3:",0,0);					//执行格式化操作,卷标为3,分区规则为0:FDISK,分配单元大小默认为0
        printf("\r\n磁盘正在格式化中,请稍等.....\r\n");
        if(res == FR_OK)
        {
            printf("\r\n磁盘格式化完成...\r\n");
            f_mount(NULL,"3:",1);					//格式化后需要先卸载设备
        	res = f_mount(&flash_fs,"3:",1);		 //再重新挂载设备
        }
        else
        {
            printf("\r\n%d磁盘格式化失败,请尝试复位操作!\r\n",res);
        }
    }

这里需要注意的是,当使用f_mkfs格式化FLASH时,需要再fconf.h中先将_USE_MKFS使能:

#define	_USE_MKFS		1       /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */

这里需要注意三点:

a、之前我已经将FLASH设置为FAT格式,所以测试的时候我将判断是否为是否为FAT文件系统的条件注释掉了,所以每次执行程序都是默认格式化;

b、格式化会将整个芯片全部格式化掉,这里需要注意;

c、格式化完成后,需要先将磁盘卸载,然后重新挂载。

在这里插入图片描述

3、文件名中文支持

以上的例程中,我们都是以非中文字符来命名文件,但是后面如果使用中文来命名文件,那可能会出现乱码的情况,例如我们将之前的文件名改为3:FatFs文件系统测试例程.txt后,用野火提供的外部FLASH模仿U盘例程来看一下创建的文件,会发现是乱码。

在这里插入图片描述

遇到这种情况,我们需要将原来工程文件中的ccsbsc.c文件去掉,将cc936.c文件加入到工程中,并在fconf.h中将_CODE_PAGE更改为936即可。

#define _CODE_PAGE	936

在这里插入图片描述

后面如果需要支持繁体中文或者日文等的,可以根据下面的注释去选择编码页,并将对应的编码页加入到工程中即可。

/* This option specifies the OEM code page to be used on the target system.
/  Incorrect setting of the code page can cause a file open failure.
/
/   1   - ASCII (No extended character. Non-LFN cfg. only)
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
*/

二、程序细化

类似于Windows 系统一样,当我们在磁盘上右键属性时,可以看到该磁盘的一些数据信息,这里用FatFs文件系统也可以对FLASH进行这些操作,例如:

1、获取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;
}
2、文件定位操作
	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);
    }
3、创建目录及重命名
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");

在这里插入图片描述

4、文件/文件夹信息获取
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;
}

main中调用:

res = file_check("3:Hello/testdir.txt");

在这里插入图片描述

在这里关于时间戳说明一下,因为之前get_fattime函数我们用了一个空函数来骗过编译器,所以这里读出来的时间实际上是有问题的,等到后面有时间系统了,这个就可以实现了。

5、文件遍历
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);
#endif
    res = 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;	
#else
            fn = fInfo.name;
#endif
            if(*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;
}

在这里插入图片描述

OK,关于FatFs文件系统的内容就学习到这里,其实里面还有很多内容这里没有提到,有兴趣的可以去官网学习一下。

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

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

相关文章

经纬恒润推出整车E/E全链路测试实验室解决方案

仿真测试作为“V流程”右半部分最重要的组成部分,是汽车电子电气测试不可或缺的技术手段。随着各种各样的测试设备进场,如何高效地统筹规划仿真测试实验室,成为了各车企关心的问题。 仿真测试实验室不仅能够服务于汽车电子零部件的仿真测试&…

Robot Framweork之UI自动化测试---元素定位的4种方式

在Robot Framweork的UI自动化测试中,元素定位主要有四种,即通过id,name,xpath和CSS定位。 一、id定位 id就好比一个人身份证,元素在 HTML 页面中的唯一标识符,因此 ID 定位方式是最常用的方式之一&#xf…

WMI 介绍

1.什么是WMI WMI的全称是Windows Management Instrumentation,即WIndows管理规范。它允许通过一个公共接口访问多种操作系统的构成单元,实现对操作系统的信息获取及管理操作。 Windows提供了一个WMI测试器,使得查询这些内容变得尤为方便。按下"winR&q…

安装nvm之后,node -v 提示‘node‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件

1. 检查有没有执行这个命令:nvm use [nodejs version name] 2. 检查nvm安装位置同级,有没有nodejs文件夹,是一个快捷键!如果有一个其他的nodejs,把它删掉,然后到cmd中,重新nvm install一下&…

Centos7 上安装 redis-dump 和redis-load 命令

一、安装rvm 1、安装GPG keys gpg2 --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDBcurl -sSL http://rvm.io/mpapis.asc | gpg2 --import - curl -sSL http://rvm.io/pkuczynski.asc | g…

SQL-多表

create table course (id int auto_increment primary key comment 主键id,name varchar(10) comment 课程名字 ); insert into course (name) values (java),(linux),(SQL);create table course_student (id int auto_increment primary key comment 主键id,studentid int not…

低代码开发平台源码:基于模型驱动,内置功能强大的建模引擎,零代码也能快速创建智能化、移动化的企业应用程序

管理后台低代码PaaS平台是一款基于 Salesforce Platform 的开源替代方案,旨在为企业提供高效、灵活、易于使用的低代码开发平台。低代码PaaS平台的10大核心引擎功能:1.建模引擎 2.移动引擎 3.流程引擎 4.页面引擎 5.报表引擎 6.安全引擎 7.API引擎 8.应用集成引擎 9…

MySQL执行一条select语句,执行过程怎么样

执行一条select语句,执行过程怎么样 连接器 与客户端进行 TCP 三次握手建立连接;MySQL基于TCP协议进行传输的校验客户端的用户名和密码,如果用户名或密码不对,则会报错如果用户名和密码都对了,会读取该用户的权限&…

湖南省物业满意度研究(群狼调研)

01 行业现状 随着湖南省物业行业的蓬勃发展,物业管理走向规范化的道路。近年来,湖南省物业管理行业迎来飞速发展的黄金时期,全省物业服务相关企业已超过9万家,其中长沙市占据了四成以上。 数据来源:天眼查公开数据 在…

直播丨如何用最新的 Serverless 技术让文化古籍“活过来”?

当前,古籍数字化面临技术难度高、资金缺口大、人才紧张等难点。云计算和人工智能技术可以高效实现古籍产品化、可视化、平台化,不仅使其保存形式迈上一个新台阶,还可以有效降低用户阅读门槛。 本次 Serverless 圆桌派 特别邀请上海慧游文化 …

TCGA数据批量运行Coxph函数

df数据框形如&#xff1a; djs.coxph <- function(df,genelist){library(survival)library(survminer)dir.create("./survival")setwd("./survival")# 准备好的生存分析数据框&#xff0c;变量中包括OS.time,OS以及values of gene expression df <…

论文阅读 - Few-shot Network Anomaly Detection via Cross-network Meta-learning

论文链接&#xff1a;https://arxiv.org/pdf/2102.11165.pdf 目录 摘要&#xff1a; 引言 问题定义 方法 Graph Deviation Networks Cross-network Meta-learning 摘要&#xff1a; 网络异常检测旨在找到与绝大多数行为显着不同的网络元素&#xff08;例如节点、边、子图…

河北沃克仓储解决方案最新布局|HEGERLS四向穿梭车在高标仓和楼层仓中的应用

河北沃克金属制品有限公司是业内十分稀缺可提供整体物流仓储解决方案并落地的企业&#xff0c;既拥有自主研发和生产等一整套核心软硬件的能力&#xff0c;又具备丰富的整体方案规划与实施经验。经过多年积累和开拓&#xff0c;河北沃克金属制品有限公司业务已拓展覆盖近众多行…

如何列出phpMyAdmin左侧菜单中的所有表格 - 不分页 - 显示数据库所有的表

效果图 原来 优化后 步骤 点击logo&#xff0c;回到首页 点击设置 》 导航面板 》 导航树 》 节点中最大项数 》 应用 ok

Windows下RocketMQ的启动

下载地址&#xff1a;下载 | RocketMQ 解压后 一、修改runbroker.cmd 修改 bin目录下的runbroker.cmd set "JAVA_OPT%JAVA_OPT% -server -Xms2g -Xmx2g" set "JAVA_OPT%JAVA_OPT% -XX:MaxDirectMemorySize15g" set "JAVA_OPT%JAVA_OPT% -cp %CLASSP…

jmeter之接口测试(http接口测试)

基础知识储备 一、了解jmeter接口测试请求接口的原理 客户端--发送一个请求动作--服务器响应--返回客户端 客户端--发送一个请求动作--jmeter代理服务器---服务器--jmeter代理服务器--服务器 二、了解基础接口知识&#xff1a; 1、什么是接口&#xff1a;前端与后台之间的…

MySQL 的 Join 查询及 Hash Join 优化 | StoneDB 技术分享会 #3

StoneDB开源地址 https://github.com/stoneatom/stonedb 设计&#xff1a;小艾 审核&#xff1a;丁奇、宇亭 编辑&#xff1a;宇亭 作者一&#xff1a;徐鑫强&#xff08;花名&#xff1a;无花果&#xff09; 电子科技大学-计算机技术-在读硕士、StoneDB 内核研发实习生 作…

BES 平台 SDK之代码架构讲解二

本文章是基于BES2700 芯片&#xff0c;其他BESxxx 芯片可做参考&#xff0c;如有不当之处&#xff0c;欢迎评论区留言指出。 BES 平台 SDK之代码架构讲解一_谢文浩的博客-CSDN博客 上篇文章粗略的对整个SDK 目录下的文件进行了说明&#xff0c;接下来会对SDK 比较详细的介绍。…

C语言实用调试详解

目录 什么是bug? 调试是什么?有多重要? 调试是什么? 调试的基本步骤 Debug和Release的介绍 Windows环境调试介绍 调试环境的准备 学会快捷键 调试的时候查看程序当前信息 查看临时变量的值 查看内存信息 查看调用堆栈 查看汇编信息 查看寄存器信息 一些调试…

HCIP 重发布+路由策略总结

重发布 在同一个网络拓结构中&#xff0c;如果存在多种不同的路由协议&#xff0c;由于不同路由协议的机制各有不同&#xff0c;对路由的处理也不相同&#xff0c;这就在网络中造成了路由信息的隔离&#xff0c;在路由器的边界路由器上&#xff0c;将某种路由协议的路由信息引…