历史上的今天
返回首页

历史上的今天

今天是:2024年10月26日(星期六)

2021年10月26日 | stm32专题十九:FatFs文件系统简单读写

2021-10-26 来源:eefocus

首先,我们需要向FatFs来提供一些硬件接口,包括储存设备的初始化,读 / 写函数,硬件参数等,这些在diskio.c中实现:


diskio.c


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

/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2014        */

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

/* If a working storage control module is available, it should be        */

/* attached to the FatFs via a glue function rather than modifying it.   */

/* This is an example of glue functions to attach various exsisting      */

/* storage control modules to the FatFs module with a defined API.       */

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

 

#include "diskio.h" /* FatFs lower layer API */

#include "./flash/bsp_spi_flash.h"

//#include "usbdisk.h" /* Example: Header file of existing USB MSD control module */

//#include "atadrive.h" /* Example: Header file of existing ATA harddisk control module */

//#include "sdcard.h" /* Example: Header file of existing MMC/SDC contorl module */

 

/* Definitions of physical drive number for each drive */

#define ATA 0 /* Example: Map ATA harddisk to physical drive 0 */

#define MMC 1 /* Example: Map MMC/SD card to physical drive 1 */

#define USB 2 /* Example: Map USB MSD to physical drive 2 */

 

#define SD_CARD 0

#define SPI_FLASH 1

 

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

/* Get Drive Status    读取驱动状态                                       */

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

 

DSTATUS disk_status (

BYTE pdrv /* Physical drive nmuber to identify the drive */

)

{

DSTATUS stat;

// int result;

 

switch (pdrv) {

case SD_CARD :

// result = ATA_disk_status();

 

// translate the reslut code here

 

return stat;

 

case SPI_FLASH :

if (SPI_FLASH_ReadID() == sFLASH_ID)

{

// 状态正常

stat = 0;

}

else

{

// 状态异常

stat = STA_NOINIT;

}

 

// translate the reslut code here

 

return stat;

}

return STA_NOINIT;

}

 

 

 

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

/* Inidialize a Drive                                                    */

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

 

DSTATUS disk_initialize (

BYTE pdrv /* Physical drive nmuber to identify the drive */

)

{

DSTATUS stat;

// int result;

 

switch (pdrv) {

case SD_CARD :

// result = ATA_disk_initialize();

 

// translate the reslut code here

 

return stat;

 

case SPI_FLASH :

SPI_FLASH_Init(); // 这里只是初始化引脚和硬件SPI

SPI_Flash_WAKEUP(); // 确保FLASH不处在低功耗状态

return disk_status(SPI_FLASH);

 

}

return STA_NOINIT;

}

 

 

 

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

/* Read Sector(s)                                                        */

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

/* 这里操作的单位都是扇区,要对应到实际的地址                                 */

DRESULT disk_read (

BYTE pdrv, /* Physical drive nmuber to identify the drive */

BYTE *buff, /* Data buffer to store read data */

DWORD sector, /* Sector address in LBA */

UINT count /* Number of sectors to read */

)

{

DRESULT res;

// int result;

 

switch (pdrv) {

case SD_CARD :

// translate the arguments here

 

// result = ATA_disk_read(buff, sector, count);

 

// translate the reslut code here

 

return res;

 

case SPI_FLASH :

// 输入的是扇区号,这里要转换成地址

// W25Q64的每个扇区为4KB = 4096 字节

SPI_FLASH_BufferRead(buff, sector * 4096, count * 4096);

res = RES_OK; // 默认就认为读取正常

 

return res;

 

}

 

return RES_PARERR;

}

 

 

 

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

/* Write Sector(s)                                                       */

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

 

#if _USE_WRITE

DRESULT disk_write (

BYTE pdrv, /* Physical drive nmuber to identify the drive */

const BYTE *buff, /* Data to be written */

DWORD sector, /* Sector address in LBA */

UINT count /* Number of sectors to write */

)

{

DRESULT res;

// int result;

 

switch (pdrv) {

case SD_CARD :

// translate the arguments here

 

// result = ATA_disk_write(buff, sector, count);

 

// translate the reslut code here

 

return res;

 

case SPI_FLASH :

// 一定要先擦除再写入

SPI_FLASH_SectorErase(sector * 4096);

SPI_FLASH_BufferWrite((u8 *)buff, sector * 4096, count * 4096);

 

res = RES_OK;

return res;

}

 

return RES_PARERR;

}

#endif

 

 

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

/* Miscellaneous Functions                                               */

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

/* 杂项功能函数,用于传递存储器硬件相关的参数,以便于格式化文件系统 ------------*/

 

#if _USE_IOCTL

