STM32 SDIO 挂载 FATFS读写TF卡

参考文章
以下的内容可能需要参考文章
USB重定向printf
STM32 SDIO 读写 TF卡
使用FatFs文件系统读写SD卡

CubeMX配置

在fatfs中勾选SD Card选项
在这里插入图片描述

代码分析

实现几个函数
创建app_flie_operate.c函数

#include "app_flie_operate.h"
#include "usbd_cdc_if.h"
// 定义用于格式化的工作区缓存
BYTE workBuffer[4 * User_Sector];

/*挂载FatFs文件系统*/
void Mount_FatFs(void)
{
    // 挂载文件系统
    FRESULT retUSER = f_mount(&User_FatFs, User_SDPath, 1);
    // 发生错误
    if (retUSER != FR_OK)
    {
        // 没有文件系统,需要格式化
        if (retUSER == FR_NO_FILESYSTEM)
        {
            usb_printf("\r\nNo file system, start formatting\r\n");
            // 创建文件系统
            retUSER = f_mkfs(User_SDPath, FM_FAT32, 0, workBuffer, 4 * User_Sector);
            // 格式化失败
            if (retUSER != FR_OK)
            {
                usb_printf("Formatting failed, error code = %d \r\n", retUSER);
            }
            // 格式化成功
            else
            {
                usb_printf("The formatting is successful, and the mounting starts again\r\n");
                // 有文件系统后重新挂载
                retUSER = f_mount(&User_FatFs, User_SDPath, 1);
                // 挂载失败
                if (retUSER != FR_OK)
                {
                    usb_printf("Error occurred. Error code = %d \r\n", retUSER);
                }
                // 挂载成功
                else
                {
                    usb_printf("*** The file system is mounted successfully ***\r\n");
                }
            }
        }
        // 不是没有文件系统,而是发生其他错误
        else
        {
            usb_printf("Another error occurred, error code = %d \r\n", retUSER);
        }
    }
    // 有文件系统直接挂在成功
    else
    {
        usb_printf("The file system is mounted successfully\r\n");
    }
}

/*获取磁盘信息并在LCD上显示*/
void FatFs_GetDiskInfo(void)
{
    FATFS *fs;
    // 定义剩余簇个数变量
    DWORD fre_clust;
    // 获取剩余簇个数
    FRESULT res = f_getfree("0:", &fre_clust, &fs);
    // 获取失败
    if (res != FR_OK)
    {
        usb_printf("f_getfree() error\r\n");
        return;
    }
    usb_printf("\r\n*** FAT disk info ***\r\n");

    // 总的扇区个数
    DWORD tot_sect = (fs->n_fatent - 2) * fs->csize;

    // 剩余的扇区个数 = 剩余簇个数 * 每个簇的扇区个数
    DWORD fre_sect = fre_clust * fs->csize;

    // 对于SD卡和U盘, _MIN_SS=512字节
#if _MAX_SS == _MIN_SS
    // SD卡的_MIN_SS固定为512,右移11位相当于除以2048
    // 剩余空间大小,单位:MB,用于SD卡,U盘
    DWORD freespace = (fre_sect >> 11);
    // 总空间大小,单位:MB,用于SD卡,U盘
    DWORD totalSpace = (tot_sect >> 11);
#else
    // Flash存储器,小容量
    // 剩余空间大小,单位:KB
    DWORD freespace = (fre_sect * fs->ssize) >> 10;
    // 总空间大小,单位:KB
    DWORD totalSpace = (tot_sect * fs->ssize) >> 10;
#endif

    // FAT类型
    usb_printf("FAT type = %d\r\n", fs->fs_type);
    usb_printf("[1=FAT12,2=FAT16,3=FAT32,4=exFAT]\r\n");

    // 扇区大小,单位字节
    usb_printf("Sector size(bytes) = ");
    // SD卡固定512字节
#if _MAX_SS == _MIN_SS
    usb_printf("%d\r\n", _MIN_SS);
#else
    // FLASH存储器
    usb_printf("%d\r\n", fs->ssize);
#endif

    usb_printf("Cluster size(sectors) = %d\r\n", fs->csize);
    usb_printf("Total cluster count = %ld\r\n", fs->n_fatent - 2);
    usb_printf("Total sector count = %ld\r\n", tot_sect);

    // 总空间
#if _MAX_SS == _MIN_SS
    usb_printf("Total space(MB) = %ld\r\n", totalSpace);
#else
    usb_printf("Total space(KB) = %ld\r\n", totalSpace);
#endif

    // 空闲簇数量
    usb_printf("Free cluster count = %ld\r\n", fre_clust);
    // 空闲扇区数量
    usb_printf("Free sector count = %ld\r\n", fre_sect);

    // 空闲空间
#if _MAX_SS == _MIN_SS
    usb_printf("Free space(MB) = %ld\r\n", freespace);
#else
    usb_printf("Free space(KB) = %ld\r\n", freespace);
#endif

    usb_printf("Get FAT disk info OK\r\n");
}

