历史上的今天

今天是:2025年10月12日(星期日)

正在发生

2022年10月12日 | 基于STM32完成FATFS文件系统移植与运用

发布者:美梦小狮子 关键字:STM32  FATFS  文件系统  移植 手机看文章 扫描二维码
随时随地手机看文章

一、环境介绍

主控MCU: STM32F103ZET6 


STM32程序开发IDE: keil5


STM32程序风格:  采用寄存器方式开发,注释齐全,执行效率高,方便移植


硬件包含:  一块STM32F103ZET6系统板、一个SPI接口的SD卡卡槽模块、一张SD卡


工程完整源码下载地址:  https://download.csdn.net/download/xiaolong1126626497/19687693


这篇文章主要演示FATFS文件系统如何移植到自己的工程,并完成文件的读写。


因为SD卡采用的是SPI模拟时序,所以,其他单片机一样可以照着移植,代码都可以复制粘贴的。

二、FATFS文件系统介绍

2.1 FATFS简介

FatFs 是一种完全免费开源的 FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全用标准C 语言编写,所以具有良好的硬件平台独立性,可以移植到 8051、 PIC、 AVR、 SH、 Z80、 H8、 ARM 等系列单片机上而只需做简单的修改。它支持 FATl2、 FATl6 和 FAT32,支持多个存储媒介;有独立的缓冲区,可以对多个文件进行读/写,并特别对 8 位单片机和 16 位单片机做了优化。


2.2 特点

 Windows兼容的FAT文件系统

不依赖于平台,易于移植

代码和工作区占用空间非常小

 多种配置选项

多卷(物理驱动器和分区)

 多ANSI/OEM代码页,包括DBCS

在ANSI/OEM或Unicode中长文件名的支持

RTOS的支持

多扇区大小的支持

只读,最少API,I/O缓冲区等等

2.3 移植性

fatfs模块是ANSI C(C89)编写的。 没有平台的依赖, 编译器只要符合ANSI C标准就可以编译。


fatf模块假设大小的字符/短/长8/16/32位和int是16或32位。 这些数据类型在integer.h文件中定义。这些数据类型在大多数的编译器中定义都符合要求。 如果现有的定义与编译器有任何冲突发生时,需要自己解决。


2.4 源码下载

下载地址:http://elm-chan.org/fsw/ff/00index_e.html

FATFS有两个版本,一个大版本,一个小版本。小版本主要用于8位机(内存小)使用。


下载图:

2.5 FATFS源码文件介绍

将下载的源码解压后可以得到两个文件夹: doc 和 src。 doc 里面主要是对 FATFS 的介绍(离线文档—英文和日文),而 src 里面才是我们需要的源码。


其中,与平台无关的是:


ffconf.h     FATFS配置文件


ff.h        应用层头文件


ff.c        应用层源文件


diskio.h    硬件层头文件


interger.h   数据类型定义头文件


option     可选的外部功能(比如支持中文等)


与平台相关的代码:


diskio.c     底层接口文件(需要用户提供)


FATFS 模块在移植的时候,我们一般只需要修改 2 个文件,即 ffconf.h 和 diskio.c。


FATFS模块的所有配置项都是存放在 ffconf.h 里面,我们可以通过配置里面的一些选项,来满足自己的需求。


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


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


需要我们编写移植代码的是 FATFS 模块提供的底层接口,它包括存储媒介读/写接口 ( disk、I/O) 和供给文件创建修改时间的实时时钟。


三、 移植FATFS文件系统

移植之前,首先得准备一个能正常编译的工程,并且工程里有SD卡的驱动代码,提供了读写扇区这些函数才能进行FATFS文件系统的正常移植。


关于如何编写SD卡驱动,SD卡的时序介绍、命令介绍等知识点下篇文章再讲解。这篇文章重点是FATFS文件系统的移植过程。


3.1  新建工程

FATFS文件系统源码下载下来,解压之后,移植修改的步骤如下:


打开KEIL工程,添加FATFS文件源码:

加入.h文件主要是方便配。cc936.c 用于支持中文。

3.2  修改diskio.c文件

注释掉现在不需要的用到的文件,因为我们现在用的是SD卡,与USB,ATA,MMC卡没关系。


并加入一个新的宏 :


#define  SD  0


定义SD卡的物理驱动器号为0。 


修改 disk_status函数,该函数主要是用来获取磁盘状态。现在未用到,可以直接函数体内代码删除。


修改截图:


代码示例:


#include "diskio.h"           /* fatf底层API */


#include "sd.h"                      /* SD卡驱动头文件  */


/* 定义每个驱动器的物理驱动器号*/


#define SD    0


 