DRESULT disk_ioctl (

BYTE pdrv, /* Physical drive nmuber (0..) */

BYTE cmd, /* Control code */

void *buff /* Buffer to send/receive control data */

)

{

DRESULT res;

// int result;

 

switch (pdrv) {

case SD_CARD :

 

// Process of the command for the ATA drive

 

return res;

 

case SPI_FLASH :

 

switch (cmd)

{

/* 

case CTRL_SYNC:

// 用于实现缓存,把要写入的文件,先保存在内存(缓存)中,然后再一次性写入到存储介质

break;

*/

// 返回扇区个数

case GET_SECTOR_COUNT:

// buff是一个void*空指针,我们根据命令格式,要转换成 DWORD* 类型的指针

*(DWORD *)buff = 2048;

break;

// 返回扇区大小

case GET_SECTOR_SIZE:

*(WORD *)buff = 4096;

break;

// 返回擦除扇区的最小个数

case GET_BLOCK_SIZE:

*(DWORD *)buff = 1;

break;

}

res = RES_OK;

return res;

}

 

return RES_PARERR;

}

#endif

 

// 返回时间

DWORD get_fattime (void)

{

return 0;

}

 

其中包括了读取设备状态(通过读取SPI设备号来实现),存储设备初始化(stm32引脚配置和硬件SPI),读写操作(调用SPI读写函数),以及传递硬件参数的杂项函数。


然后,要在ffconf.h中进行一些配置(说明:这个主要用于裁剪,通过配置宏定义,可以实现 / 屏蔽相应功能):


// 格式化文件系统

#define _USE_MKFS 1

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

 

// 配置扇区的大小(有多少个字节),特别值得注意的是,两个值不要相等

#define _MIN_SS 512

#define _MAX_SS 4096

接下来就是在主函数中进行测试:


#include "stm32f10x.h"

#include "./usart/bsp_usart.h"

#include "./led/bsp_led.h"

#include "./flash/bsp_spi_flash.h"

#include "ff.h"

 

FATFS fsObject;

FIL fp;

UINT bw;

UINT br;

 

const char wData[] = "FatFs文件系统测试成功!";

char rData[4096] = "";

 

/*

 * 函数名:main

 * 描述  :主函数

 * 输入  :无

 * 输出  :无

 */

int main(void)

