本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在嵌入式系统中,文件系统的应用至关重要,尤其是在存储设备如SD卡的使用中。本项目专注于STM32微控制器上的FATFS文件系统实现,这是一种资源受限的嵌入式系统中广泛使用的轻量级文件系统。项目提供了FATFS库,支持多种FAT格式,并介绍了如何在STM32上与SD卡进行交互,实现文件的读写操作。FATFS库提供了丰富的文件操作函数,而SD卡驱动负责与STM32的通信,完成数据传输。本项目旨在通过实例程序,展示如何利用这些工具和库函数来实现文件的创建、打开、读取、写入和关闭等操作。
SD卡上文件系统FatFs的参考程序_FatFS读写程序_STM32SD卡FATFS_fatfs_

1. FATFS文件系统简介

1.1 FATFS文件系统概述

FATFS是一个通用的文件系统模块,它是针对小型嵌入式系统设计的,旨在提供一个简单的文件操作接口。它允许在多种类型的存储介质上进行文件操作,比如闪存卡、USB存储设备以及其它基于块的设备。FATFS是由ChaN开发,采用ANSI C语言编写,能够轻松地嵌入到微控制器上运行。

1.2 FATFS与其它文件系统的比较

与其他文件系统如EXT2/3/4、F2FS等相比,FATFS的主要优势在于它广泛被各种操作系统所支持,而且由于其简单性,FATFS在资源受限的嵌入式系统中拥有较小的运行开销。FATFS提供了标准的文件操作API,使得开发人员可以容易地实现文件的读写、创建和删除等操作。

1.3 FATFS在项目中的应用

在嵌入式项目的文件管理需求中,FATFS通常是第一选择,尤其在对存储介质大小和处理能力有限制的情况下。无论是将日志数据记录到存储介质,还是读取存储器中的配置文件,FATFS都能够提供一个高效而简单的解决方案。在下一章节中,我们将探讨FATFS如何与STM32微控制器协同工作,以实现更高级的文件管理功能。

2. STM32微控制器特性

2.1 STM32架构与性能概述

2.1.1 微控制器的内部结构

STM32微控制器是基于ARM Cortex-M系列处理器构建的32位高性能MCU,广泛应用于工业控制、医疗设备、消费电子产品等领域。其内部结构可以细分为几个主要模块:

  • CPU核心 :采用ARM Cortex-M内核,其中M0/M0+内核适用于低功耗和低成本应用;M3/M4/M7内核则提供更高的性能,适合复杂的控制算法和数据处理。
  • 存储器 :集成了闪存(Flash)和SRAM,以存储程序代码和运行时数据。
  • 外设接口 :提供多种外设接口,如USART、I2C、SPI、CAN、USB等,用于连接各种外部设备。
  • 时钟系统 :具备灵活的时钟管理单元,可以配置系统时钟以优化性能和功耗。
  • 中断系统 :支持多种中断源,包括外部中断、内部中断等,以及具有低延迟的中断处理能力。

2.1.2 STM32系列的特点与优势

STM32微控制器系列的特点和优势可从以下几个方面进行阐述:

  • 高性能与低功耗 :STM32系列在保持高性能的同时,通过多种省电模式和优化的内核设计,实现了优秀的功耗性能。
  • 丰富的外设选择 :提供了大量内置的外设接口,简化了硬件设计复杂度,并降低了总体成本。
  • 安全特性 :集成安全特性,如硬件加密、读写保护、存储器保护单元(MPU),确保了系统安全性。
  • 开发工具和生态系统 :拥有完善的软件开发工具链和生态系统支持,包括STM32CubeMX配置工具、HAL库、LL库,以及广泛的第三方支持。

2.2 STM32开发环境搭建

2.2.1 开发板和调试工具选择

选择适合的开发板和调试工具是开始STM32项目的第一步。在众多开发板中,ST官方提供的Nucleo系列板和Discovery系列板都是不错的选择,它们都带有ST-LINK调试器,可以快速进行开发和调试。

  • Nucleo开发板 :提供了多种引脚兼容的板型,并支持扩展功能板(如Arduino和ST Morpho扩展板)。它们通常配备了一个高性能的MCU,支持丰富的接口。
  • Discovery开发板 :主要针对入门级用户和学生,功能较为齐全,价格适中。它们提供了全面的示例代码和应用程序,对于快速原型开发有很大帮助。