/*-----------------------------------------------------------------------*/


/* 获取设备(磁盘)状态                                                     */


/*-----------------------------------------------------------------------*/


 


DSTATUS disk_status (


        BYTE pdrv             /* 物理驱动识别 */


)


{


   return 0;  //该函数现在无需用到,直接返回0


}


修改disk_initialize函数,添加SD卡的初始化,其他不用到的代码直接删掉,该函数成功返回0,失败返回1。


修改截图:

代码示例:


/*-----------------------------------------------------------------------*/


/* 初始化磁盘驱动                                                        */


/*-----------------------------------------------------------------------*/


 


DSTATUS disk_initialize (


        BYTE pdrv                             /* 物理驱动识别 */


)


{


        DSTATUS stat;


        int result;


 


        switch (pdrv) {


        case SD :            //选择SD卡


                stat=SD_Init();   //初始化SD卡-用户自己提供


        }


        if(stat)return STA_NOINIT;  //磁盘未初始化


        return 0; //初始化成功


}


修改disk_read函数,加入SD卡读任意扇区的函数(需要用户自己提供),其他不用到的选项可以删掉。

修改代码如下:


/*-----------------------------------------------------------------------*/


/* 读扇区                                                                */


/*-----------------------------------------------------------------------*/


DRESULT disk_read (


        BYTE pdrv,            /* 物理驱动编号 - 范围0-9*/


        BYTE *buff,           /* 数据缓冲区存储读取数据 */


        DWORD sector,  /* 扇区地址*/


        UINT count             /* 需要读取的扇区数*/


)


{


        DRESULT res;


        int result;


        switch (pdrv) {


                case SD:


                  res=SD_Read_Data((u8*)buff,sector,count);  //读SD扇区函数--用户提供


                  return res; //在此处可以判错误


        }


        return RES_PARERR;  //无效参数


}


修改disk_write 函数,添加写扇区函数:

代码:


/*-----------------------------------------------------------------------*/


/* 写扇区                                                                */


/*-----------------------------------------------------------------------*/

#if _USE_WRITE


DRESULT disk_write (


        BYTE pdrv,                      /* 物理驱动号*/


        const BYTE *buff,        /* 要写入数据的首地址 */


        DWORD sector,                 /* 扇区地址 */


        UINT count                        /* 扇区数量*/


)


{


        DRESULT res;


        int result;


 


        switch (pdrv) {


                case SD:


                        res=SD_Write_Data((u8*)buff,sector,count); //写入扇区


                  return res;


        }


        return RES_PARERR;  //无效参数


}


#endif


修改disk_ioctl 函数,填充ioctl命令功能。这些功能是标准的命令,在diskio.h有定义。


代码如下:

/*-----------------------------------------------------------------------*/


/* 其他函数                                              */


/*-----------------------------------------------------------------------*/


 


#if _USE_IOCTL


DRESULT disk_ioctl (


        BYTE pdrv,            /* 物理驱动号 */


        BYTE cmd,               /* 控制码  */


        void *buff               /* 发送/接收数据缓冲区地址 */


)


