STM32CubeMX学习笔记(27)——FatFs文件系统使用(操作SD卡

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

如果你需要这些资料,可以戳这里获取

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

功能创建/打开一个文件对象
函数定义FRESULT f_open(FIL* fp, const TCHAR* path, BYTE mode)
参数fp:将被创建的文件对象结构的指针path:文件名指针,指定将创建或打开的文件名mode:访问类型和打开方法,由一下标准的一个组合指定的
返回操作结果
模式描述
FA_READ指定读访问对象。可以从文件中读取数据。 与FA_WRITE 结 合可以进行读写访问。
FA_WRITE指定写访问对象。可以向文件中写入数据。与FA_READ 结合 可以进行读写访问。
FA_OPEN_EXISTING打开文件。如果文件不存在,则打开失败。(默认)
FA_OPEN_ALWAYS如果文件存在,则打开;否则,创建一个新文件。
FA_CREATE_NEW创建一个新文件。如果文件已存在,则创建失败。
FA_CREATE_ALWAYS创建一个新文件。如果文件已存在,则它将被截断并覆盖。
1.3.3 f_close
功能关闭一个打开的文件
函数定义FRESULT f_close(FIL* fp)
参数fp:指向将被关闭的已打开的文件对象结构的指针
返回操作结果
1.3.4 f_read
功能从一个打开的文件中读取数据
函数定义FRESULT f_read(FIL* fp, void* buff, UINT btr, UINT* br)
参数fp:指向将被读取的已打开的文件对象结构的指针buff:指向存储读取数据的缓冲区的指针btr:要读取的字节数br:指向返回已读取字节数的UINT变量的指针,返回为实际读取的字节数
返回操作结果
1.3.5 f_write
功能写入数据到一个已打开的文件
函数定义FRESULT f_write(FIL* fp, void* buff, UINT btw, UINT* bw)
参数fp:指向将被写入的已打开的文件对象结构的指针buff:指向存储写入数据的缓冲区的指针btw:要写入的字节数bw:指向返回已写入字节数的UINT变量的指针,返回为实际写入的字节数
返回操作结果

另外FatFs还有很多API操作函数,在这里不再作详细的介绍,详细信息请查看FatFs文件系统官网。

二、新建工程

1. 打开 STM32CubeMX 软件,点击“新建工程”

2. 选择 MCU 和封装

3. 配置时钟
RCC 设置,选择 HSE(外部高速时钟) 为 Crystal/Ceramic Resonator(晶振/陶瓷谐振器)

选择 Clock Configuration,配置系统时钟 SYSCLK 为 72MHz
修改 HCLK 的值为 72 后,输入回车,软件会自动修改所有配置

4. 配置调试模式
非常重要的一步,否则会造成第一次烧录程序后续无法识别调试器
SYS 设置,选择 Debug 为 Serial Wire

三、SDIO

STM32 控制器可以控制使用单线或 4 线传输,本开发板设计使用 4 线传输。

3.1 参数配置

Connetivity 中选择 SDIO 设置,并选择 SD 4 bits Wide bus 四线SD模式

此时 SDIO 对应的管脚也被选中。

Parameter Settings 进行具体参数配置。

Clock transition on which the bit capture is made: Rising transition。主时钟 SDIOCLK 产生 CLK 引脚时钟有效沿选择,可选上升沿或下降沿,它设定 SDIO 时钟控制寄存器(SDIO_CLKCR)的 NEGEDGE 位的值,一般选择设置为上升沿

SDIO Clock divider bypass: Disable。时钟分频旁路使用,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 BYPASS 位。如果使能旁路,SDIOCLK 直接驱动 CLK 线输出时钟;如果禁用,使用 SDIO_CLKCR 寄存器的 CLKDIV 位值分频 SDIOCLK,然后输出到 CLK 线。一般选择禁用时钟分频旁路

SDIO Clock output enable when the bus is idle: Disable the power save for the clock。节能模式选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 PWRSAV 位的值。如果使能节能模式,CLK 线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能 CLK 线输出时钟。

SDIO hardware flow control: The hardware control flow is disabled。硬件流控制选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 HWFC_EN 位的值。硬件流控制功能可以避免 FIFO 发送上溢和下溢错误。

SDIOCLK clock divide factor: 6。时钟分频系数,它设定 SDIO_CLKCR 寄存器的 CLKDIV 位的值,设置 SDIOCLK 与 CLK 线输出时钟分频系数:CLK 线时钟频率=SDIOCLK/([CLKDIV+2])。

SDIO_CK 引脚的时钟信号在卡识别模式时要求不超过 400KHz,而在识别后的数据传输模式时则希望有更高的速度(最大不超过 25MHz),所以会针对这两种模式配置 SDIOCLK 的时钟。

这里参数描述建议将SDIOCLK clock divede factor 参数使用默认值为0,SDIOCLK为72MHz,可以得到最大频率36MHz,但请注意,有些型号的SD卡可能不支持36MHz这么高的频率,所以还是要以实际情况而定。

3.2 配置DMA

SDIO 外设支持生成 DMA 请求,使用 DMA 传输可以提高数据传输效率,因此在 SDIO 的控制代码中,可以把它设置为 DMA 传输模式或轮询模式,ST 标准库提供 SDIO 示例中针对这两个模式做了区分处理。应用中一般都使用DMA 传输模式。

点击 DMA Settings 添加 SDIO 对应 DMA2 的通道4。DMA模式选择循环模式,方向选为内存到外设。

  • Priority
    当发生多个 DMA 通道请求时,就意味着有先后响应处理的顺序问题,这个就由仲裁器也管理。仲裁器管理 DMA 通道请求分为两个阶段。第一阶段属于软件阶段,可以在 DMA_CCRx 寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的 DMA 通道请求设置的优先级一样,则他们优先级取决于通 道编号,编号越低优先权越高,比如通道 0 高于通道 1。在大容量产品和互联型产品中,DMA1 控制器拥有高于 DMA2 控制器的优先级。
  • Mode
    Normal 表示单次传输,传输一次后终止传输。
    Circular 表示循环传输,传输完成后又重新开始继续传输,不断循环永不停止。
  • Increment Address
    Peripheral 表示外设地址自增。
    Memory 表示内存地址自增。
  • Data Width
    Byte 一个字节。
    Half Word 半个字,等于两字节。
    Word 一个字,等于四字节。

3.3 配置NVIC

DMA及SDIO中断设置,原则是全局中断优先级高于DMA中断

四、FATFS

4.1 参数配置

Middleware 中选择 FATFS 设置,并勾选 SD Card 配置为SD卡

  • Function Parameters 跳过

  • Locale and Namespace Parameters:

    • CODE_PAGE(Code page on target): Simplified Chinese GBK(DBCS,OEM,Windows) 支持简体中文编码
    • USE_LFN(Use Long Filename): Enabled with dynamic working buffer on the STACK 支持长文件名,并指定使用栈空间为缓冲区

缓存工作区为什么放在栈?其实fatfs提供了三个选项:BSS,STACK , HEAP,根据个人情况选一个。
在BSS上启用带有静态工作缓冲区的LFN,不能动态分配。
如果选择了HEAP(堆)且自己有属于自己的malloc就去重写ff_memalloc  ff_memfree函数。如果是库的malloc就不需要。
一般都选择使用STACK(栈),能动态分配。
当使用堆栈作为工作缓冲区时,请注意堆栈溢出。

  • Physical Drive Parameters:
    • VOLUMES(Logical drivers): 2 指定物理设备数量,这里设置为 2,包括预留 SD 卡和 SPI Flash 芯片
    • MAX_SS(Maximum Sector Size): 512 指定扇区大小的最大值。SD 卡扇区大小一般都为 512 字节,SPI Flash 芯片扇区大小一般设置为 4096 字节,所以需要把 _MAX_SS 改为 512
    • MIN_SS(Minimum Sector Size): 512 指定扇区大小的最小值

4.2 配置SD卡检测引脚

SD卡插入检测引脚,如果不配置一个引脚生成文件时会报错,所以这里即使没有硬件连接,也可以任意设置一引脚使用,生成工程后注释代码。

4.3 增大栈空间

将最小栈空间改到 0x1000

注意:由于刚才设置长文件名动态缓存存储在堆中,故需要增大堆大小,如果不修改则程序运行时堆会生成溢出,程序进入硬件错误中断(HardFault),死循环。

4.4 生成代码

输入项目名和项目路径

选择应用的 IDE 开发环境 MDK-ARM V5

每个外设生成独立的 ’.c/.h’ 文件
不勾:所有初始化代码都生成在 main.c
勾选:初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。

点击 GENERATE CODE 生成代码

五、屏蔽SD卡插入检测代码

由于没有检测SD卡插入的硬件引脚,打开 bsp_driver_sd.c 文件,修改 BSP_SD_IsDetected() 函数,始终返回SD_PRESENT:

六、修改main函数

定义相关变量:

FATFS fs;                       /\* FatFs 文件系统对象 \*/
FIL file;                       /\* 文件对象 \*/
FRESULT f_res;                  /\* 文件操作结果 \*/
UINT fnum;                      /\* 文件成功读写数量 \*/
BYTE ReadBuffer[1024] = {0};    /\* 读缓冲区 \*/
BYTE WriteBuffer[] =            /\* 写缓冲区 \*/
    "This is STM32 working with FatFs\r\n";

修改main函数:

/\*\*
 \* @brief The application entry point.
 \* @retval int
 \*/
int main(void)
{
  /\* USER CODE BEGIN 1 \*/

  /\* USER CODE END 1 \*/

  /\* MCU Configuration--------------------------------------------------------\*/

  /\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/
  HAL\_Init();

  /\* USER CODE BEGIN Init \*/

  /\* USER CODE END Init \*/

  /\* Configure the system clock \*/
  SystemClock\_Config();

  /\* USER CODE BEGIN SysInit \*/

  /\* USER CODE END SysInit \*/

  /\* Initialize all configured peripherals \*/
  MX\_GPIO\_Init();
  MX\_DMA\_Init();
  MX\_USART1\_UART\_Init();
  MX\_SDIO\_SD\_Init();
  MX\_FATFS\_Init();
  /\* USER CODE BEGIN 2 \*/
    printf("\r\n\*\*\*\*\*\* FatFs Example \*\*\*\*\*\*\r\n\r\n");
    
    //在外部 SD 卡挂载文件系统,文件系统挂载时会对 SD 卡初始化
    f_res = f\_mount(&fs, "0:", 1);
    
    /\*----------------------- 格式化测试 ---------------------------\*/
    printf("\r\n\*\*\*\*\*\* Register the file system object to the FatFs module \*\*\*\*\*\*\r\n");
    /\* 如果没有文件系统就格式化创建创建文件系统 \*/
    if(f_res == FR_NO_FILESYSTEM)
    {
        printf("The SD card does not yet have a file system and is about to be formatted...\r\n");
        /\* 格式化 \*/
        f_res = f\_mkfs("0:", 0, 0);
        if(f_res == FR_OK)
        {
            printf("The SD card successfully formatted the file system\r\n");
            /\* 格式化后,先取消挂载 \*/
            f_res = f\_mount(NULL, "0:", 1);
            /\* 重新挂载 \*/
            f_res = f\_mount(&fs, "0:", 1);
        }
        else
        {
            printf("The format failed\r\n");


![img](https://img-blog.csdnimg.cn/img_convert/fe5aecbb5e1fca87211baa58f7eceb0e.png)
![img](https://img-blog.csdnimg.cn/img_convert/e5f41dad65d1d8e15118f68e29b50901.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

format failed\r\n");


[外链图片转存中...(img-1QpMBKqo-1715908287210)]
[外链图片转存中...(img-zxEXh9Fv-1715908287210)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值