2.2.2 软件开发环境的配置

在开发环境中,Keil MDK-ARM、IAR Embedded Workbench、STM32CubeIDE等是常用的IDE工具。这里以STM32CubeIDE为例介绍环境搭建步骤:

  1. 下载并安装STM32CubeIDE。
  2. 打开STM32CubeIDE,创建一个新项目或导入现有项目。
  3. 选择目标设备型号。STM32CubeIDE通常会自动检测连接的开发板,并列出可用的MCU型号。
  4. 配置项目属性,包括编译器优化级别、堆栈大小、调试器设置等。
  5. 编写或导入源代码,编译并下载到目标开发板进行调试。

在本章中,我们详细介绍了STM32微控制器的架构和性能特点,以及开发环境的搭建步骤。这些基础知识为后续章节中FATFS文件系统与STM32的集成和操作打下了坚实的基础。通过了解STM32的内部结构、特点与优势,以及开发环境的配置,我们可以更加高效地进行微控制器应用的开发工作。在下一章节中,我们将深入探讨FATFS库的功能特性,以及如何将文件系统集成到STM32项目中。

3. FATFS库功能介绍

3.1 FATFS库的基本构成

3.1.1 核心模块与功能概述

FATFS是一个通用的 FAT 文件系统模块,用于小型嵌入式系统。它提供了操作 FAT 文件系统的基本功能,包括但不限于文件的读写、创建、删除、目录管理等。FATFS库被设计为与 FFF ( FAT Filesystem Fore Fographers ) 兼容,而 FFF 是一个更抽象的文件系统接口。FATFS库是用 C 语言编写的,它可以作为源代码形式集成到任何使用标准 C 编译器的项目中。

FATFS的核心模块主要包括以下几个部分:
- FAT file access layer :文件访问层,它负责访问底层存储介质,处理与文件系统相关的数据存储和检索。
- File system layer :文件系统层,负责逻辑上的文件操作,如创建、删除、重命名等。
- Upper file access layer :上层文件访问层,提供给应用层调用的接口,如 f_open, f_read, f_write 等。

3.1.2 FATFS库的API接口

FATFS库提供了丰富且直观的API接口,以方便用户进行文件操作。以下是一些核心API的简介:

  • f_mount :挂载文件系统。
  • f_unmount :卸载文件系统。
  • f_open :打开文件。
  • f_read :读取文件。
  • f_write :写入文件。
  • f_lseek :改变文件指针位置。
  • f_close :关闭文件。
  • f_opendir :打开目录。
  • f_readdir :读取目录项。
  • f_mkdir :创建目录。
  • f_unlink :删除文件。
  • f_chmod :修改文件属性。

每个API都有其特定的参数和返回值。例如, f_open 函数用于打开文件,它接受文件名和模式作为参数,并返回一个指向文件对象的指针。在设计时,这些API都遵循了简明易用的原则,使得即使是嵌入式系统中的开发者也能够轻松地操作文件系统。

3.2 FATFS库与文件系统的关联

3.2.1 文件系统接口的设计原理

在与文件系统交互时,FATFS库作为应用程序和存储介质之间的桥梁。它需要处理操作系统级的复杂性,提供一个简单的API层给应用程序。设计原理基于以下几点:

  • 抽象层 :FATFS通过提供抽象层来隐藏不同存储介质之间的差异,使得文件操作不受具体存储硬件的限制。
  • 兼容性 :通过统一的接口和操作,FATFS确保了与不同版本的FAT文件系统兼容。
  • 模块化 :FATFS的各个组件被设计成模块化,以支持仅包含所需功能的精简版本。
  • 错误处理 :FATFS提供了一套完整的错误处理机制,以确保在操作文件系统时能够准确地识别和处理各种异常情况。

3.2.2 FATFS库与文件系统兼容性分析

FATFS库针对不同的FAT变种(如FAT12、FAT16、FAT32)以及兼容性都有细致的处理。以下是与文件系统兼容性相关的几个重点:

  • FAT类型识别 :FATFS能够自动识别存储介质上的FAT类型,并选择合适的操作模式。
  • 文件系统更新 :为了与不断发展的文件系统格式保持同步,FATFS库持续更新以支持新的FAT特性。
  • 磁盘维护 :FATFS库能够在文件系统层面执行诸如检查和修复等维护任务。

