新版cubemx配置stm32f407vet6驱动在fatfs库下的sd卡读写

本文基于优信电子售卖的stm32f407vet6最小系统开发板使用vscode进行开发

开发过程中阅读了STM32CubeMX教程28 SDIO - 使用FatFs文件系统读写SD卡_stm32cubemx fatfs-CSDN博客

这位大佬的教程,写的十分详细,但是目前来看有一些版本更新之后的区别,因此在这里简单记录一下,防止自己之后再重新走一遍

初始化过程略过

时钟树配置

初始状态如下(芯片刚点进去就是这样)

分别在主页面开启

外部时钟:system core->RCC->HSC LSE->Crystal/Ceramic Resonator.(我的板子是8Mhz,之后在时钟树还得改)

开启sdio功能:connectivity->SDIO->mode->SD4bits wide bus(然后剩下的就都不用改了,我看之前的大佬说他版本的cubemx在设置四总线之后还得在代码里改一下,但在现在版本6.15.0cubemx里就不用了)

在上述步骤结束之后的时钟树配置应该是这样的,着重关注一下画圈的三个地方,在这仨地方都配置正确之后直接点击HCLK(就是下面标着最大频率的地方)在里面直接输入168敲一下回车整个时钟树就配置好了。系统会自动配置sdio的48Mhz的。

接下来配置fatfs文件库,下面图片的三个红圈,选上了就啥也不用管了,platform报错是因为没有设置sd卡检测引脚,我这个板子上也没有这个就放那不用管,之后出来的报错继yes就完事了。(如果板子上有相应硬件的情况下,需要在右边找对应引脚设置为input,然后在platform settings里面选择该引脚即可避免报错)(没有别瞎写啊)

选上这些之后生成的文件会多出来如下内容,如果只是使用的话绝大多数不用管,只需要点开其中ff.h文件,向下拉找到主函数要用的函数声明(我选的.c.h文件分离)

绝大多数都用不上,下面简单记录其中几句的使用方式


FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode);				/* Open or create a file */
FRESULT f_close (FIL* fp);											/* Close an open file object */
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br);			/* Read data from the file */
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw);	/* Write data to the file */
FRESULT f_lseek (FIL* fp, FSIZE_t ofs);								/* Move file pointer of the file object */
FRESULT f_truncate (FIL* fp);										/* Truncate the file */
FRESULT f_sync (FIL* fp);											/* Flush cached data of the writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path);						/* Open a directory */
FRESULT f_closedir (DIR* dp);										/* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno);							/* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);	/* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno);							/* Find next file */
FRESULT f_mkdir (const TCHAR* path);								/* Create a sub directory */
FRESULT f_unlink (const TCHAR* path);								/* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new);	/* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno);					/* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask);			/* Change attribute of a file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno);			/* Change timestamp of a file/dir */
FRESULT f_chdir (const TCHAR* path);								/* Change current directory */
FRESULT f_chdrive (const TCHAR* path);								/* Change current drive */
FRESULT f_getcwd (TCHAR* buff, UINT len);							/* Get current directory */
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs);	/* Get number of free clusters on the drive */
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn);	/* Get volume label */
FRESULT f_setlabel (const TCHAR* label);							/* Set volume label */
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf);	/* Forward data to the stream */
FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt);					/* Allocate a contiguous block to the file */
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt);			/* Mount/Unmount a logical drive */
FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len);	/* Create a FAT volume */
FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work);			/* Divide a physical drive into some partitions */
int f_putc (TCHAR c, FIL* fp);										/* Put a character to the file */
int f_puts (const TCHAR* str, FIL* cp);								/* Put a string to the file */
int f_printf (FIL* fp, const TCHAR* str, ...);						/* Put a formatted string to the file */
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);						/* Get a string from the file */

例子

在sd卡中创建一个名为test.txt的文件,向其中写入hello sd

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SDIO_SD_Init();
  MX_USART1_UART_Init();
  MX_FATFS_Init();
  /* USER CODE BEGIN 2 */
  UART1_Init();
////////////////////////////////////////////////////////
//主要是这段
  if (f_mount(&SDFatFS, SDPath, 1) == FR_OK)
{
    f_open(&SDFile, "test.txt", FA_CREATE_ALWAYS | FA_WRITE);
    f_puts("hello sd\r\n", &SDFile);
    f_close(&SDFile);

    UART1_SendString("SD card initialized and test.txt created.\r\n");
}
/////////////////////////////////////////////////////////

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
{
}

&后面跟着的所有变量都被定义在app里,使用者需要的只是按照位置填进函参里,不用自己去读写,每次写完了记得写个f_close,要不然容易写不进去,或者用f_sync(&SDFile);函数

想要连续写入得用f_lseek(&f, f_size(&f));,让指针往前推

模版如下

FIL f;
UINT bw;

f_open(&f, "log.txt", FA_OPEN_ALWAYS | FA_WRITE);
f_lseek(&f, f_size(&f));
f_write(&f, "hello\r\n", 7, &bw);
f_sync(&f);
f_close(&f);

同时操作两个文件的模版如下

FIL logFile;
FIL cfgFile;
UINT br, bw;

/* 打开日志文件(写) */
f_open(&logFile, "log.txt", FA_OPEN_ALWAYS | FA_WRITE);
f_lseek(&logFile, f_size(&logFile));

/* 同时打开配置文件(读) */
f_open(&cfgFile, "config.txt", FA_READ);

/* 写日志 */
f_write(&logFile, "tick\r\n", 6, &bw);

/* 读配置 */
char buf[32];
f_read(&cfgFile, buf, sizeof(buf), &br);

f_close(&cfgFile);
f_close(&logFile);

总结:cubemx是真的好用,sd卡的读写在使用内置的sdio协议后几乎不用人为配置什么,只有当自己需要同时操作复数个文件时才需要在fatfs.c文件中定义一个文件操作体

接下来尝试写一下方便操作的api库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值