医保和社保有什么区别| 里正是什么官| 逍遥丸的功效和作用是什么| 一个永一个日念什么| 霉菌阳性是什么意思| 12月10日什么星座| 南瓜可以做什么美食| 唐卡是什么| 孕反什么时候结束| 胆酷醇高有什么危害| 风湿属于什么科| 左眼跳代表什么| 肛门疼是什么原因| 什么的骆驼| 子宫为什么长肌瘤| 右眼一直跳是什么原因| 痔疮用什么药膏最好| 什么动物吃蚊子| 吃什么才能减肥最快| 冰心的原名是什么| 肾低密度灶是什么意思| hay什么意思| 3月24日什么星座| peni是什么意思| 脑梗什么原因导致的| yl是什么牌子| 卧推80公斤什么水平| 包茎不割会有什么影响| 2015属什么生肖| 一什么新月| notebook什么意思| hbv是什么意思| 爱好是什么意思| 梦到和别人打架是什么意思| 77年五行属什么| daily是什么意思| 脑卒中是什么病| 谷氨酰基转移酶低是什么原因| 什么是亲子鉴定| 唐卡是什么| 1980年是什么年| iqr是什么意思| 敛是什么意思| 门可罗雀是什么意思| 无缘无故流鼻血是什么原因| 宫颈醋酸白色上皮是什么病变| 黄什么什么| 益生菌有什么好处| 梦到自己头发白了是什么意思| 蛋白尿是什么原因引起的| 阴囊上长了几根白毛是什么原因| 栩是什么意思| 草莓是什么季节| 蜗牛有什么特点| 茶减一笔是什么字| 家的含义是什么| 纵隔子宫是什么意思| 什么是人| 排异反应是什么意思| 勤代表什么生肖| 抓阄什么意思| 子宫内膜厚有什么症状| 书签是什么| 嗓子干痒吃什么药效果好| 高铁上不能带什么东西| 微字五行属什么| 为什么会突然长智齿| 白质脱髓鞘是什么病| 草龟吃什么食物| 马后面是什么生肖| 雌二醇测定是什么检查| 什么的大叫| 什么是化学| lining是什么意思| 总胆固醇什么意思| 沈殿霞为什么地位高| 夏季吃什么好| 吉利丁片是什么东西| 叔叔的儿子叫什么| 非凡是什么意思| 吃什么食物增加黑色素| 羸弱什么意思| 1991年五行属什么| 仪仗队是什么意思| 同甘共苦什么意思| 头皮痒是什么原因| 路上行人匆匆过是什么歌| 苹果6和苹果6S有什么区别| 两个人背靠背是什么牌子| 什么乐器最好学| 什么情况需要打破伤风| 6月30日是什么节日| 南枝是什么意思| 借鸡生蛋是什么意思| 张飞穿针歇后语下一句是什么| 痱子是什么样的图片| 尿酸高适合喝什么茶| 指甲弯曲是什么原因| 邂逅什么意思| 球镜是什么意思| 插队是什么意思| 舌炎是什么原因引起的怎样治疗| 慢性肠炎用什么药| 双子座和什么座最配| 贫血吃什么可以补血| 地下恋是什么意思| 什么驴技穷成语| 让我爱你然后把我抛弃是什么歌| 乳房胀痛什么原因| 尿急尿痛吃什么药| 家里为什么会有隐翅虫| 红枣和什么不能一起吃| 甲状腺4a类什么意思| 为什么会得灰指甲| 熟地黄有什么功效| 青柑是什么| 身体动不动就出汗是什么原因| 来月经小腹痛是什么原因| 马子什么意思| 乳腺挂什么科| 罗嘉良为什么娶苏岩| 狐狸和乌鸦告诉我们什么道理| 用减一笔是什么字| 公因数是什么意思| 高胆固醇血症是什么病| 肚子疼应该挂什么科| 外阴长水泡是什么原因| 蛔虫是什么| dcr是什么意思| 亲故是什么意思| 咳嗽吐黄痰是什么原因| 努尔哈赤姓什么| 今晚吃什么| 散瞳后需要注意什么| 7月13日什么星座| 女人吃维生素b有什么好处| 贫血到什么程度会晕倒| 瘰疬是什么病| 胸口疼应该挂什么科| 大树像什么| ABB式的词语有什么| 印劫是什么意思| 心什么如什么的成语| 冲正什么意思| 虚火牙痛吃什么药效果最快| 自控能力是什么意思| 的意思是什么| 银饰变黑是什么原因| belkin是什么牌子| 周杰伦英文名叫什么| 地盆是一种什么病| 吃豆腐什么意思| 瓦是什么的单位| 养猫需要准备什么东西| 养老院护工都做些什么| 高血脂吃什么| 银行卡为什么会被冻结| 宝宝益生菌什么时候吃最好| 遮羞布是什么意思| 子宫糜烂用什么药| 5月21日是什么星座| giada是什么牌子| 叔叔的儿子叫什么| 不全纵隔子宫是什么意思| 特斯拉用的是什么电池| 粉色玫瑰花代表什么意思| 芋圆是什么做的| 毛血旺是什么菜| 猜疑是什么意思| 头发变棕色是什么原因| 黄色有什么黄| 空姐在飞机上干什么| 碎花裙配什么鞋子| 什么情况下用妇炎洁| 王羲之的儿子叫什么名字| fml什么意思| 血管瘤有什么危害吗| 女性脉弦是什么意思| 藕粉对身体有什么好处| 孩子手抖是什么原因| 干眼症是什么原因引起的| 心率高是什么原因| 一什么之| 喝茶什么意思| 胎儿头偏小是什么原因引起的| 红字五行属什么| 北京为什么是首都| 老人大小便失禁是什么原因造成的| tdp是什么| 南极有什么| 血脂是指什么| 没什么打什么| 马桶对着卫生间门有什么不好| 榴莲为什么苦| 上午十点到十一点是什么时辰| 室内用什么隔墙最便宜| 义是什么意思| 假卵是什么样子的| 扁桃体发炎严重吃什么药好得快| 橄榄是什么| 心阳不足吃什么中成药| 妇科炎症吃什么药最好| 道和集团是干什么的| 促甲状腺激素低是什么原因| 三月29号是什么星座| 小学生什么时候放暑假| 晋字五行属什么| 心脏窦性心律什么意思| 白色舌苔厚是什么原因| 口苦口臭口干吃什么药| 乳腺钙化是什么意思| 腊猪脚炖什么好吃| 八月三日是什么星座| 琪五行属性是什么| 恒字属于五行属什么| 肺实性结节是什么意思| 手发抖是什么病的先兆| 玫瑰糠疹吃什么药最有效| 经期喝什么汤| 发烧呕吐吃什么药| 为什么会长痣| 武夷岩茶是什么茶| 男人蛋蛋疼是什么原因| 不让看朋友圈显示什么| 被蝎子蛰了用什么药| 烧仙草是什么东西| 什么是糖化血红蛋白| 89年是什么命| 喝中药尿黄是什么原因| 拜土地公要准备什么东西| 授人以鱼不如授人以渔什么意思| hds是什么意思| 肾结石是什么引起的| 金银花长什么样子图片| 农历11月18日是什么星座| 猫眼石是什么| 宁五行属性是什么| tnt什么意思| 小米粥配什么菜好吃| 2004年是什么生肖| 胃底腺息肉是什么意思| 春考是什么| 掰弯了是什么意思| 胆囊壁不光滑是什么意思| 西红柿什么时候成熟| 回光返照是什么意思| 腰扭伤用什么药最好| 脚气长什么样| 接盘是什么意思| 白兰地是什么| 揽子是什么意思| 人死后会变成什么| 大拇指疼是什么原因| 白头发补什么维生素| 伤口结痂为什么会痒| 三七粉吃了有什么好处| 宝宝什么时候可以吃盐| 蛐蛐吃什么食物| 十月十一是什么星座| 郭富城属什么生肖| 91岁属什么| 灰水是什么| 赤色是什么颜色| 为什么突然就得肝炎了| 百度
打印
[RISC-V MCU 应用开发]