FATFS库支持的设备类型包括固定磁盘和可移动磁盘。对于后者,FATFS库还提供了对多种分区表格式的支持,如MBR(Master Boot Record)和GPT(GUID Partition Table)。通过这些设计,FATFS库能够确保与广泛存在的文件系统以及新出现的技术之间维持良好的兼容性。

在实际应用中,开发者可以利用FATFS库所提供的丰富的API接口和良好的兼容性,实现对FAT文件系统的高效和稳定操作。

3.2.3 代码示例与逻辑分析

下面是一个使用FATFS库进行文件写入操作的代码示例,之后将对代码逻辑进行详细分析:

FIL file;               // 定义一个文件对象
FRESULT fresult;        // 定义FRESULT枚举类型变量,用于存储API函数执行结果
UINT bw;                // 定义UINT类型变量,用于存储写入的字节数
char wtext[] = "This is FATFS test.\r\n";  // 要写入的文本字符串

fresult = f_open(&file, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);  // 打开或创建文件用于写入

if (fresult == FR_OK) {   // 检查文件是否成功打开
    fresult = f_write(&file, wtext, sizeof(wtext), &bw);  // 写入文本到文件

    if (bw > 0) {     // 检查是否成功写入
        // 写入成功
    } else {
        // 写入失败,bw值为实际写入字节数
    }
    f_close(&file);   // 关闭文件
}
  • f_open 函数用于打开或创建一个名为 “test.txt” 的文件,如果文件不存在则创建,如果文件已存在则覆盖。 FA_CREATE_ALWAYS 表示无论文件是否存在,都创建文件。 FA_WRITE 表示打开文件用于写入。
  • f_write 函数将字符串 wtext 写入文件。它返回成功写入的字节数,存储在变量 bw 中。
  • f_close 函数用于关闭打开的文件。

在整个过程中,通过检查 fresult 变量的值可以了解操作是否成功。如果文件操作失败,则可以通过 fresult 的值来判断是哪种错误,以便进行相应的错误处理。

4. SD卡驱动与STM32通信

4.1 SD卡通信协议解析

4.1.1 SD卡的物理和数据接口

SD卡(Secure Digital Card)是一种广泛应用于嵌入式系统的非易失性存储媒体。物理上,SD卡使用一个小型闪存卡,遵循一系列的物理规范和电气特性。它的设计允许高速数据传输和良好的兼容性。

SD卡的物理接口设计包括以下几个关键部分:

  • 金属接触点 :SD卡的底部是一排的金属接触点,共9个金属点,用于连接SD卡和读卡器或微控制器。主要的信号包括电源、地线、数据线以及控制线。
  • 数据线 :SD卡支持多种数据传输模式,包括单数据速率(SDR)和双数据速率(DDR)。数据通过DAT0至DAT3的四条数据线进行传输。
  • 命令和响应线 :CMD线用于发送命令和接收响应。
  • 时钟线 :CLK线用于提供同步时钟信号。

4.1.2 SD卡通信协议的层次结构

SD卡通信协议的层次结构由以下部分组成:

  • 物理层 :负责定义信号的电气特性,包括电压水平和传输速率。
  • 传输层 :定义了数据包的格式、数据传输的时序以及命令和响应的结构。
  • 文件系统层 :文件系统层则管理存储在SD卡上的数据,比如FAT文件系统。

在物理层,SD卡支持不同的速度等级和总线模式(比如1位模式、4位模式)。在传输层,数据包遵循特定的协议,数据包由5字节的头部,数据字段和校验尾部组成。命令和响应则以特定的格式和编码进行传输。

4.2 STM32与SD卡的硬件连接

4.2.1 硬件接口的配置方法

在将STM32与SD卡连接时,首先要配置STM32的引脚以匹配SD卡的引脚功能。STM32拥有灵活的GPIO(通用输入输出)引脚,可以通过软件来设置每个引脚的模式,例如推挽输出、开漏输出、模拟输入、浮空输入等。

典型的SD卡接口配置包括以下步骤:

  1. 时钟配置 :为SD卡提供同步时钟信号(CLK)。
  2. 数据线配置 :配置四个数据线(DAT0-DAT3)。
  3. 命令线配置 :CMD线用以发送命令和接收SD卡响应。
  4. 电源和地线连接 :确保SD卡获得正确的电源供应和接地。

