1. 为什么你的STM32F429需要文件系统?
如果你用过STM32F429的SPI Flash,比如W25Q256,你肯定干过这样的事:为了存一段数据,你得自己算好一个绝对地址,比如从0x00010000开始写,然后小心翼翼地记在小本本上,生怕下次读的时候忘了。想存个日志?得自己管理地址偏移。想存多个不同版本的文件?头都大了。这就像在一个巨大的仓库里,你把东西随便往地上一扔,过几天自己都找不着了。
文件系统就是来解决这个“仓库管理”难题的。它就像给你的SPI Flash请了一个专业的仓库管理员(FatFs),这个管理员会帮你:
- 建立目录和文件索引:你不用再记物理地址了,给文件起个名字(比如
log_20231027.txt),告诉管理员“存起来”,它自己会找地方放好。 - 自动管理剩余空间:它会记录哪里用了,哪里空着,你只管“存”和“取”,不用操心会不会覆盖掉别人的数据。
- 提供标准操作接口:
f_open,f_write,f_read,f_close... 这一套是不是很眼熟?对,和你在电脑上用C语言读写文件几乎一模一样。这意味着你的应用层代码和底层存储设备彻底解耦了。
所以,当你的项目需要存储配置文件、记录运行日志、保存用户数据或者存放字库图片等资源时,上文件系统是必然选择。而FatFs,正是为STM32这类资源有限的MCU量身定做的轻量级文件系统,它纯C编写,几乎不挑硬件,移植起来特别友好。
2. 动手之前:理清FatFs的“三明治”结构
在开始敲代码前,我们必须搞清楚FatFs在整个工程里扮演什么角色。它不是魔法,而是一个清晰的分层架构,理解了这个,移植和调试都会轻松很多。
你可以把FatFs想象成一个“三明治”:
- 最上层:应用层(你写的代码)。你在这里调用
f_open,f_write等标准API,完全不用关心底下是SPI Flash还是SD卡。 - 中间层:FatFs核心(ff.c, ff.h)。这是FatFs的大脑,负责文件分配表(FAT)的管理、目录解析、逻辑簇号转换等所有文件系统的核心逻辑。这一层我们通常不需要动。
- 最底层:设备驱动层(diskio.c)。这是FatFs和你的硬件(STM32F429的SPI外设和W25Q256芯片)对话的“翻译官”。FatFs只知道“读扇区”、“写扇区”这些抽象指令,而具体怎么通过SPI总线发命令、读数据,全靠这一层的函数来实现。移植的工作,90%都集中在这里。
此外,还有两个关键的配置文件:
- ffconf.h:FatFs的功能“菜单”。你可以在这里裁剪功能,比如要不要支持长文件名、用什么语言编码、支持几个物理设备等。通过改这里的宏定义,可以优化最终代码的体积和功能。
- integer.h:数据类型定义。确保FatFs用的
DWORD、UINT等类型和你编译器里的定义一致,通常不用改。
所以,我们的核心任务就是:根据开发板的硬件连接,在diskio.c里写好那几个“翻译”函数,然后在ffconf.h里勾选我们需要的功能。
3. 从零开始:将FatFs移植到SPI Flash
理论说再多不如动手。我们假设你已经有一个能正常读写W25Q256的SPI驱动工程了(如果还没有,得先搞定这个)。接下来,我们一步步把FatFs加进去。
3.1 获取源码与添加工程
首先,去FatFs官网(elm-chan.org)下载最新源码。解压后,我们主要关心src文件夹里的东西。把它拷贝到你的项目目录下,比如Middlewares/FatFs。
在你的IDE(比如Keil MDK或IAR)里,将以下文件添加到工程:
src/ff.c:核心文件,必须添加。src/diskio.c:驱动接口文件,必须添加,也是我们要修改的重点。src/option/cc936.c:如果你需要支持简体中文文件名(长文件名),就需要添加这个。否则,用ccsbcs.c就行。- 把头文件路径
Middlewares/FatFs/src也添加到项目的包含路径里。
3.2 核心改造:编写diskio.c的驱动接口
这是移植的重中之重。diskio.c里有6个函数需要我们根据硬件实现。别怕,我们一个个来拆解。
首先,在文件开头定义你的设备编号。FatFs支持多个存储设备(比如同时挂载SPI Flash和SD卡),用编号区分。
#define DEV_SPI_FLASH 0 // 我们给SPI Flash分配逻辑设备号0
#define DEV_SD_CARD 1 // 可以预留一个给SD卡
第一个函数:disk_initialize - 设备初始化 当FatFs调用f_mount时,会先来初始化设备。这里就是调用你的SPI和Flash芯片初始化函数。
DSTATUS disk_initialize (BYTE pdrv)
{
DSTATUS stat = STA_NOINIT;
switch (pdrv) {
case DEV_SPI_FLASH:
SPI_FLASH_Init(); // 你的SPI外设

2042

被折叠的 条评论
为什么被折叠?