信用卡“江湖”争夺战: 工、建、招行稳居前三

[复制链接]
6327|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
RISCVLAR|  楼主 | 2025-08-04 17:23 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 RISCVLAR 于 2025-08-04 17:22 编辑

CH32V103应用教程——FATFS文件系统(SD卡)

本章教程将使用FATFS文件系统来管理SD卡,实现对SD卡文件读写等基本功能。

1、FATFS简介及相关函数介绍
FATFS 是一种免费开源的、且面向小型嵌入式系统的一种通用FAT文件系统。其采用标准C语言编写并完全独立于底层I/O介质,具有良好的硬件平**立性,可以移植到8051、PIC、AVR、SH、Z80、H8、ARM 等系列单片机上而只需做简单的修改。它支持 FATl2、FATl6和FAT32等格式,支持多个存储媒介;有独立的缓冲区,可以对多个文件进行读/写,并特别对8位单片机和16位单片机做了优化。

本章教程在上一章SD卡教程的基础上,将FATFS文件系统代码移植到SD卡工程中,并对其进行读写测试。关于FATFS文件系统源码可从FATFS官网进行下载。

FATFS源码文件夹src文件夹主要包含以下几个文件:
  • option文件夹下文件为一些可选外部c文件,包含多语言支持需要用到的文件和转换函数;
  • diskio.c文件是 FATFS移植最关键的文件,它为文件系统提供了最底层的访问SD卡SPI接口的方法。其包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。
  • diskio.h定义了FATFS用到的宏,以及diskio.c文件内与底层硬件接口相关的函数声明。
  • integer.h文件中包含了一些数值类型定义。
  • ff.c文件是FATFS核心文件,是文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。
  • ffconf.h这个头文件包含了对FATFS功能配置的宏定义, 通过修改这些宏定义就可以裁剪FATFS的功能。

关于FATFS文件系统模块的移植,我们只需把上述几个文件添加到SD卡工程中并进行一些修改即可。

2、硬件设计
本章教程主要在SD卡基础上进行FATFS文件系统模块的移植,所需资源与上一章一致。

3软件设计
本章教程在上一章SD卡测试基础上进行FATFS文件系统模块的移植,将FATFS源码文件夹下文件添加工工程之后,只需进行以下修改即可:

1、由于本款开发板芯片ROM容量限制原因,option文件夹中选用文件ccsbcs.c文件;

2、对ffconf.h文件进行以下修改:
  • #define _USE_MKFS  1,这个用来定时是否使能格式化,本章需要用到,所以设置这里为1。
  • #define _CODE_PAGE 437,此选项指定要在目标系统上使用的OEM代码页,错误的代码页设置可能会导致文件打开失败,此处选择U.S.,语言类型选择为英文,437,此处需要和ccsbcs.c文件同步使用;
  • #define _USE_LFN   1,该选项用于设置是否支持长文件名(还需要_CODE_PAGE 支持),取值范围为 0~3。0,表示不支持长文件名,1~3 是支持长文件名,但是存储地方不一样,我们选择使用1,通过启用BSS上的静态工作缓冲区启用LFN;
  • #define _VOLUMES   2,用于设置FATFS支持的逻辑设备数目,我们设置为 2,即支持2个设备;
  • #define _MIN_SS    512,指定扇区缓冲最小值;
  • #define _MAX_SS   4096,指定扇区缓冲最大值。

3、关于diskio.c文件,其具体程序如下:

#include "diskio.h"
#include "sd.h"
#include "malloc.h"


#define SD_CARD  0  //SD卡,卷标为0
#define EX_FLASH 1  //外部flash,卷标为1

#define FLASH_SECTOR_SIZE   512

//初始化磁盘
DSTATUS disk_initialize (
    BYTE pdrv               /* Physical drive nmuber (0..) */
)
{
    u8 res=0;
    switch(pdrv)
    {
        case SD_CARD://SD卡
            res = SD_Initialize();//SD_Initialize()
            if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
            {
                SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
            }
            break;
        case EX_FLASH://外部flash
            break;
        default:
            res=1;
    }
    if(res)return  STA_NOINIT;
    else return 0; //初始化成功
}

//获得磁盘状态
DSTATUS disk_status (
    BYTE pdrv       /* Physical drive nmuber (0..) */
)
{
    return 0;
}

//读扇区
//drv:磁盘编号0~9
//*buff:数据接收缓冲首地址
//sector:扇区地址
//count:需要读取的扇区数
DRESULT disk_read (
    BYTE pdrv,      /* Physical drive nmuber (0..) */
    BYTE *buff,     /* Data buffer to store read data */
    DWORD sector,   /* Sector address (LBA) */
    UINT count      /* Number of sectors to read (1..128) */
)
{
    u8 res=0;
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
    switch(pdrv)
    {
        case SD_CARD://SD卡
            res=SD_ReadDisk(buff,sector,count);
            if(res)//STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常
            {
                SD_SPI_ReadWriteByte(0xff);//提供额外的8个时钟
            }
            break;
        case EX_FLASH://外部flash
            res=0;
            break;
        default:
            res=1;
    }
   //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res==0x00)return RES_OK;
    else return RES_ERROR;
}

//写扇区
//drv:磁盘编号0~9
//*buff:发送数据首地址
//sector:扇区地址
//count:需要写入的扇区数
#if _USE_WRITE
DRESULT disk_write (
    BYTE pdrv,          /* Physical drive nmuber (0..) */
    const BYTE *buff,   /* Data to be written */
    DWORD sector,       /* Sector address (LBA) */
    UINT count          /* Number of sectors to write (1..128) */
)
{
    u8 res=0;
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误
    switch(pdrv)
    {
        case SD_CARD://SD卡
            res=SD_WriteDisk((u8*)buff,sector,count);
            break;
        case EX_FLASH://外部flash
            res=0;
            break;
        default:
            res=1;
    }
    //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res == 0x00)return RES_OK;
    else return RES_ERROR;
}
#endif


//其他表参数的获得
//drv:磁盘编号0~9
//ctrl:控制代码
//*buff:发送/接收缓冲区指针
#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;
    if(pdrv==SD_CARD)//SD卡
    {
        switch(cmd)
        {
            case CTRL_SYNC:
                SD_CS_L;
                if(SD_WaitReady()==0)res = RES_OK;
                else res = RES_ERROR;
                SD_CS_H;
                break;
            case GET_SECTOR_SIZE:
                *(WORD*)buff = 512;
                res = RES_OK;
                break;
            case GET_BLOCK_SIZE:
                *(WORD*)buff = 8;
                res = RES_OK;
                break;
            case GET_SECTOR_COUNT:
                *(DWORD*)buff = SD_GetSectorCount();
                res = RES_OK;
                break;
            default:
                res = RES_PARERR;
                break;
        }
    }
    else res=RES_ERROR;//其他的不支持
    return res;
}
#endif
//获得时间
//User defined function to give a current time to fatfs module      */
//31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */
//15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */
DWORD get_fattime (void)
{
    return 0;
}
diskio.c文件主要进行磁盘初始化以及进行获取磁盘状态和读写扇区等操作;

4、关于main.c文件
/********************************** (C) COPYRIGHT *******************************
* File Name          : main.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2020/04/30
* Description        : Main program body.
*******************************************************************************/
#include "debug.h"
#include "spi.h"
#include "sd.h"
#include "ff.h"