STM32提供了一个高性能的SDIO(Secure Digital Input Output)接口,这个接口专门用于与SD卡通信。当使用SDIO接口时,数据和命令传输通过专用的硬件逻辑来处理,这大大降低了软件开销。

4.2.2 STM32的SDIO接口介绍

STM32的SDIO接口能够直接与SD卡进行通信,支持SDIO模式和SPI模式。SDIO模式下,STM32通过SDIO接口提供了一组专用的硬件资源,包括一组寄存器用于实现SDIO协议的所有操作。

SDIO模式的工作原理如下:

  1. 初始化 :STM32初始化SDIO接口,设置适当的时钟速率和通信参数。
  2. 命令传输 :通过CMD线发送SD卡命令。
  3. 数据传输 :通过DAT0至DAT3线进行数据传输。
  4. 状态监测 :通过SDIO接口的状态寄存器来监控SD卡的响应。

使用SDIO接口的优点在于它提供了高速的数据吞吐率和低的CPU负载,这对于要求高效率和实时性能的嵌入式应用来说是非常重要的。

4.3 STM32与SD卡通信的软件实现

4.3.1 驱动程序的初始化和配置

在软件层面,初始化STM32与SD卡的通信需要进行一系列的步骤,包括硬件资源的配置和SD卡的识别与初始化。

初始化流程通常包括以下步骤:

  1. 时钟和GPIO初始化 :设置SDIO时钟和GPIO引脚。
  2. SDIO初始化 :配置SDIO接口的相关参数,如时钟频率、数据宽度和总线模式。
  3. SD卡检测和识别 :通过发送特定的SD卡命令,检查SD卡是否连接并且可被识别。
  4. 初始化命令序列 :执行一系列的命令来将SD卡置于正确的操作模式。

配置完成后,STM32就可以开始向SD卡发送命令和数据。

4.3.2 数据传输和状态监控的实现

一旦驱动程序初始化完成,数据传输就可以开始了。数据传输涉及到的数据包包括命令、响应和实际的数据包。

数据传输流程:

  1. 命令发送 :STM32通过CMD线发送命令给SD卡,每个命令都有一个唯一的命令响应。
  2. 数据传输 :SD卡根据接收到的命令执行读或写操作。
  3. 状态监控 :STM32需要监控SD卡的状态,包括检查数据传输是否完成,是否有错误发生。

STM32的SDIO驱动程序通常会提供API函数来处理这些操作。典型的API函数包括sdio_read_blocks(), sdio_write_blocks(), sdio_get_status()等。通过这些API函数,开发者可以轻松实现复杂的SD卡数据读写操作和状态管理。

在代码层面上,开发者需要编写具体的函数调用逻辑,包括设置正确的命令参数、处理数据缓存以及错误处理机制。这些功能的实现能够确保数据准确无误地在STM32和SD卡之间传输。

/* 代码块示例:STM32初始化SDIO接口和发送SD卡读取数据的命令 */
void SDIO_Init(void) {
    /* 初始化SDIO硬件接口 */
    /* 设置SDIO时钟频率、命令和数据线的参数 */
}

int SD_ReadData(uint32_t start_block, uint16_t block_size, uint8_t* buffer, uint32_t num_blocks) {
    /* 发送读取命令给SD卡 */
    /* 等待数据传输完成 */
    /* 读取数据到buffer */
    /* 检查并处理任何可能的错误 */
    return 0; // 返回成功或错误代码
}

通过这些初始化和数据传输步骤,STM32可以高效地与SD卡进行通信,从而实现数据的存储和读取。

以上内容为第四章:SD卡驱动与STM32通信的详细介绍。本章节中,我们首先解析了SD卡的通信协议,然后介绍了STM32与SD卡的硬件连接方法,并且深入讨论了软件层面上如何实现与SD卡的数据传输和状态监控。这些内容旨在帮助读者理解和掌握STM32与SD卡之间的通信机制,为进一步开发嵌入式系统中的数据存储功能打下坚实的基础。

5. 文件操作示例代码

在这一章节中,我们将深入探讨如何使用FATFS库在STM32微控制器上执行基本的文件操作。示例代码将为用户提供实际操作的参考,并将详细分析关键点以帮助理解如何利用FATFS进行文件的创建、读取、写入和删除。

