概述
1首先用STM32CUBEMX配置
如下图:
2重点修改user_diskio.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file user_diskio.c
* @brief This file includes a diskio driver skeleton to be completed by the user.
******************************************************************************
* @attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
#ifdef USE_OBSOLETE_USER_CODE_SECTION_0
/*
* Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
* To be suppressed in the future.
* Kept to ensure backward compatibility with previous CubeMx versions when
* migrating projects.
* User code previously added there should be copied in the new user sections before
* the section contents can be deleted.
*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
#endif
/* USER CODE BEGIN DECL */
/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include "ff_gen_drv.h"
/* Private typedef -----------------------------------------------------------*/
#include "w25qxx.h"
#define FLASH_SECTOR_SIZE 4096 //每个扇区4K
#define FLASH_SECTOR_COUNT 256*16 //W25Q128有256block,每个block16扇区
#define FLASH_BLOCK_SIZE 65536 //16*4096
/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Disk status */
static volatile DSTATUS Stat = STA_NOINIT;
/* USER CODE END DECL */
/* Private function prototypes -----------------------------------------------*/
DSTATUS USER_initialize (BYTE pdrv);
DSTATUS USER_status (BYTE pdrv);
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
#if _USE_WRITE == 1
DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
#endif /* _USE_IOCTL == 1 */
Diskio_drvTypeDef USER_Driver =
{
USER_initialize,
USER_status,
USER_read,
#if _USE_WRITE
USER_write,
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
USER_ioctl,
#endif /* _USE_IOCTL == 1 */
};
/* Private functions ---------------------------------------------------------*/
/**
* @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;
return RES_OK;
/* USER CODE END INIT */
}
/**
* @brief Gets Disk Status
* @param pdrv: Physical drive number (0..)
* @retval DSTATUS: Operation status
*/
DSTATUS USER_status (
BYTE pdrv /* Physical drive number to identify the drive */
)
{
/* USER CODE BEGIN STATUS */
Stat = STA_NOINIT;
return RES_OK;
/* USER CODE END STATUS */
}
/**
* @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 */
for(;count>0;count--){
W25QXX_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
sector++;
buff+=FLASH_SECTOR_SIZE;
}
return RES_OK;
/* USER CODE END READ */
}
/**
* @brief Writes Sector(s)
* @param pdrv: Physical drive number (0..)
* @param *buff: Data to be written
* @param sector: Sector address (LBA)
* @param count: Number of sectors to write (1..128)
* @retval DRESULT: Operation result
*/
#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 */
for(;count>0;count--){
W25QXX_Write((uint8_t *)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
sector++;
buff+=FLASH_SECTOR_SIZE;
}
return RES_OK;
/* USER CODE END WRITE */
}
#endif /* _USE_WRITE == 1 */
/**
* @brief I/O control operation
* @param pdrv: Physical drive number (0..)
* @param cmd: Control code
* @param *buff: Buffer to send/receive control data
* @retval DRESULT: Operation result
*/
#if _USE_IOCTL == 1
DRESULT USER_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
/* USER CODE BEGIN IOCTL */
DRESULT res = RES_ERROR;
switch(cmd){
case CTRL_SYNC:
res = RES_OK;
break;
case GET_SECTOR_SIZE:
*(WORD*)buff = FLASH_SECTOR_SIZE;
res = RES_OK;
break;
case GET_BLOCK_SIZE:
*(WORD*)buff = (WORD)FLASH_BLOCK_SIZE;
res = RES_OK;
break;
case GET_SECTOR_COUNT:
*(DWORD*)buff = FLASH_SECTOR_COUNT;
res = RES_OK;
break;
default:
res = RES_PARERR;
break;
}
return res;
/* USER CODE END IOCTL */
}
#endif /* _USE_IOCTL == 1 */
3在main函数添加代码并测试
BYTE work[4096];
BYTE WriteBuffer[]= "hello world123";
BYTE ReadBuffer[1024] = {0};
void FATFS_MOUNT(void){
printf("FATFS START");
retUSER = f_mount(&USERFatFS, USERPath, 1);
if(retUSER ==FR_NO_FILESYSTEM)
{
printf("fmkfs");
/* 格式化 */
retUSER = f_mkfs(USERPath, 1, 0, work, sizeof(work));
if(retUSER == FR_OK)
{
printf("fmkfs success");
/* 格式化后,先取消挂载 */
retUSER = f_mount(NULL, USERPath, 1);
/* 重新挂载 */
retUSER = f_mount(&USERFatFS,USERPath, 1);
}
else
{
printf("fmkfs error");
while(1);
}
}
else if(retUSER != FR_OK)
{
printf("mount error");
while(1);
}
else
{
printf("mount succes");
}
}
void FATFS_WRITE_TEST(void){
retUSER = f_open(&USERFile, "1:/data.txt", FA_OPEN_ALWAYS | FA_WRITE);
if(retUSER){
printf("open error");
while(1);
}
else
printf("open success");
retUSER = f_write(&USERFile, WriteBuffer, sizeof(WriteBuffer), &fnum);
if(retUSER){
printf("write error");
while(1);
}
else
printf("write success");
retUSER = f_close(&USERFile);
//读
void FAFTF_READ_FILE_TEST(void){
retUSER = f_open(&USERFile, "1:/data.txt", FA_READ);
if(retUSER){
printf("open error");
while(1);
}
else
printf("open success");
retUSER = f_read(&USERFile, ReadBuffer, 100, &fnum);
if(retUSER){
printf("read error");
while(1);
}
else
printf("read success");
retUSER = f_close(&USERFile);
}
int main(void)
{
MX_SPI1_Init();
W25QXX_Init();
MX_FATFS_Init();
FATFS_MOUNT();
HAL_Delay(1000);
FATFS_WRITE_TEST();
HAL_Delay(1000);
FAFTF_READ_FILE_TEST();
f_mount(NULL, USERPath, 1);
while(1);
}
用LCD显示过程。
经过测试能用,但是不推荐用FATFS管理spi flash。
因为使用FATFS管理上没有擦写均衡功能。spi flash寿命有限。
推荐使用LittleFS文件管理系统。
FATFS的优势在于能用电脑查看,适用于TF卡等能插在电脑上看的存储器。
最后
以上就是傲娇小霸王为你收集整理的FATFS文件系统管理W25Q128的全部内容,希望文章能够帮你解决FATFS文件系统管理W25Q128所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复