{


        DRESULT res;


        int result;


 


        switch (pdrv) {


                case SD:


                         switch(cmd)


                         {


                                 case CTRL_SYNC:      //等待写过程


                                         SD_CS(0);          //选中SD卡


                                         if(SD_Wait_Ready())result = RES_ERROR;/*等待卡准备好*/


                                     else res = RES_OK;     //成功


                                         SD_CS(1);            //释放SD卡


                        break;     


                                 


                         case GET_SECTOR_SIZE://获取扇区大小


                           *(DWORD*)buff = 512;


                        res = RES_OK;     //成功


                        break;     


                                 


                         case GET_BLOCK_SIZE:    //获取块大小


                                *(WORD*)buff = 8;      //块大小(扇区为单位),一块等于8个扇区


                         res = RES_OK;


                         break;

[1] [2] [3] [4] [5]
关键字:STM32  FATFS  文件系统  移植 引用地址:基于STM32完成FATFS文件系统移植与运用

上一篇:基于STM32完成FATFS文件系统移植与运用
下一篇:基于STM32设计的小说阅读器(翻页、字体切换、颜色切换、语音播报)

推荐阅读

今天,机器人“网红”公司波士顿动力又有了新动态,他们发布了一段以腿足式机器人“Altas”为主角的演示视频。视频中,面对一层比一层高的高台,Altas以跳跃式的姿态很稳定的、以层层递进的方式跳上了高台。关于Altas的这段表演,波士顿动力在视频中描述道:“控制软件(control software)利用包括腿、胳膊和躯干在内的整个身体,在不中断步伐的情况下,...
电磁流量计的测量通过是一段无阻流检测件的光滑直管,仪表的阻力仅是同一长度管道的沿程阻力,节能效果显著,所测得的体积流量,实际上不受流体密度、粘度、温度、压力和导电率(只要在某阈值以上)变化明显的影响,测量范围度大,要真正发挥电磁流量计的高精度、高稳定性等优异性能,必须要注意根据不同的测量介质选择相应类型的流量计。一、自来水大流量...
MPX4115压力传感器AT89c51单片机LED共阳极显示 单片机最小系统显示模块AD0832与单片机的连接传感器与AD的连接单片机源程序如下:#include <reg51.h>#include <intrins.h>//ADC0832 引脚sbit ADCS=P2^0;sbit ADDI=P3^7;sbit ADDO=P3^7;sbit ADCLK=P3^6;unsigned char dispbitcode[8]={0xF7,0xFB,0xFD,0xFE,0xEF,0xDF,0xBF,0x7F}; //位扫描unsigne...
在单片机的应用系统中,经常会用到EEPROM,用来保存一些掉电后仍然需要保存的数据。传统的方法是在单片机外再加一个EEPROM芯片,这种方法除了增加成本外,也降低了可靠性。现在,许多单片机芯片公司也都推出了集成有小容量EEPROM的单片机,降低了成本,提高了可靠性。STM8单片机芯片内部也集成有EEPROM,容量从640字节到2K字节。最为关键的是,在STM8单片...

史海拾趣

问答坊 | AI 解惑

关于ad9833的问题

    问ad9833能产生方波吗?看了它的控制寄存器功能表,好像不能直接产生方波啊,而且框图里面也没有比较器嘛,但看关于它的主要特点,都说可以直接产生正弦、三角、方波三种波形    恳请赐教…

查看全部问答∨

单片机最小系统

实验五、模数转换 一、实验目的 1、掌握A/D转换与单片机的接口方法; 2、掌握A/D芯片TLC549的编程方法; 3、掌握数据采集程序的设计方法; 二、实验内容 利用实验开发装置上的TLC549做A/D转换器,对电位器提供的模拟电压信号进行定时中断 ...…

查看全部问答∨

分享入门资料

将linux嵌入ARM的典型步骤以及相关应用工具…

查看全部问答∨

关于在evc中开发ppc的GIS程序的数据图片加载的问题

搞到了一个份能在EVC下运行的 pocketpc  GIS的程序 程序都能运行 只是 随程序提供了一个map文件夹 里面放了一些 .dbf .shp和.shx的文件,应该是一些地图图片信息和相关的地理数据信息。程序运行时 需要加载上述的图片,我是在模拟器中运 ...…

查看全部问答∨

tlc555频率测量,理论实际不符怎么回事?

tlc555频率测量时,如果选取C=180PF,要求输出为20KHZ左右,匹配R1,R2时该注意什么,为什么我选取R1=18K,R2=110K,按照如下公式计算: 上升时间 (T1) = 0.693 * (R1+R2) * C 下降时间(T2) = 0.693 * R2 * C 頻率 = 1.44 / ( (R1+R2+R2) * C) ...…

查看全部问答∨

请问各位大侠,在WinCE中调用windows media player 时,能不能隐藏它自带的下面的一排按钮.

我在WinCE+VS2005调用Windows media player,定制它的界面,请问可以实现吗? …

查看全部问答∨

ActiveSync连接 造成电脑死机 问题

我调试wince的时候使用ActiveSync进行连接 有时候调试到一般,连接突然中断,但是电脑右下脚的小图标仍然是绿色,这个时候我一拔出USB电缆,电脑就会死机 这个问题困扰了我很久 希望有人能帮我解决,谢谢!…

查看全部问答∨

H3C高端路由器产品招聘软件开发人员

H3C公司2003年11月成立,最初由华为和3COM合资组建,2006年11月由3COM公司全资收购。 目前公司正在全力投入高端路由器产品的开发,急需大量软件开发、测试人员。 地点:杭州 职责: 1、负责H3C高端路由器产品软件开发工作,完成相关的设计文档、 ...…

查看全部问答∨

wince设备连接PC的SQL SERVER问题,急啊!

各位好!我现在用一台PC没有与其他PC连网,只使用它来开发,用ACTIVESYNC与WINCE设备相连,在模拟器中可以与SQLSERVER相连,可是部署到设备上时,提示找不到SQLSERVER,请问谁遇到过,帮忙解决一下,多谢!…

查看全部问答∨

eZ430-RF2500开发板申请

将认真填写测试报告…

查看全部问答∨
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved