STM32CubeMX系列 | FATFS文件系统

发布者:SparklingStar22最新更新时间:2023-03-23 来源: zhihu关键字:STM32CubeMX系列  FATFS  文件系统 手机看文章 扫描二维码
随时随地手机看文章

1. FATFS文件系统简介

文件系统是操作系统用于明确存储设备或分区上的文件的方法和数据结构(即在存储设备上组织文件的方法)。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统;不带文件系统的SD卡仅能实现简单的读写扇区操作,要真正应用SD卡必须要使用文件系统

FATFS文件存储原理(以FAT32为例),下图为FAT32文件系统布局:

簇是文件存储的最小单元,FAT32分区大小与对应簇空间大小关系如下表示:

分区空间大小簇空间大小每个簇包含的扇区数
< 8GB4KB8
[ 8GB, 16GB )8KB16
[ 16GB, 32GB )16KB32
>= 32GB32KB64

例如:创建一个50字节的test.txt文件,文件大小是50字节,但是占用磁盘空间为4096字节(一个簇)

FATFS是一个完全免费开源,专为小型嵌入式系统设计的FAT(File Allocation Table)文件系统模块。FATFS的编写遵循ANSI C,并且完全与磁盘I/O层分开。支持FAT12/FAT16/FAT32,支持多个存储媒介,有独立的缓冲区,可对多个文件进行读写。兼容Windows文件系统。

FATFS模块的层次结构如下图示:

- 最顶层是应用层:使用者只需要调用FATFS模块提供给用户的一系列应用接口函数(如f_open, f_read, f_write和f_close等),就可以像在PC上读写文件那样简单
- 中间层FATFS模块:实现了FAT文件读写协议;它提供了ff.c和ff.h文件,一般情况下不用修改,使用时将头文件包含进去即可
- 最底层是FATFS模块的底层接口:包括存储媒介读写接口和供给文件创建修改时间的实时时钟,需要在移植时编写对应的代码

FATFS源码相关文件介绍如下表示;移植FATFS模块时,一般只需要修改2个文件(即ffconf.h和diskio.c)

与平台无关文件描述
ffconf.hFATFS模块配置文件
ff.hFATFS和应用模块公用的包含文件
ff.cFATFS模块
diskio.hFATFS和disk I/O模块公用的包含文件
interger.h数据类型定义
option可选的外部功能(比如支持中文)
与平台相关文件描述
diskio.cFATFS和disk I/O模块接口层文件

FATFS的移植主要分为三步:

- 数据类型:在integer.h里面去定义好数据的类型
- 配置:通过ffconf.h配置FATFS相关功能
- 函数编写:在diskio.c文件中进行底层驱动编写(6个接口函数disk_initialize、disk_status、disk_read、disk_write、disk_ioctl、get_fattime)

本例程使用的是STM32CubeMX图形化软件配置FATFS,只需要简单设置即可以完成以上三步的工作。下图是STM32CubeMX的FATFS底层实现框图:

STM32CubeMX生成的代码工程里,涉及底层驱动实现的文件主要有以下三个:

ff_gen_drv.c文件:FATFS提供的通用驱动文件的实现

//ff_gen_drv.h文件内容

/*Disk IO Driver structure definition */

typedef struct

{

  DSTATUS (*disk_initialize) (BYTE);    //通过指针指向diskio.c中的disk_initialize()

  DSTATUS (*disk_status)     (BYTE);    //通过指针指向diskio.c中的disk_status()

  DRESULT (*disk_read)       (BYTE, BYTE*, DWORD, UINT);    //指向disk_read()

#if _USE_WRITE == 1 

  DRESULT (*disk_write)      (BYTE, const BYTE*, DWORD, UINT);  //指向disk_write()

#endif 

#if _USE_IOCTL == 1  

  DRESULT (*disk_ioctl)      (BYTE, BYTE, void*);   //指向disk_ioctl() 

#endif

}Diskio_drvTypeDef;


/*brief  Global Disk IO Drivers structure definition*/ 

typedef struct{ 

  uint8_t                 is_initialized[_VOLUMES]; //磁盘是否初始化

  Diskio_drvTypeDef       *drv[_VOLUMES];   //磁盘的驱动

  uint8_t                 lun[_VOLUMES];    //磁盘的编号

  __IO uint8_t            nbr;

}Disk_drvTypeDef;

/* Exported functions ------------------------------------------------------- */

uint8_t FATFS_LinkDriverEx(Diskio_drvTypeDef *drv, char *path, uint8_t lun);

uint8_t FATFS_LinkDriver(Diskio_drvTypeDef *drv, char *path);

uint8_t FATFS_UnLinkDriver(char *path);

uint8_t FATFS_LinkDriverEx(Diskio_drvTypeDef *drv, char *path, BYTE lun);

uint8_t FATFS_UnLinkDriverEx(char *path, BYTE lun);

uint8_t FATFS_GetAttachedDriversNbr(void);

sd_diskio.c:针对SD底层驱动实现,封装成为通用的底层驱动API

//sd_diskio.c文件内容

const Diskio_drvTypeDef  SD_Driver = {

  SD_initialize,    //指向diskio.c中的disk_initialize()

  SD_status,    //指向diskio.c中的disk_status()

  SD_read,  //指向diskio.c中的disk_read()

#if  _USE_WRITE == 1

  SD_write, //指向diskio.c中的disk_write()

#endif /* _USE_WRITE == 1 */  

#if  _USE_IOCTL == 1

  SD_ioctl, //指向diskio.c中的disk_ioctl()

#endif /* _USE_IOCTL == 1 */

};  //定义Diskio_drvTypeDef类型的SD_Driver


/* -------------------以上各函数的实现---------------------------*/

DSTATUS SD_initialize(BYTE lun){

  Stat = STA_NOINIT;  

  if(BSP_SD_Init() == MSD_OK){

    Stat &= ~STA_NOINIT;

  }

  return Stat;

}


DSTATUS SD_status(BYTE lun){

  Stat = STA_NOINIT;

  if(BSP_SD_GetCardState() == MSD_OK){

    Stat &= ~STA_NOINIT;

  }

  return Stat;

}


DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count){

  DRESULT res = RES_ERROR;

  uint32_t timeout = 100000;

  if(BSP_SD_ReadBlocks((uint32_t*)buff,(uint32_t) (sector), count, SD_DATATIMEOUT) == MSD_OK){

    while(BSP_SD_GetCardState()!= MSD_OK){

      if (timeout-- == 0)

        return RES_ERROR;

    }

    res = RES_OK;

  } 

  return res;

}


#if _USE_WRITE == 1

DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count){

  DRESULT res = RES_ERROR;

  uint32_t timeout = 100000;

  if(BSP_SD_WriteBlocks((uint32_t*)buff,(uint32_t)(sector),count, SD_DATATIMEOUT) == MSD_OK){

    while(BSP_SD_GetCardState()!= MSD_OK){

      if (timeout-- == 0)

        return RES_ERROR;

    }    

    res = RES_OK;

  }

  return res;

}

#endif /* _USE_WRITE == 1 */


#if _USE_IOCTL == 1

DRESULT SD_ioctl(BYTE lun, BYTE cmd, void *buff){

  DRESULT res = RES_ERROR;

  BSP_SD_CardInfo CardInfo;  

  if (Stat & STA_NOINIT) return RES_NOTRDY;  

  switch (cmd){

  /* Make sure that no pending write process */

  case CTRL_SYNC :

    res = RES_OK;

    break;

  /* Get number of sectors on the disk (DWORD) */

  case GET_SECTOR_COUNT :

    BSP_SD_GetCardInfo(&CardInfo);

    *(DWORD*)buff = CardInfo.LogBlockNbr;

    res = RES_OK;

    break;

  /* Get R/W sector size (WORD) */

  case GET_SECTOR_SIZE :

    BSP_SD_GetCardInfo(&CardInfo);

    *(WORD*)buff = CardInfo.LogBlockSize;

    res = RES_OK;

    break;

  /* Get erase block size in unit of sector (DWORD) */

  case GET_BLOCK_SIZE :

    BSP_SD_GetCardInfo(&CardInfo);

    *(DWORD*)buff = CardInfo.LogBlockSize;

    res = RES_OK;

    break;

  default:

    res = RES_PARERR;

  } 

  return res;

}