5.1 文件创建和读取操作示例

5.1.1 示例代码详解

首先,我们将探讨如何使用FATFS库在STM32上创建和读取文件。以下是创建和读取文件的示例代码:

#include "ff.h"     /* 引入FATFS库核心头文件 */
#include "diskio.h" /* 引入底层I/O接口头文件 */

FATFS fs;           /* 文件系统对象 */
FIL fil;            /* 文件对象 */
FRESULT fr;         /* 文件操作结果状态 */
UINT bw;            /* 写入字节数 */
char wtext[] = "This is a test text.\r\n"; /* 测试写入文本 */
char rtext[100];     /* 读取文本缓冲区 */

/* 挂载文件系统 */
fr = f_mount(&fs, "", 0);
if (fr != FR_OK) {
    /* 错误处理 */
}

/* 创建文件 */
fr = f_open(&fil, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);
if (fr == FR_OK) {
    /* 写入文本 */
    fr = f_write(&fil, wtext, sizeof(wtext), &bw);
    /* 关闭文件 */
    f_close(&fil);
}

/* 重新打开文件进行读取 */
fr = f_open(&fil, "test.txt", FA_READ);
if (fr == FR_OK) {
    /* 读取文本 */
    fr = f_read(&fil, rtext, sizeof(rtext), &bw);
    /* 关闭文件 */
    f_close(&fil);
}

5.1.2 代码中关键点分析

文件系统挂载

在文件操作开始前,必须先挂载文件系统:

fr = f_mount(&fs, "", 0);

这段代码挂载了文件系统。第一个参数是指向 FATFS 类型的文件系统对象的指针。在这个例子中,我们使用 &fs 。第二个参数是逻辑驱动器号,这里传入空字符串表示默认驱动器。最后一个参数为挂载选项, 0 表示以默认方式挂载。

文件创建与写入

创建文件并写入数据通过以下步骤完成:

fr = f_open(&fil, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);

此代码中, f_open 用于打开或创建文件。 &fil 是文件对象指针, "test.txt" 是要打开的文件名。标志 FA_CREATE_ALWAYS 表示如果文件存在则覆盖它, FA_WRITE 指明以写入模式打开文件。

写入数据:

fr = f_write(&fil, wtext, sizeof(wtext), &bw);

f_write 函数用于向文件写入数据。这里将 wtext 字符串写入文件, bw 用来存储实际写入的字节数。

文件读取

为了读取文件,我们需要重新打开文件,并在读取模式下:

fr = f_open(&fil, "test.txt", FA_READ);

最后,我们使用 f_read 来读取文件内容到缓冲区:

fr = f_read(&fil, rtext, sizeof(rtext), &bw);

这段代码将文件内容读取到 rtext 缓冲区中, bw 再次存储实际读取的字节数。

5.2 文件写入和删除操作示例

5.2.1 示例代码详解

接下来,我们将通过示例代码来展示如何在STM32上使用FATFS库进行文件写入和删除操作。

/* 假设之前的文件系统已经挂载 */

/* 写入数据到文件 */
fr = f_open(&fil, "test.txt", FA_OPEN_APPEND | FA_WRITE);
if (fr == FR_OK) {
    /* 在文件末尾追加文本 */
    fr = f_write(&fil, wtext, sizeof(wtext), &bw);
    /* 关闭文件 */
    f_close(&fil);
}

/* 删除文件 */
fr = f_unlink("test.txt");

5.2.2 代码中关键点分析

文件追加写入

在需要向文件末尾追加数据时,可以使用 FA_OPEN_APPEND 标志:

fr = f_open(&fil, "test.txt", FA_OPEN_APPEND | FA_WRITE);

与之前示例不同的是,此处我们用 FA_OPEN_APPEND FA_WRITE 的组合来打开文件,这样就会在文件的末尾追加数据而不是覆盖原有内容。

文件删除

删除文件非常简单:

fr = f_unlink("test.txt");

f_unlink 函数用于删除指定的文件。如果文件删除成功,函数返回 FR_OK

在以上的示例代码中,我们介绍了如何在STM32微控制器上利用FATFS库进行文件的创建、读取、写入和删除操作。通过这些示例,开发者可以理解如何将FATFS集成到他们的项目中,执行基本的文件管理任务。接下来的章节中,我们将继续探索FATFS在目录操作和属性查询方面的功能。