//定义变量
FATFS fs;                     /* FatFs文件系统对象 */
FIL fnew;                     /* 文件对象 */
FRESULT res_sd;               /* 文件操作结果 */
UINT fnum;                    /* 文件成功读写数量 */
BYTE ReadBuffer[1024]={0};    /* 读缓冲区 */
BYTE WriteBuffer[] =          /* 写缓冲区*/
"欢迎使用沁恒CH32V103开发板,新建文件系统测试文件\r\n";

/*******************************************************************************
* Function Name  : main
* Description    : Main program.
* Input          : None
* Return         : None
*******************************************************************************/
int main(void)
{
    u32 sd_size;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
        USART_Printf_Init(115200);

        printf("SystemClk:%d\r\n",SystemCoreClock);
        printf("This is SD FATFS example\r\n");

        if(SD_Detect()==0)
        {
            printf("未检测SD卡插入!\n");
        }
        else
        {
            printf("已检测SD卡插入!\n");

            if(SD_Initialize())
            {
                printf("SD卡初始化出错,请检查!!\n");
                Delay_Ms(500);
            }
            else
            {
                printf("SD卡初始化完成!\n");
                sd_size=SD_GetSectorCount();//得到扇区数
                printf("SD Card Size(MB):%d\n",sd_size>>11);
            }
        }

    //在外部SPI SD挂载文件系统,文件系统挂载时会对SPI设备初始化
    res_sd = f_mount(&fs,"0:",1);

    /*----------------------- 格式化测试 ---------------------------*/
        /* 如果没有文件系统就格式化创建创建文件系统 */
        if(res_sd == FR_NO_FILESYSTEM)
        {
            printf("》SD卡还没有文件系统,即将进行格式化...\r\n");
        /* 格式化 */
            res_sd=f_mkfs("0:",0,0);

            if(res_sd == FR_OK)
            {
                printf("》SD卡已成功格式化文件系统。\r\n");
          /* 格式化后,先取消挂载 */
                res_sd = f_mount(NULL,"0:",1);
          /* 重新挂载   */
                res_sd = f_mount(&fs,"0:",1);
            }
            else
            {
                printf("《《格式化失败。》》res_sd =%d\r\n",res_sd);
                while(1);
            }
        }
      else if(res_sd!=FR_OK)
      {
        printf("!!SD卡挂载文件系统失败。(%d)\r\n",res_sd);
        printf("!!可能原因:SD卡初始化不成功。\r\n");
            while(1);
      }
      else
      {
        printf("》文件系统挂载成功,可以进行读写测试\r\n");
      }
        /*----------------------- 文件系统测试:写测试 -----------------------------*/
            /* 打开文件,如果文件不存在则创建它 */
            printf("\r\n****** 即将进行文件写入测试... ******\r\n");
            res_sd = f_open(&fnew, "0:FatFs读写测试文件.txt",FA_CREATE_ALWAYS | FA_WRITE );
            if ( res_sd == FR_OK )
            {
                printf("》打开/创建FatFs读写测试文件.txt文件成功,向文件写入数据。\r\n");
            /* 将指定存储区内容写入到文件内 */
                res_sd=f_write(&fnew,WriteBuffer,sizeof(WriteBuffer),&fnum);
            if(res_sd==FR_OK)
            {
              printf("》文件写入成功,写入字节数据:%d\n",fnum);
              printf("》向文件写入的数据为:\r\n%s\r\n",WriteBuffer);
            }
            else
            {
              printf("!!文件写入失败:(%d)\n",res_sd);
            }
                /* 不再读写,关闭文件 */
            f_close(&fnew);
            }
            else
            {
                printf("!!打开/创建文件失败。\r\n");
            }

        while(1)
    {
        }
}

main.c文件主要进行相关函数初始化以及读取输出相关信息。


4、下载验证
将编译好的程序下载到开发板并复位,当未插入SD卡时,串口打印情况具体如下:

插入SD卡并复位后,串口打印情况如下:



25、FATFS.rar

715.64 KB

评论
Jekele 2025-08-04 11:47 回复TA
学习。 

相关帖子

沙发
xdqfc| | 2025-08-04 11:59 | 只看该作者
楼主能否在磁盘(SD)下多增加几个文件,然后再扫描磁盘下的目录,并且print出来,那样就更加完美了。先期待一下。
板凳
RISCVLAR|  楼主 | 2025-08-04 14:08 | 只看该作者
xdqfc 发表于 2025-08-04 11:59
楼主能否在磁盘(SD)下多增加几个文件,然后再扫描磁盘下的目录,并且print出来,那样就更加完美了。先期 ...

好的,后面有空会搞得
地板
gtbestom| | 2021-8-4 13:38 | 只看该作者
这个新建的文件,文件名乱码了。
5
gtbestom| | 2021-8-4 14:10 | 只看该作者
64K的Flash空间,放不下936对照表,所以中文文件名会显示乱码
6
sesefadou| | 2021-8-11 15:57 | 只看该作者
FATFS需要占用多大的内存额   
7
earlmax| | 2021-8-11 15:58 | 只看该作者
支持flash芯片吗   
8
maudlu| | 2021-8-11 15:58 | 只看该作者
必须用malloc吗?     
9
mattlincoln| | 2021-8-11 15:58 | 只看该作者
读取文件的时候特别慢。           
10
mollylawrence| | 2021-8-11 15:58 | 只看该作者
FATFS文件系统速度可行?  
11
geraldbetty| | 2021-8-11 15:59 | 只看该作者
这个扇区是怎么划分   
12
macpherson| | 2021-8-11 15:59 | 只看该作者
哪里是配置空间大小的呢  
13
jonas222| | 2021-8-11 16:00 | 只看该作者
可以通过usb管理SD卡吗  
14
claretttt| | 2021-8-11 16:00 | 只看该作者
CH32V103可以直接生成fatfs代码吗  
15
kkzz| | 2021-8-11 16:00 | 只看该作者
8位单片机没有移植成功过。
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

133

主题

296

帖子

44

粉丝
金蝉脱壳什么意思 电信诈骗是什么意思 戒色有什么好处 牙结石有什么危害 如日中天的意思是什么
奶咖色是什么颜色 急性胆囊炎吃什么药 有始无终是什么生肖 大学团委书记什么级别 此起彼伏是什么意思
耳朵发炎吃什么消炎药 今天什么属相 脂蛋白a是什么意思 花椒有什么作用 七月五号是什么星座
血糖高喝什么茶好 切除痣挂什么科 万宝龙皮带算什么档次 你想干什么 甲虫吃什么食物
风寒感冒吃什么药hcv8jop4ns0r.cn 什么马不能骑dajiketang.com 哈达是什么hcv9jop5ns2r.cn 专技十三级是什么意思0735v.com 满月送什么礼物好adwl56.com
池塘边的榕树上是什么歌hcv9jop6ns6r.cn 白细胞酯酶弱阳性是什么意思hcv9jop6ns7r.cn 女生下面是什么样的hcv9jop0ns2r.cn 女人做梦梦到蛇是什么意思hcv9jop2ns0r.cn 什么是火碱hcv9jop1ns2r.cn
布洛芬吃多了有什么副作用520myf.com 榄仁是什么hcv7jop9ns3r.cn skin是什么意思hcv8jop6ns2r.cn 脚底出汗什么原因0735v.com 音序是什么意思hcv7jop6ns5r.cn
膀胱癌有什么症状hkuteam.com 淋巴细胞计数偏高是什么原因aiwuzhiyu.com 臭虫长什么样hcv9jop6ns1r.cn 尿道炎吃什么药好hcv8jop7ns9r.cn 喝酒头疼吃什么药hcv8jop9ns3r.cn
百度