#endif /* _USE_IOCTL == 1 */

bsp_driver_sd.c:HAL库的二次封装,将基于SD卡的操作都在该文件下实现

//bsp_driver_sd.h文件内容

uint8_t BSP_SD_Init(void);

uint8_t BSP_SD_ITConfig(void);

void    BSP_SD_DetectIT(void);

void    BSP_SD_DetectCallback(void);

uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout);

uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout);

uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks);

uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks);

uint8_t BSP_SD_Erase(uint32_t StartAddr, uint32_t EndAddr);

void BSP_SD_IRQHandler(void);

void BSP_SD_DMA_Tx_IRQHandler(void);

void BSP_SD_DMA_Rx_IRQHandler(void);

uint8_t BSP_SD_GetCardState(void);

void    BSP_SD_GetCardInfo(HAL_SD_CardInfoTypeDef *CardInfo);

uint8_t BSP_SD_IsDetected(void);

void    BSP_SD_AbortCallback(void);

void    BSP_SD_WriteCpltCallback(void);

void    BSP_SD_ReadCpltCallback(void);

FATFS提供的应用接口如下图示:

下面简单介绍几个常用操作函数:


f_mount:在FATFS模块上注册/注销一个工作区(文件系统对象)

FRESULT f_mount(FATFS* fs, const TCHAR* path, BYTE opt);

参数--> fs:fs工作区(文件系统对象)指针,如果赋值为 NULL 可以取消物理设备挂载

        path:注册/注销工作区的逻辑设备编号,使用设备根路径表示

        opt:注册或注销选项(可选0或1),0表示不立即挂载,1表示立即挂载

f_mkfs:格式化物理设备

FRESULT f_mkfs(const TCHAR* path, BYTE sfd, UINT au);

参数--> path:逻辑设备编号,使用设备根路径表示

        sfd:0或1,0表示为硬盘设备;1表示为软盘设备

        au:指定扇区大小,若为0表示通过disk_ioctl函数获取

f_open:创建/打开一个文件对象

FRESULT f_open(FIL* fp, const TCHAR* path, BYTE mode);

参数--> fp:将创建或打开的文件对象指针

        path:文件名指针,指定将创建或打开的文件名(包含文件类型后缀名)

        mode:访问类型和打开方法

mode可选值:

FA_READ     指定读访问对象。可以从文件中读取数据。 与FA_WRITE结合可以进行读写访问。   

FA_WRITE    指定写访问对象。可以向文件中写入数据。与FA_READ结合可以进行读写访问。   

FA_OPEN_EXISTING    打开文件。如果文件不存在,则打开失败。(默认)  

FA_OPEN_ALWAYS      如果文件存在,则打开;否则,创建一个新文件。  

FA_CREATE_NEW       创建一个新文件。如果文件已存在,则创建失败。   

FA_CREATE_ALWAYS    创建一个新文件。如果文件已存在,则它将被截断并覆盖。

f_close:关闭一个打开的文件

FRESULT f_close (FIL *fp)

参数--> fp:将被关闭的已打开的文件对象结构的指针

f_write:写入数据到一个已打开的文件

FRESULT f_write (FIL* fp, const void *buff, UINT btw, UINT* bw)

参数--> fp:指向将被写入的已打开的文件对象结构的指针

        buff:指向存储写入数据的缓冲区的指针

        btw:要写入的字节数

        bw:指向返回已写入字节数的UINT变量的指针,返回为实际写入的字节数

f_read:从一个打开的文件中读取数据

FRESULT f_read (FIL* fp, const void *buff, UINT btr, UINT* br)