6. FATFS文件系统操作流程

6.1 FATFS文件系统挂载流程

FATFS文件系统的挂载是访问文件系统前必不可少的一个步骤,它涉及初始化文件系统和分配内存等操作,保证能够正确地与存储设备进行交互。在挂载文件系统之前,需要做一些准备工作,包括确认文件系统的类型,以及确保存储设备(比如SD卡)已经连接并被识别。

系统挂载前的准备工作

挂载FATFS文件系统之前,我们需要准备好一个磁盘I/O接口,这是与存储介质进行交互的基础。在STM32这样的嵌入式设备上,这通常是SD卡或者其他类型的存储设备。以下是一些挂载前的准备工作步骤:

  • 检查存储设备的连接状态 。确保SD卡已经插入并且被系统识别。这通常通过检查SD卡的检测引脚或者通过设备管理器查看是否识别到新设备。
  • 初始化磁盘I/O层 。在STM32微控制器上,这通常涉及使用SDIO接口或者SPI接口与SD卡进行通信。初始化工作包括配置相应的GPIO引脚,以及设置好SDIO或SPI的相关参数,比如时钟速度、通信协议等。
  • 确保足够的内存资源 。FATFS文件系统在运行时会占用一定的RAM资源,主要用来存储FAT表和工作缓冲区。在挂载文件系统之前,需要确保有足够的内存空间来维持文件系统正常运行。

文件系统挂载步骤和注意事项

一旦准备工作完成,接下来就是挂载FATFS文件系统的具体步骤,流程大致如下:

  1. 初始化文件系统对象 。创建一个FATFS类型的结构体变量,并调用 f_mount 函数来挂载文件系统。
  2. 挂载文件系统 。调用 f_mount 函数时,需要传入之前创建的FATFS结构体变量以及文件系统的工作缓冲区(如果需要的话)。此时,文件系统会从存储介质读取必要的信息,如FAT表、根目录项等,以建立起与存储介质的联系。
  3. 检查挂载状态 。挂载成功后,通过返回值或者检查文件系统对象的状态来确认是否正确挂载。
  4. 注意事项 。在挂载过程中需要注意的是,文件系统不能在使用中被强制卸载,这可能会导致存储介质损坏。此外,每次挂载前应确保文件系统之前没有异常关闭的情况,否则可能需要进行文件系统的完整性检查。

6.2 FATFS文件系统卸载和维护

文件系统的卸载是指断开文件系统与存储介质的连接,这一步骤同样重要,因为它确保了数据的完整性和存储介质的健康。

文件系统的安全卸载

在进行文件系统卸载前,需要确保所有挂载操作都已完成,所有的文件都已关闭,缓存也已经刷新。在STM32和FATFS的环境中,可以通过以下步骤安全地卸载文件系统:

  • 检查并关闭所有打开的文件 。在卸载文件系统之前,需要确保没有文件被打开或者处于使用中。这可以通过调用 f_close 函数来实现。
  • 刷新数据缓存 。在卸载文件系统之前,应该调用 f_sync 函数来同步所有已修改的文件,确保数据完整写入存储介质。
  • 卸载文件系统 。调用 f_mount 函数,并传入NULL作为参数来卸载文件系统。这将断开文件系统和存储介质的连接,并释放相关资源。

文件系统维护和错误处理

在文件系统运行过程中,维护工作也是必不可少的,它包括监控文件系统的健康状态,以及在出现问题时进行相应的错误处理。

  • 定期检查文件系统 。定期运行 f_checkdisk 函数来检查文件系统的完整性,确保没有文件系统错误。
  • 错误处理 。在遇到文件系统错误时,可以尝试使用 f_repair 函数进行简单的修复。若错误严重,可能需要对存储介质进行格式化。

错误处理和维护是文件系统长期稳定运行的保证。通过合理地使用FATFS提供的接口,可以有效地预防和处理文件系统运行中遇到的各类问题。

7. FATFS目录操作与属性查询功能

7.1 FATFS目录操作基础

7.1.1 目录的创建与删除

在FAT文件系统中,创建和删除目录的操作是常见的文件管理活动。使用FATFS库进行目录操作前,必须首先确保FATFS库已经正确挂载,并且拥有当前目录的读写权限。

创建目录的代码示例如下:

FRESULT create_directory(const char *path) {
    return f_mkdir(path);
}

该函数 f_mkdir 接受一个路径参数,并尝试在该路径下创建新的目录。如果目录创建成功,将返回 FR_OK 状态码;如果失败,返回其他相应的错误码。

删除目录的代码示例如下:

FRESULT delete_directory(const char *path) {
    return f_unlink(path);
}

使用 f_unlink 函数删除目录时,需要注意的是,只有当目标目录为空(不包含任何文件或子目录)时,该函数才会成功删除目录。

7.1.2 目录浏览与遍历方法

遍历目录中的文件或子目录,通常使用 f_opendir f_readdir f_closedir 这几个函数。目录浏览的代码示例如下:

FRESULT traverse_directory(const char *path) {
    DIR dj;
    FILINFO fno;

    // 打开目录
    FRESULT res = f_opendir(&dj, path);
    if (res == FR_OK) {
        // 读取目录项
        while ((res = f_readdir(&dj, &fno)) == FR_OK && fno.fname[0]) {
            // 输出文件信息
            printf("%s/%s\n", path, fno.fname);
        }
        // 关闭目录
        f_closedir(&dj);
    }
    return res;
}

在这段代码中,首先通过 f_opendir 打开指定路径的目录。 f_readdir 函数用于读取目录中的每一个项,如果读取成功, fno.fname[0] 不为空,表示还有更多的目录项。最后,使用 f_closedir 关闭目录,释放相关资源。

7.2 文件属性的查询与管理

7.2.1 文件属性的读取

文件属性包括文件的大小、创建时间、修改时间等信息。在FATFS库中,可以通过 f_stat 函数读取文件的属性信息:

void read_file_attributes(const char *path) {
    FILINFO fno;
    if (f_stat(path, &fno) == FR_OK) {
        printf("File size: %d\n", fno.fsize);
        printf("File date: %04d/%02d/%02d\n", fno.fdate >> 9, (fno.fdate >> 5) & 0x0F, fno.fdate & 0x1F);
        printf("File time: %02d:%02d:%02d\n", (fno.ftime >> 11), (fno.ftime >> 5) & 0x3F, (fno.ftime << 1) & 0x3E);
    } else {
        printf("File not found!\n");
    }
}

在这段代码中, f_stat 函数将文件属性信息存储在 fno 结构体中。 fno.fsize 字段包含了文件的大小,而 fno.fdate fno.ftime 字段则分别包含了文件的创建日期和时间。

7.2.2 文件时间戳和权限的修改

文件时间戳可以通过 futime 函数进行修改。修改文件时间戳的代码示例如下:

void update_file_timestamp(const char *path, WORD year, WORD month, WORD day, WORD hour, WORD min, WORD sec) {
    FILINFO fno;
    if (f_stat(path, &fno) == FR_OK) {
        fno.fdate = ((year - 1980) << 9) | ((month & 0x0F) << 5) | (day & 0x1F);
        fno.ftime = ((hour & 0x1F) << 11) | ((min & 0x3F) << 5) | ((sec >> 1) & 0x1F);
        f_lseek(path, 0); // 移动文件指针到文件开始位置
        f_chmod(path, fno.fattrib); // 更新文件属性
        futime(path, &fno);
    }
}

通过设置 fno.fdate fno.ftime ,然后调用 futime ,可以更新文件的最后访问时间和修改时间。此外, f_chmod 函数可以用来修改文件的属性(如只读、隐藏等)。

通过上述方法,开发者可以灵活地管理FATFS文件系统中的文件和目录,实现对文件属性的查询和修改。这对于文件的维护和管理至关重要,能够帮助开发者更好地组织和优化存储结构。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:在嵌入式系统中,文件系统的应用至关重要,尤其是在存储设备如SD卡的使用中。本项目专注于STM32微控制器上的FATFS文件系统实现,这是一种资源受限的嵌入式系统中广泛使用的轻量级文件系统。项目提供了FATFS库,支持多种FAT格式,并介绍了如何在STM32上与SD卡进行交互,实现文件的读写操作。FATFS库提供了丰富的文件操作函数,而SD卡驱动负责与STM32的通信,完成数据传输。本项目旨在通过实例程序,展示如何利用这些工具和库函数来实现文件的创建、打开、读取、写入和关闭等操作。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