从零实现 FATFS+SD卡 您所在的位置:网站首页 内存卡又叫sd卡吗 从零实现 FATFS+SD卡

从零实现 FATFS+SD卡

2024-07-01 02:20| 来源: 网络整理| 查看: 265

 

cubemx软件版本是V4.23.0,芯片型号是STM32F103ZET6、STM32F429IGT6;SD卡是闪迪的64G tf卡,然后用了转大卡的卡槽,exFAT。

 

该篇为调试过程,所以阅读时一定要看到尾,中间的判断是有误的!!!中间会涉及到F429是因为一直失败,我拿两个板子来回尝试。

调试过程:

注意,//在生成fatfs代码后,一定要在初始化SDIO时或者FATFS初始化时加上该句(在f_mount前就行),因为cubemx建立中间层,把SD也封装了中间层BSP_SD,所以之前的默认初始化中HAL_SD_Init移至了该函数中!!!     BSP_SD_Init();

死在这个函数中 uint8_t SDIO_GetCommandResponse(SDIO_TypeDef *SDIOx) {   return (uint8_t)(SDIOx->RESPCMD); } 这个函数从disk_initialize开始被层层调用,在f_mount中去初始化SD卡,看是否成功。disk_initialize在diskio.c中定义,cubemx会自动生成,正点原子是自己写的实现功能。 为什么cubemx出来的获取SD卡状态要用到SDMMC?而正点原子没有使用到?

在cubemx F429时一定要使能exfat,我的tf卡默认是exfat格式,正点原子支持,cubemx的教程都没有提到exfat,在f_mount中有判断SD卡的启动页,去检查是什么文件格式,如果不使能就会被认为是没有文件系统。f_mount就会失败。 但是在cubemx F103时则没有该项。

正点原子的HAL与我的cubemx生成的HAL,stm32f4xx_hal_sd.c都不一样。可能是版本问题,cubemx生成的HAL版本为2017年,原子的为2016年。

普通使用SD卡读写是可以的,但在FATFS中调用HAL_SD的读写就会死机,不知道为什么!

世上无难事,只要肯放弃。明天上网找找资料,如果还是没有结果的话,就先放到一边,以后有时间再突破把,反正移植原子的也可以用。

在F103精英版创建了读SD卡的程序,需要注意,因为HAL与正点原子的不同,读扇区不是计算出具体地址,而是直接输入要读的扇区号。 刚开始读不出来,后来在论坛上发现原子的分频因子设为了9.同样设为9就能读了,跟内存分配也没关系,读出的buff为局部指针也可以。

还发现一个不同,HAL版本不同,读出的SD卡的类型号也不同。  cubemx的HAL: /** @defgroup SD_Exported_Constansts_Group3 SD Supported Memory Cards   * @{ #define CARD_SDSC                  0x00000000U         #define CARD_SDHC_SDXC             0x00000001U            //同样的SD卡读出这个 #define CARD_SECURED               0x00000003U /** @defgroup SD_Exported_Constansts_Group4 SD Supported Version   * @{   */ #define CARD_V1_X                  0x00000000U #define CARD_V2_X                  0x00000001U 原子的HAL: /**    * @brief Supported SD Memory Cards    */ #define STD_CAPACITY_SD_CARD_V1_1             ((uint32_t)0x00000000) #define STD_CAPACITY_SD_CARD_V2_0             ((uint32_t)0x00000001) #define HIGH_CAPACITY_SD_CARD                 ((uint32_t)0x00000002)    //同样的SD卡读出这个     #define MULTIMEDIA_CARD                       ((uint32_t)0x00000003) #define SECURE_DIGITAL_IO_CARD                ((uint32_t)0x00000004) #define HIGH_SPEED_MULTIMEDIA_CARD            ((uint32_t)0x00000005) #define SECURE_DIGITAL_IO_COMBO_CARD          ((uint32_t)0x00000006) #define HIGH_CAPACITY_MMC_CARD                ((uint32_t)0x00000007)

接下来再试写入,之后再读,成功后就重新配置fatfs.