参数--> fp:指向将被读取的已打开的文件对象结构的指针

        buff:指向存储读取数据的缓冲区的指针

        btr:要读取的字节数

        br:指向返回已读取字节数的UINT变量的指针,返回为实际读取的字节数

2. 硬件设计

D1指示灯用来提示系统运行状态,串口1用来打印调试信息,使用FATFS文件系统对SD卡进行相关操作

  • D1指示灯

  • USART1

  • TF卡

3. 软件设计

3.1 STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M

  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

  • 激活SDIO,详细请参考SD卡例程

  • 打开FATFS文件系统,按下图配置,其余默认值

  • 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

3.2 MDK-ARM编程

int main(void){

    HAL_Init();

    SystemClock_Config();

  /* Initialize all configured peripherals */

    MX_GPIO_Init();

    MX_CRC_Init();

    MX_FSMC_Init();

    MX_SDIO_SD_Init();

    MX_USART1_UART_Init();

    MX_FATFS_Init();

  /* USER CODE BEGIN 2 */

    uint32_t byteswritten;                /* File write counts */

    uint32_t bytesread;                   /* File read counts */

    uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */

    uint8_t rtext[100];                   /* File read buffers */

    char filename[] = "STM32cube.txt";

    char SensorBuff[100];

    printf("********* STM32CubeMX FatFs Example *********rnrn");    

    if(f_mount(&SDFatFS,SDPath,1) == FR_OK){

        printf("f_mount sucess!!! rn");

[1] [2]
关键字:STM32CubeMX系列  FATFS  文件系统 引用地址:STM32CubeMX系列 | FATFS文件系统

上一篇:STM32CubeMX系列 | SD卡
下一篇:CLion配置STM32开发环境

推荐阅读最新更新时间:2024-11-13 10:37

烧写内核+烧写文件系统(JZ2440-S3C2440)
(一)使用DNW烧写内核 1、把开发板设置为 NOR 启动,连接 USB-串口线(开发板上的 USBcom1口 --- PC 的 USB 口), 用另一条 USB 线连接 PC机和开发板 USB 口(开发板上的 USB 口 --- PC 的 USB口)。 上电,使用 SecureCRT,选择 Download Linuxkernel uImage。 2、使用 DNW 工具,先进行“Serial Port”中的“Connect”。使用“USB Port”菜单中的 Transmit,发送要烧写uImage 文件。开发板收到文件后会自动把程序烧写到 NAND Flash上去。 (二)使用TFTP烧写内核 1、先查看PC
[单片机]
烧写内核+烧写<font color='red'>文件系统</font>(JZ2440-S3C2440)
吓人技术是它?华为演示安卓新文件系统EROFS:手机更快
文件系统虽然听起来有些晦涩,但其实有些常识的用户都接触过,尤其是PC用户。比如,在单文件开始突破4GB+大小的时候,FAT32由于先天局限无法支持 ,从而将NTFS格式推向历史舞台。 安卓依托于Linux,所以主要的文件系统包括exFAT、F2FS、ext4等,在华为Mate 9的发布会上,余承东就曾隆重介绍了EMUI 5.0采用F2FS取代ext4,使得流畅度提升。而这套F2FS是三星开发的,其对高速闪存的4K读写做了大量优化。 据Phoronix/XDA报道,华为工程师Gao Xiang在开源社区分享了一套新的Linux只读文件系统EROFS(Extendable Read-Only File System,暂译为
[手机便携]
SD卡和FAT文件系统示例
1. 初始化SD卡。 我现在用的多是SPI模式,所以在这里只讨论SPI模式。在SPI模式中,所有的指令都要求先将CS脚置0。所以这点,我在后面就不再强调了。 CMD0,使SD卡从SD模式转到SPI模式。判断返回值R0,如果不是CARD IS NOT READY,说明硬件上有问题。 CMD8,参数是0x000001AA,判断SD卡符合哪个标准。如果返回ILLEGAL COMMAND,说明是ver1.x的卡,否则就是ver2.0的卡。 CMD1,如果是ver2.0的卡,参数是1 30,否则就是0,读取SD卡的状态,反复,直到CARD IS READY或者超时。这里有一个问题,Spec上建议使用ACMD1,说是通用性比CMD1好,而且
[单片机]
STM32F7xx —— FatFS(W25QXX)
使用经典的fatfs1.4.1,下载源码,和我们用户相关的式diskio.c,实现里面的初始化读写和ioctl。ffconf.h用来配置,很容易看懂,不再细说了。后面写了一个测试例子,能读写成功就说明没问题了。Fatfs对文件的操作与Linux文件操作基本类似,会使用就行,想弄清楚实现要深入学习fatfs的文件结构。 /*-----------------------------------------------------------------------*/ /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ /*---------
[单片机]
STM32CubeMX系列教程04_STM32CubeMX各窗口界面描述
一、写在前面 上一篇文章让你入门STM32CubeMX,你可能还是会觉得心里摸不到底。本文就从另外一个角度带你了解STM32CubeMX。 本文讲述STM32CubeMX各主要界面内容,让你对STM32CubeMX这个工具有一个比较直观的认识。 二、主界面 打开STM32CubeMX,呈现的界面大致如下图,界面比较简洁。我把它划分为六大板块。 1.菜单 STM32CubexMX V4版本(前面老版本)有很多功能做在菜单里面,但V5版本优化(删减)菜单,把一些常用功能做在相应界面里面了。 菜单内容后面会单独详细讲述。 2.社交链接 facebook(脸书)、youtube、twitter(推特)以及ST社区、官
[单片机]
<font color='red'>STM32CubeMX</font><font color='red'>系列</font>教程04_STM32CubeMX各窗口界面描述
STM32+SDIO+FATFS文件系统 直读SD卡 (含程序)
网上关于小型嵌入式的文件系统有好多~当然要数 FATFS 很是出名 一来小巧,二来免费。当然了国产的振南的znFAT 一样开源好用而且极其的省资源~!非常适合51单片。更重要的是国语的支持,呵呵!这次在STM32上为SD卡移植文件系统还是非常简单顺利的,这多亏了ST 官方提供的驱动,而我自己不用动手编写SD卡的命令省了很多时间而且官方做的驱动虽然效率一般但是极其严谨我很是佩服。 FATFS的官方网站是 http://elm-chan.org/fsw/ff/00index_e.html znFAT的官方网站是 http://www.znmcu.cn/softshow.asp?id=47 SD卡以用SPI驱动 也可
[单片机]
第37章 基于SD卡的FatFs文件系统—零死角玩转STM32-F429系列
上一章我们已经全面介绍了SD卡的识别和简单的数据读写,也进行了简单的读写测试,不过像这样直接操作SD卡存储单元,在实际应用中是不现实的。SD卡一般用来存放文件,所以都需要加载文件系统到里面。类似于串行Flash芯片,我们移植FatFs文件系统到SD卡内。 对于FatFs文件系统的介绍和具体移植过程参考 基于串行Flash的FatFs文件系统 ,这里就不做过多介绍,重点放在SD卡与FatFs接口函数编写上。与串行Flash的FatFs文件系统移植例程相比,FatFs文件系统部分的代码只有diskio.c文件有所不同,其他的不用修改,所以一个简易的移植方法是利用原来工程进行修改。下面讲解利用原来工程实现SD卡的FatFs文件系统。
[单片机]
第37章 基于SD卡的<font color='red'>FatFs</font><font color='red'>文件系统</font>—零死角玩转STM32-F429<font color='red'>系列</font>
为STM32移植FATFS,读取SD卡上FAT12/16/32文件系统
给stm32移植fatfs文件系统,今天终于取得阶段性胜利。只需要提供这样几个函数即可 DSTATUS disk_initialize (BYTE); DSTATUS disk_status (BYTE); DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); // 如果实现只读的文件系统就不需要了。 DRESULT disk_ioctl (BYTE, BYTE, void*); 移植成功后,可以用如下方式读取SD卡了,实在太方便了,和PC机上编程差不了多少。 unsigned in
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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