{

FRESULT res;

LED_GPIO_Config();

LED_BLUE;

/* 配置串口为:115200 8-N-1 */

USART_Config();

printf("rn 这是一个8Mbyte串行flash(W25Q64)实验 rn");

/* 挂载文件系统,就是初始化硬件GPIO接口和SPI,使能

   第一个参数为文件系统句柄,第二个参数为路径,第三个参数1表示立即挂载 */

res = f_mount(&fsObject, "1:", 1);

printf("tf_mount res = %dn", res);

// 只有当存储介质不存在文件系统时,才进行格式化

if (res == FR_NO_FILESYSTEM)

{

res = f_mkfs("1:", 0, 0); // 格式化存储介质

printf("tf_mkfs res = %dn", res);

// 格式化后要取消挂载,然后再重新挂载文件系统

res = f_mount(NULL, "1:", 1);

res = f_mount(&fsObject, "1:", 1);

printf("tsecond f_mount res = %dn", res);

}

/* 开始测试 */

// 以可读可写权限打开一个文件

res = f_open(&fp, "1:abcd.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE);

printf("tf_open res = %dn", res);

// 如果打开文件成功,就可以写入数据

if (res == FR_OK)

{

res = f_write(&fp, wData, sizeof(wData), &bw);

printf("tbw = %dn", bw);

if (res == FR_OK)

{

f_lseek(&fp, 0); // 把文件的光标移到最开头处

res = f_read(&fp, rData, f_size(&fp), &br);

if (res == FR_OK)

{

printf("t文件内容: %s, br = %dn", rData, br);

}

}

f_close(&fp); // 关闭文件

}

while(1);  

}


串口打印结果如下:

推荐阅读

史海拾趣

Electric Imp Inc.公司的发展小趣事

在物联网设备管理平台的基础上,Electric Imp Inc.公司不断推动技术创新。公司研发团队经过数年的努力,成功研发出了一款基于边缘计算的物联网设备。这款设备具有更高的数据处理能力、更低的延迟和更好的安全性,能够满足更广泛的应用场景。这一技术突破使得公司在物联网领域的技术实力得到了显著提升。

富信半导体(FOSAN)公司的发展小趣事

在电子行业的浪潮中,Electric Imp Inc.公司以其独特的物联网(IoT)解决方案崭露头角。公司创始人是一位资深的电子工程师,他敏锐地捕捉到了物联网市场的巨大潜力。在创业初期,公司面临资金短缺、技术瓶颈等挑战,但创始人带领团队夜以继日地研发,终于推出了第一款基于云计算的物联网设备管理平台。这款产品凭借其易用性、稳定性和可扩展性,迅速获得了市场的认可。

Asia Pacific Microsystems Inc公司的发展小趣事

APM深知在电子行业中,单打独斗很难取得长远的发展。因此,公司开始积极寻求与上下游企业的合作,共同构建完整的产业链。通过与原材料供应商、代工厂商以及终端客户的紧密合作,APM实现了产业链的整合与协同发展。这不仅降低了公司的运营成本,还提高了产品的质量和生产效率,为公司的持续发展奠定了坚实基础。

DBS Microwave Inc公司的发展小趣事

DBS Microwave Inc公司起源于XXXX年,当时由几位志同道合的电子工程师创立。他们共同意识到,随着无线通信技术的飞速发展,微波器件的市场需求将会急剧增长。于是,他们凭借丰富的专业知识和对市场趋势的敏锐洞察,决定专注于研发和生产高质量的微波射频器件。起初,公司面临着资金紧张、市场竞争激烈等诸多挑战,但创始人团队凭借坚韧不拔的精神和对技术的执着追求,逐步在市场上崭露头角。

GSR Technology Ltd公司的发展小趣事

在电子行业的初期,GSR Technology Ltd专注于研发高性能的传感器技术,特别是针对工业自动化领域的GSR(Ground Surveillance Radar,地面监视雷达)技术。通过多年的技术积累和研发创新,公司成功开发出具有高精度、长距离监测能力的GSR系统,填补了市场空白。这一技术突破吸引了众多工业客户的关注,公司迅速获得市场准入,并与多家知名企业建立了长期合作关系。

Corex Intervest Inc公司的发展小趣事

在技术创新和产品创新的基础上,Corex Intervest Inc公司开始积极拓展市场。公司通过参加国际电子展览、与各大电商平台合作等方式,不断提升品牌知名度和影响力。同时,公司还注重与客户的沟通与合作,根据客户需求定制产品方案,赢得了客户的广泛信任和好评。

问答坊 | AI 解惑

74系列芯片资料

本帖最后由 paulhyde 于 2014-9-15 09:01 编辑 大家分享,,,,,,,,,,  …

查看全部问答>

EWB软件简介

本帖最后由 paulhyde 于 2014-9-15 08:59 编辑 内容不是很多,有兴趣的可以看一下  …

查看全部问答>

A Unified Calibration Algorithm for Scattering

A simple algorithm which unifies the calibration procedures for Scattering and Load Pull measurements is proposed. The new technique is particulary useful when measuring non-insertable devices and for on-wafer characterization ...…

查看全部问答>

关于WinCE5.0下WiFi SDIO卡的支持

在WinCE5.0下要添加哪些组件才能支持WiFi? 已经添加了: 还有就是,是不是如果支持了WiFi配置,那么在开机的时候就会弹出一个配置的对话框? 据说只支持English,是吗?有在中文下弄成功的吗?…

查看全部问答>

【USB】插入USB后,怎么阻止PC识别设备,仅仅是充电?

usb 兼充电功能,但与PC连线的时候,PC会枚举识别设备。 如果我仅仅要的是充电功能,此时不需要PC设备设备,怎么去做? ----------- 谢谢!…

查看全部问答>

请高手们帮分析为什么intLock无法锁住中断

公司的一个项目采用MIPS的CPU 发现调用intLock()无效,各中断照样产生 用IDA反汇编出来的代码如下: .text:80050524  # =============== S U B R O U T I N E ======================================= .text:80050524 .text:800505 ...…

查看全部问答>

flashplayer中对MP3音频解码是用LIBMAD吗?

flashplayer中对MP3音频解码是用LIBMAD吗?…

查看全部问答>

钢厂照明配电用接触器触点被烧是什么原因?

钢厂照明配电用接触器触点被烧是什么原因? 我公司最近在一钢厂 照明配电采用LC1-D245M7C交流接触器,型号是按照客户要求来选的。但是,最近老是烧掉交流接触器的主触点。     请教各位高手,造成上述问题的原因是什么?该如何处 ...…

查看全部问答>

我的nandFalsh操作还是有问题,但用IO模拟总线的是可以读出ID

我的nandFalsh操作还是有问题,但用IO模拟总线的是可以读出ID的请问哪位老兄能帮我一下,我全总是按ST的的例子来的。。不知道是哪里出现了问题,,,,我用的FLASH也是跟ST的型号一样。。…

查看全部问答>

STM32的软件复位函数在哪个库文件里?

                                 所谓的SYSRESETREQ位的控制,在手册里没看到关于这个位所在寄存器的说明…

查看全部问答>