/*创建文本文件*/
void FatFs_WriteTXTFile(TCHAR *filename, uint16_t year, uint8_t month, uint8_t day)
{
    FIL file;
    usb_printf("\r\n*** Creating TXT file: %s ***\r\n", filename);

    FRESULT res = f_open(&file, filename, FA_CREATE_ALWAYS | FA_WRITE);
    // 打开/创建文件成功
    if (res == FR_OK)
    {
        // 字符串必须有换行符"\n"
        TCHAR str[] = "Line1: Hello, FatFs***\n";
        // 不会写入结束符"\0"
        f_puts(str, &file);

        usb_printf("Write file OK: %s\r\n", filename);
    }
    else
    {
        usb_printf("Open file error,error code: %d\r\n", res);
    }
    // 使用完毕关闭文件
    f_close(&file);
}

/*读取一个文本文件的内容*/
void FatFs_ReadTXTFile(TCHAR *filename)
{
    usb_printf("\r\n*** Reading TXT file: %s ***\r\n", filename);

    FIL file;
    // 以只读方式打开文件
    FRESULT res = f_open(&file, filename, FA_READ);
    // 打开成功
    if (res == FR_OK)
    {
        // 读取缓存
        TCHAR str[100];
        // 没有读到文件内容末尾
        while (!f_eof(&file))
        {
            // 读取1个字符串,自动加上结束符”\0”
            f_gets(str, 100, &file);
            usb_printf("%s", str);
        }
        usb_printf("\r\n");
    }
    // 如果没有该文件
    else if (res == FR_NO_FILE)
        usb_printf("File does not exist\r\n");
    // 打开失败
    else
        usb_printf("f_open() error,error code: %d\r\n", res);
    // 关闭文件
    f_close(&file);
}

/*扫描和显示指定目录下的文件和目录*/
void FatFs_ScanDir(const TCHAR *PathName)
{
    DIR dir;     // 目录对象
    FILINFO fno; // 文件信息
    // 打开目录
    FRESULT res = f_opendir(&dir, PathName);
    // 打开失败
    if (res != FR_OK)
    {
        // 关闭目录,直接退出函数
        f_closedir(&dir);
        usb_printf("\r\nf_opendir() error,error code: %d\r\n", res);
        return;
    }

    usb_printf("\r\n*** All entries in dir: %s ***\r\n", PathName);
    // 顺序读取目录中的文件
    while (1)
    {
        // 读取目录下的一个项
        res = f_readdir(&dir, &fno);
        // 文件名为空表示没有多的项可读了
        if (res != FR_OK || fno.fname[0] == 0)
            break;
        // 如果是一个目录
        if (fno.fattrib & AM_DIR)
        {
            usb_printf("DIR: %s\r\n", fno.fname);
        }
        // 如果是一个文件
        else
        {
            usb_printf("FILE: %s\r\n", fno.fname);
        }
    }
    // 扫描完毕,关闭目录
    usb_printf("Scan dir OK\r\n");
    f_closedir(&dir);
}

/*获取一个文件的文件信息*/
void FatFs_GetFileInfo(TCHAR *filename)
{
    usb_printf("\r\n*** File info of: %s ***\r\n", filename);

    FILINFO fno;
    // 检查文件或子目录是否存在
    FRESULT fr = f_stat(filename, &fno);
    // 如果存在从fno中读取文件信息
    if (fr == FR_OK)
    {
        usb_printf("File size(bytes) = %ld\r\n", fno.fsize);
        usb_printf("File attribute = 0x%x\r\n", fno.fattrib);
        usb_printf("File Name = %s\r\n", fno.fname);
        // 输出创建/修改文件时的时间戳
        FatFs_PrintfFileDate(fno.fdate, fno.ftime);
    }
    // 如果没有该文件
    else if (fr == FR_NO_FILE)
        usb_printf("File does not exist\r\n");
    // 发生其他错误
    else
        usb_printf("f_stat() error,error code: %d\r\n", fr);
}

