一:文件系统的知识分享:
FATFS 是一个完全免费开源的 FAT 文件系统模块,专门为小型的嵌入式系统而设计。它完全用标准C 语言编写,所以具有良好的硬件平台独立性,
可以移植到 8051、PIC、AVR、SH、Z80、H8、ARM 等系列单片机上而只需做简单的修改。它支持 FATI2、FATI6 和 FAT32,
支持多个存储媒介;有独立的缓冲区,可以对多个文件进行读/写,并特别对8位单片机和 16 位单片机做了优化。
FATFS 的特点有:
Windows 兼容的 FAT 文件系统(支持 FAT12/FAT16/FAT32)
与平台无关,移植简单
代码量少、效率高
多种配置选项
支持多卷(物理驱动器或分区,最多10个卷)
多个 ANSIOEM 代码页包括 DBCS
支持长文件名、ANSI/OEM 或 Unicode
支持 RTOS
支持多种扇区大小
只读、最小化的 API和 IO 缓冲区等
最顶层是应用层,使用者无需理会FATFS 的内部结构和复杂的 FAT 协议,只需要调用FATFS 模块提供给用户的一系列应用接口函数,如fopen,f read,f write 和f close 等,就可以像在 PC 上读/写文件那样简单。
中间层 FATFS 模块,实现了 FAT 文件读/写协议。FATFS 模块提供的是 c 和 fh。除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。
二:STM32 cube MX软件配置如下所示:
2.1 修改程序的堆栈大小
2.2 使能软件的文件系统的底层驱动部分
配置如上图所示,直接生成代码即可。
三:软件代码编写:
3.1 对于存储芯片的选择:
/** * @brief Initializes a Drive * @param pdrv: Physical drive number (0..) * @retval DSTATUS: Operation status */ DSTATUS USER_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { /* USER CODE BEGIN INIT */ Stat = STA_NOINIT; switch (pdrv) { case 1: // SD Stat = RES_PARERR; break; case 0: // flash Stat = RES_OK; break; default: Stat = RES_PARERR; } return Stat; /* USER CODE END INIT */ }
3.2 添加 写入文件的操作:
/** * @brief Reads Sector(s) * @param pdrv: Physical drive number (0..) * @param *buff: Data buffer to store read data * @param sector: Sector address (LBA) * @param count: Number of sectors to read (1..128) * @retval DRESULT: Operation result */ DRESULT USER_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 */ ) { /* USER CODE BEGIN READ */ if (pdrv == 0) { W25QXX_Read((uint8_t *)buff ,sector * 4096, count * 4096); return RES_OK; } else { return RES_PARERR; } /* USER CODE END READ */ }
3.3 添加读取文件的操作:
#if _USE_WRITE == 1 DRESULT USER_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 */ ) { /* USER CODE BEGIN WRITE */ /* USER CODE HERE */ if (pdrv == 0) { W25QXX_Erase_Sector(sector ); W25QXX_Write_NoCheck((uint8_t *)buff,sector * 4096, count * 4096); return RES_OK; } else { return RES_PARERR; } /* USER CODE END WRITE */ }
四:测试读取的函数如下所示:
这里我创建一个 以EEPW为名字的txt文件:
void FATFS_FLASH_Test(void) { static FATFS fs; //文件系统对象 static FIL fnew; //文件对象 BYTE FATFS_Wr_Buff[128] = "hi.WWW.EEPW.COM.CN! autor:by :keyboard !!!!!\r\n"; // 写缓冲区 BYTE FATFS_Rd_Buff[128] = {0}; // 读缓冲区 UINT fnum; // 成功读写数量 FRESULT res; // 返回 printf("\r\n\r\n------------------FLASH FATFS TEST------------------\r\n\r\n"); res = f_mount(&fs, "0:", 1); if (res == FR_NO_FILESYSTEM) { printf("no file system,begin mkfs\r\n"); res = f_mkfs("0:", 0, 0); //格式化 SPI的W25Q64 if (res == FR_OK) { printf("file system mkfs ok\r\n"); // 格式化成功后先取消,再重新挂载 res = f_mount(NULL, "0:", 1); printf("cancel mount ok:%d\r\n", res); res = f_mount(&fs, "0:", 1); printf("re-mount ok:%d\r\n", res); } else { printf("failed mount\r\n"); } } else { printf("file system alreadly existed.\r\n"); } printf("\r\n\r\n-------------------FATFS write test-------------------\r\n"); // 打开文件,文件不存在的话,则先新建文件在打开 res = f_open(&fnew, "EEPW.txt", FA_CREATE_ALWAYS | FA_WRITE); if (res == FR_OK) printf("open or create EEPW.txt ok.\r\n"); else printf("open or create file failed\r\n"); // 写入测试buffer 到文件系统内 res = f_write(&fnew, FATFS_Wr_Buff, sizeof(FATFS_Wr_Buff), &fnum); if (res == FR_OK) printf("write to EEPW.txt:\r\n%s", FATFS_Wr_Buff); else printf("failed to write EEPW.txt,code: %d!\r\n", res); f_close(&fnew); // 完成操作后,需要关闭文件,这一操作很重要 HAL_Delay(200); printf("\r\n-------------------FATFS read test-------------------\r\n\r\n"); // 打开文件,读方式打开已经创建的文件 res = f_open(&fnew, "EEPW.txt", FA_OPEN_EXISTING | FA_READ); if (res != FR_OK) { printf("open EEPW.txt failed\r\n"); return; } //读取文件测试 res = f_read(&fnew, FATFS_Rd_Buff, sizeof(FATFS_Rd_Buff), &fnum); if (res != FR_OK) { printf("read file failed\r\n"); return; } printf("read file data:\r\n%s\r\n", FATFS_Rd_Buff); f_close(&fnew); // 读取完毕后,也需要关闭文件 }
五:测试图如下所示:
实测软件代码功能正常,可以正常使用文件系统的格式写入和读取文件。