在F429上重新实验SD卡,成功,发现一件事儿,就是SD卡的实验是往扇区0写入一串数字,这会破坏SD卡的fatfs的启动扇区。原来启动扇区中的数据都会被写入而先擦写。所以我之前可能也是因为这个而实验FATFS失败。

重新实验fatfs 我去,我竟然成功了!也太鬼扯了吧! 用F429的SD卡实验重新配置fatfs,竟然成功了!挂载、打开文件(打开、新建)、写文件、关文件、打开文件(读)、读文件、卸载都成功了。  

转天我又尝试了F103的FATFS,F103与F429的cubemx配置FATFS不一样,F103没有使能exFAT的选项。 我以为是默认支持的,结果生成代码后总是mount失败。重新格式化也不行,而且去看0扇区,也没毛病呀。 追根溯源是代码在判断SD卡的FAT类型出错,识别不了FAT类型。 原来是cubemxF103生成的代码没有_FS_EXFAT,而原子的F103例程是有的,而且和F429的一致。 通过查看HAL版本,我发现cubemx生成的是 R0.11 (C)ChaN, 2015。原子的是R0.12  (C)ChaN, 2016 我想如果是因为2015版的HAL不支持exFAT,那我试试格式化SD卡为FAT32,结果成功了。。。。。。 也就是说可能是我的cubemx支持的F103板级包版本低。我试试升级软件版本试试看。

升级了最新的cubemx5.6.0,然后F103的板级包也是最新的,但是重新配置FATFS仍旧是version0.11。原子是从FATFS官方移植的R0.12,cubemx配置F429是R0.12c版本。所以应该就是cubemx没有及时更新F103的。

所以如果想用最新的,还是得自己去移植FATFS,有时间再搞吧。

 

F103实验结果:

 

1.先打印SD卡信息

2.打印0号扇区的数据

3.先挂载,显示成功

打开文件,读取,关闭,失败,因为没有STM32cube.txt文件

创建文件STM32cube.txt,写入数据,关闭,成功

打开文件,读取,关闭,成功,因为此时有了STM32cube.txt文件

卸载,成功

 

F429实验结果类似,就不贴结果了,有需要的朋友可以下载资源去试一下

为了找出是哪造成之前失败的,我把改动的部分一一恢复,并总结一下:

1.看门狗延长了,恢复,没有问题。 2.SD卡的分频提高了,恢复最快速度,分频为0,也没问题。注意:F103的SD卡实验分频降到2以下就不行,需要在2以上。 3.把BSP_SD_Init放在挂载之后去,那么挂载的时候操作SD卡时就会死机。这个是坑,但我最近已经发现了这个问题。所以不是这个问题导致的。 4.那么有可能就是我往SD卡扇区0去写数据,损坏了启动盘,导致挂载失败。 5.此外还有一个坑是:f_open,如果你要写入一些文件,那么要先打开文件。retSD = f_open(&SDFile, filename, FA_CREATE_ALWAYS | FA_WRITE);     如果要读取一个文件前,也要先打开文件,但是注意区别!retSD = f_open(&SDFile, filename, FA_READ); 6.此外还有一个坑是:f_close,只要打开一个文件去操作了读写,那么之后一定要关闭文件。不然下次打开(即便你上次打开是要写,这次打开还是要写)就会失败。     也就是说,f_open和f_close要成为一个最小闭环。也就是()(),不能是(())。     也就是说,可以(f_write,f_write),但是不能(f_write(f_write)),(f_write,f_read)更是不可以了。 7.f_mount除了挂在外,retSD = f_mount(&SDFatFS, (const TCHAR*)SDPath, 1);     还有卸载的功能,即把路径下的文件系统卸载,retSD = f_mount(0, (const TCHAR*)SDPath, 1);     挂载和卸载都可以重复,没有问题。即便没有挂载也可以卸载。     但需要注意的是:卸载后就不能操作f_open等功能了,一定要先挂载。     挂载是个什么意思呢,就是通过读取SD卡的启动扇区,来让单片机的fatfs知道SD卡的具体参数,如检查是FAT32还是EXFAT啊,有没有文件系统啊。fat表的个数啊、簇大小啊、扇区数量、扇区大小啊。     然后还要通过SDMMC(SD卡的底层)去询问SD卡的状态,去查SD卡的FATFS是否能用啊。非常多。     一通检查,信息也获取了,验证能使了,就挂载成功了。     通过查看FATFS的句柄也可知其一二。 8.把栈空间分配的大一些,0x1000就够了。堆不用多分配0x200够了。我们看到原子的栈是0x400,堆是0x200,那怎么够呢。     他用的是内存分配,把要用到的FATFS的句柄、读写buff都分配在静态内存空间中,也就是除去堆和栈的SRAM空间中。 9.SD卡是FAT32的还是exFAT的都无所谓,但是一定要知道自己的SD卡是什么文件系统的,如果是exFAT类型的,则一定要使能_FS_EXFAT     F103不一定会区分exFAT,要看HAL库版本是否支持_FS_EXFAT。如果HAL版本低,那就先把SD卡格式化为FAT32再用吧。

