FatFs移植到STM32(SD卡)

目录

一、简介

二、源码下载

三、移植条件

1、芯片参数

四、源码结构分析

五、配置文件重要参数说明

1、配置扇区大小

2、配置逻辑设备个数

3、配置格式化文件系统接口

六、diskio.c代码适配

1、disk_status接口

2、disk_initialize接口

3、disk_read接口

4、disk_write接口

5、disk_ioctl接口

七、SD卡驱动实现

八、用户Demo

1、挂载设备

2、文件操作

3、运行截图


一、简介

FatFs是免费,开源的轻量级 文件系统,纯c实现,移植简单

二、源码下载

GitHub - abbrev/fatfs: FatFs - Generic FAT File System Module

三、移植条件

1、芯片参数

note:如遇挂载的失败,裸机请记得调整栈空间。

芯片类型:STM32F103VET6

flash大小为512KB,RAM大小 64KB

8GB大小SD卡。

本例中使用TFT屏幕自带SD卡硬件电路,使用SPI模式驱动SD卡

四、源码结构分析

 用户移植适配的工作全部在diskio.c中完成。

五、配置文件重要参数说明

1、配置扇区大小

#define FF_MIN_SS        512
#define FF_MAX_SS        512

如果只需要挂载一个文件系统,以上两个值设置一样即可,本例中所用SD卡扇区大小为512,所以均设置为512。

如果需要挂载一个以上文件系统且两个设备扇区大小不同,以上两值设置范围要涵盖多个设备扇区范围。disk_ioctl接口需要提供GET_SECTOR_SIZE接口。

2、配置逻辑设备个数

(本例中使用DEV_MMC, 所以设备数配置为2, 盘符使用 1: 盘符)

#define FF_VOLUMES        2 

3、配置格式化文件系统接口

#define FF_USE_MKFS        1

该字段配置为1,可以使用f_mkfs接口来格式化空白SD卡
 

六、diskio.c代码适配

note:留意下各个接口返回值,小心返回错误。

1、disk_status接口

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = RES_OK;

	switch (pdrv) {

	case DEV_MMC :
		stat = STA_NOINIT;
		stat &= ~STA_NOINIT;
		// translate the reslut code here
		return stat;
	}
	return STA_NOINIT;
}

2、disk_initialize接口

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	DSTATUS stat = RES_OK;
	int result;

	switch (pdrv) {
	case DEV_MMC :
		result = b_sd_init();
		if(result)
		{
			b_sd_set_speed(SPI_BAUDRATEPRESCALER_256);
			b_sd_read_write_byte(0XFF);
			b_sd_set_speed(SPI_BAUDRATEPRESCALER_2);
		}
		// translate the reslut code here
		return stat;
	}
	return STA_NOINIT;
}

b_sd_init 为sd卡初始化接口、b_sd_set_speed 为设置spi速度接口、b_sd_read_write_byte 为spi读写单个字节接口,均会在下文给出。

3、disk_read接口

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	LBA_t sector,	/* Start sector in LBA */
	UINT count		/* Number of sectors to read */
)
{
	DRESULT res = RES_OK;
	int ret;

	switch (pdrv) {
	case DEV_MMC :
		// translate the arguments here
		ret = b_sd_read_sector(sector, count, buff, 0XFF);
		if(ret != 0)
		{
			res = RES_ERROR;
		}
		// translate the reslut code here
		return res;
	}
	return RES_PARERR;
}

b_sd_read_sector 为sd卡的读扇区数据接口,会在下文给出。

4、disk_write接口

DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	LBA_t sector,		/* Start sector in LBA */
	UINT count			/* Number of sectors to write */
)
{
	DRESULT res = RES_OK;
	int ret;
	switch (pdrv) {

	case DEV_MMC :
		// translate the arguments here
		b_sd_set_speed(SPI_BAUDRATEPRESCALER_256);
		ret = b_sd_write_sector(sector, count, (u8*)buff, 0XFF);
		b_sd_set_speed(SPI_BAUDRATEPRESCALER_2);
		if(ret != 0)
		{
			res = RES_ERROR;
		}
		// translate the reslut code here
		return res;
	}
	return RES_PARERR;
}

b_sd_write_sector 为sd卡写扇区数据接口,会在下文给出。

5、disk_ioctl接口

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	DRESULT res = RES_OK;
	switch (pdrv) {

	case DEV_MMC :

		// Process of the command for the MMC/SD card
		switch(cmd)
		{	
			case CTRL_SYNC :
			{
				b_sd_sync_data();
				res = RES_OK;
			}
			break;
			case CTRL_TRIM:
			{
				res = RES_OK;
			}break;
			case GET_SECTOR_COUNT:
			{
				*(int*)buff = b_sd_get_sector_number();
			}break;
			case GET_SECTOR_SIZE:
			{
				*(int*)buff = b_sd_get_sector_size();
			}break;
			case GET_BLOCK_SIZE:
			{
				//*(int*)buff = b_sd_get_block_size();
				*(int*)buff = 8;
			}break;
		}
		return res;
	}
	return RES_PARERR;
}

b_sd_get_sector_number 为获取sd卡扇区个数接口,b_sd_get_sector_size为获取sd卡获取扇区大小(512字节接口),会在下文给出。

七、SD卡驱动实现

sd卡驱动实现请参考:

stm32读写SD卡(SPI模式)_spi sd卡_BIN-XYB的博客-优快云博客

 或

stm32读写SD卡(SDIO模式)-优快云博客

八、用户Demo

note:s32\u32\u16\u8等为自定义实现,如报错,请按需修改

1、挂载设备

#include "ff.h"

#define DISK_SD       "1:"

static int phase1_sd_fs_init(void)
{
    static FATFS sd_fs;
    u32 ret = 0;
    MKFS_PARM opt = {0};
    opt.fmt = FM_FAT;
    static u8 work_buf[512] = {0};
    ret = f_mount(&sd_fs, DISK_SD, 1);
    if(ret != FR_OK)
    {
        switch(ret)
        {
            case FR_NO_FILESYSTEM:
            {
                ret = f_mkfs(DISK_SD, &opt, work_buf, sizeof(work_buf));
            }break;
            case FR_MKFS_ABORTED:
            {
                ret = f_mkfs(DISK_SD, &opt, work_buf, sizeof(work_buf));
            }break;
        }
    }
    if(ret != 0)
    {
        LOG_ERROR("sd fs f_mkfs fail(%d)\r\n", ret);
    }
    else
    {
        LOG_INFO("sd fs f_mkfs succ\r\n");
    }
    return ret;
}

2、文件操作

#define USER_FILE_NAME "1:/data.txt"
s32 b_demo_user_fs(void)
{
    FIL fp;
    u32 real_write_num = 0;
    
    FRESULT ret = f_open(&fp, USER_FILE_NAME, FA_CREATE_ALWAYS | FA_WRITE | FA_READ);
    if(ret != FR_OK)
    {
        LOG_ERROR("f_open fail:%s\r\n", USER_FILE_NAME);
        return -1;
    }

    u8 *test_w_b = "fs test write data";
    ret = f_write(&fp, test_w_b, strlen(test_w_b), &real_write_num);
    if(ret != FR_OK)
    {
        LOG_ERROR("f_open fail:%d\r\n", ret );
        return -1;
    }
    LOG_INFO("write len:%d\r\n", real_write_num);
    LOG_INFO("write data:%s\r\n", test_w_b);
    
    ret = f_close(&fp);
    if(ret != FR_OK)
    {
        LOG_ERROR("f_close fail:%d\r\n", ret);
        return -1;
    }

    u32 real_read_num = 0;
    u8 test_r_b[100] = {0};
    ret = f_open(&fp, USER_FILE_NAME, FA_READ);
    if(ret != FR_OK)
    {
        LOG_ERROR("f_open fail:%s\r\n", USER_FILE_NAME);
        return -1;
    }

    ret = f_read(&fp, test_r_b, 100, &real_read_num);
    if(ret != FR_OK)
    {
        LOG_ERROR("f_read fail:%d\r\n", ret);
        return -1;
    }
    LOG_INFO("read len:%d\r\n", real_read_num);
    LOG_INFO("read data:%s\r\n", test_r_b);

    ret = f_close(&fp);
    if(ret != FR_OK)
    {
        LOG_ERROR("f_close fail:%d\r\n", ret);
        return -1;
    }
    return 0;
}

3、运行截图

 

### STM32 使用 FatFS 文件系统读写 SD #### 创建工程并配置CubeMX 为了使STM32能够通过FatFS文件系统SD交互,首先需要利用STM32CubeMX工具来初始化项目设置。选择合适的微控制器型号,并启用SPI接口用于连接SD模块。同时激活外部中断线以便检测片插入/移除事件[^1]。 #### 添加必要的软件组件 在生成的工程项目中加入FatFS库的支持。这通常意味着要将`ff.c`, `ff.h`, `diskio.c`, 和其他关联头文件复制到指定目录下。对于具体的硬件平台而言,还需要提供底层驱动程序以支持特定存储介质的操作——这里即是指向SD的SPI通信层实现[^2]。 #### 修改主函数(main.c) 编辑入口文件`main.c`,定义全局变量指向工作区缓冲区以及根路径字符串;编写初始化序列确保设备准备就绪之后再调用任何fatfs API 函数前完成挂载操作: ```c #include "ff.h" // ... other includes... FATFS fs; /* File system object */ char path[4]; /* Mount point */ int main(void){ HAL_Init(); SystemClock_Config(); // 配置系统时钟 MX_GPIO_Init(); // 初始化GPIO端口 MX_SPIx_Init(); // 初始化SPI外设 (替换为实际使用的SPI编号) f_mount(&fs, "", 0); // 尝试挂载卷 } ``` #### 实现基本功能测试 下面给出一段简单的例子展示怎样打开现有文本文件或将新内容保存至磁盘内: ```c FIL file; UINT bytes_written; if(f_open(&file,"test.txt",FA_READ | FA_WRITE| FA_OPEN_APPEND)==FR_OK){ const char *data="This is a test string."; if(f_write(&file,data,strlen(data),&bytes_written)!= FR_OK || strlen(data) != bytes_written){ Error_Handler(__FILE__,__LINE__); } f_close(&file); }else{ Error_Handler(__FILE__,__LINE__); } void Error_Handler(char* file,int line){ while(1){} // 错误处理逻辑可自定义扩展 } ``` 上述代码片段展示了如何追加模式打开名为`test.txt`的文件并向其中添加一些字符数据。如果遇到错误,则进入死循环等待调试介入[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值