/*删除文件*/
void FatFs_DeleteFile(TCHAR *filename)
{
    usb_printf("\r\n*** Delete File: %s ***\r\n", filename);
    FIL file;
    // 打开文件
    FRESULT res = f_open(&file, filename, FA_OPEN_EXISTING);
    if (res == FR_OK)
    {
        // 关闭文件
        f_close(&file);
        usb_printf("open successfully!\r\n");
    }
    // 删除文件
    res = f_unlink(filename);
    // 删除成功
    if (res == FR_OK)
    {
        usb_printf("The file was deleted successfully!\r\n");
    }
    // 删除失败
    else
    {
        usb_printf("File deletion failed, error code:%d\r\n", res);
    }
}

/*打印输出文件日期*/
void FatFs_PrintfFileDate(WORD date, WORD time)
{
    usb_printf("File data = %d/%d/%d\r\n", ((date >> 9) & 0x7F) + 1980, (date >> 5) & 0xF, date & 0x1F);
    usb_printf("File time = %d:%d:%d\r\n", (time >> 11) & 0x1F, (time >> 5) & 0x3F, time & 0x1F);
}

创建app_flie_opreate.h

#ifndef   __APP_FILE_OPERATE_H__
#define   __APP_FILE_OPERATE_H__

#include "main.h"
#include "FatFs.h"
#include "stdio.h"

/*定义自己的存储设备*/
/*用户存储设备扇区字节数*/
#define User_Sector 4096
/*用户存储设备FatFS对象*/
#define User_FatFs SDFatFS
/*用户存储设备卷路径*/
#define User_SDPath SDPath

/*函数声明*/
void Mount_FatFs(void);
void FatFs_GetDiskInfo(void);
void FatFs_ScanDir(const TCHAR *PathName);
void FatFs_ReadTXTFile(TCHAR *filename);
void FatFs_WriteTXTFile(TCHAR *filename, uint16_t year, uint8_t month, uint8_t day);
void FatFs_GetFileInfo(TCHAR *filename);
void FatFs_DeleteFile(TCHAR *filename);
void FatFs_PrintfFileDate(WORD date, WORD time);

#endif

创建以下函数

/**
 * @brief SD卡文件系统测试
 * @param  
 */
void SD_FATFS_TEST_Task(void )
{
	HAL_Delay(5000);
    HAL_StatusTypeDef status;   
    status = HAL_SD_Init(&hsd1); /* 初始化 */
	if(status != HAL_OK)
	{
		usb_printf("SD card initialize failed!\n");
		while(1) 
		{
			HAL_Delay(1000);
			usb_printf("SD card initialize failed!\n");
		}
	}
    HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&hsd1);
    if(state == HAL_SD_CARD_TRANSFER)
    {
        HAL_SD_GetCardCID(&hsd1, &SD_CardCID);
        usb_printf("\nInitialize SD card sucessfully!\r\n");
        usb_printf("\nSD card information\r\n");
        usb_printf("\nCapacity              :%llu\r\n", ((unsigned long long)hsd1.SdCard.BlockSize*hsd1.SdCard.BlockNbr));
        usb_printf("\nBlockSize             :%d\r\n", hsd1.SdCard.BlockSize);
        usb_printf("\nRCA                   :%d\r\n", hsd1.SdCard.RelCardAdd);
        usb_printf("\nCardType              :%d\r\n", hsd1.SdCard.CardType);
        usb_printf("\nManufacturerID        :%d\r\n", SD_CardCID.ManufacturerID);			
    }
    else
    {		
        usb_printf("\nSD card initialize failed.\n");
    }	
    Mount_FatFs();
    while (1)
    {
        /*按键1被按下*/
        if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET)
        {
            HAL_Delay(50);
            if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET)
            {
                FatFs_ScanDir("0:/");
                while (!HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin))
                    ;
            }
        }

        /*按键KEY2被按下*/
        if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET)
        {
            HAL_Delay(50);
            if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == GPIO_PIN_RESET)
            {
                FatFs_WriteTXTFile("test.txt", 2024, 5, 30);
                while (!HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin))
                    ;
            }
        }

        /*按键KEY3被按下*/
        if (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET)
        {
            HAL_Delay(50);
            if (HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin) == GPIO_PIN_RESET)
            {
                FatFs_ReadTXTFile("test.txt");
                FatFs_GetFileInfo("test.txt");
                while (!HAL_GPIO_ReadPin(KEY3_GPIO_Port, KEY3_Pin))
                    ;
            }
        }

    }
    
}

main.c文件中调用

实验结果

在这里插入图片描述
显示挂载成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cat_milk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值