exFAT和FAT32的区别在哪呢?FAT32不支持单文件超过4G,exFAT支持。FAT32有两个FAT表,exFAT只有一个。

感言:

FATFS其实还真的蛮复杂的,尤其是出问题的时候,真的是要一点一点倒,很多错误码的返回,去分析。     ff.c的代码也很复杂,但是我想起一句话,就是说一个东西底层做的很复杂的,往往使用起来就很简单。     比如USB,驱动也是很复杂的。比如苹果,用起来很简单的一个功能,底层代码不知道有多少逻辑。     这次做这个实验,我真的是头要炸了,好在有开发板,开发板能成功,我们就能对比着来看,找不同。     通过修改不同,一点点把自己的代码尝试成功。     所以开发板的作用一定不是给你提供底层让你去移植的,他只能作为学习用,真正使用好cubemx,会让你事半功倍。     不用看SD卡的手册,命令怎么发之类的。配置好cubemx,HAL库的封装做的非常好,直接读写指定扇区。     不用从源码移植FATFS,辛辛苦苦的,还得做好FATFS与SD卡的连接,选好FATFS的SD选项,cubemx帮你建立好连接。f_mount就完事儿了。     但是cubemx也不能认为是万能的,比如初始化的坑。他自己也有写的不好的地方,所以这也是为什么要自己动手去实战去找坑。     只有提前踩好了坑,以后用时才会不慌。     这次调试FATFS包括学习资料,断断续续大约耗时十六个小时,中间好几次想放弃了,但是心有不甘。     好在成功了,非常非常开心。     希望能够帮到别人,祝所有努力的人都有回报。

   

最近项目中的nandflash128M,不够存了。和同事咨询用SD卡存历史数据。一种是用文件系统、一种是不用文件系统按照类似操作nandflash的方式操作。

1.如果用文件系统的话每日生成一个.csv,导出数据比较方便,想导出数据的话直接取下SD卡就能在电脑上读取。存起来也比较方便,不用计算存到哪个扇区,哪一页,偏移量多少。但是缺点是,在应用程序中读取历史数据很麻烦,由于文件系统是针对文件的,并不支持文件中内容的操作,比如查找、指定位置增加删除数据等。

2.如果不用文件系统的话,难点就在于设计一个用时间计算地址的方式,因为最小擦除单位和nandflash一样都是扇区,所以这部分工作也不少做。此外,由于没有用文件系统,电脑不能直接读取。所以还需要做一个U盘导出功能。但是优点就是应用程序获取指定时间的历史数据比较方便。

对nandflash感兴趣的可以看下我的文章

调试数据存储到nandflash的那些事儿(一):关于sizeof()的一些坑

调试数据存储到nandflash的那些事儿(二): 存入nandflash的方式比较

调试数据存储到nandflash的那些事儿(三): 关于移位存入,强制类型转换读出的讨论

调试数据存储到nandflash的那些事儿(四):nandflash底层的简介

调试数据存储到nandflash的那些事儿(五):对nandflash的寻址说明

 

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有