本篇详细的记录了如何使用STM32CubeMX移植FATFS文件系统到SD卡上。
Serial Port Utility
;Keil MDK和串口助手Serial Port Utility 的安装包都可以在文末关注公众号获取,回复关键字获取相应的安装包:
打开STM32CubeMX,打开MCU选择器:
搜索并选中芯片STM32L431RCT6
:
这里我都使用外部时钟:
小熊派开发板板载ST-Link并且虚拟了一个串口,原理图如下:
这里我将开关拨到AT-MCU
模式,使PC的串口与USART1之间连接。
接下来开始配置USART1
:
知识小卡片 —— SDMMC接口
SDMMC接口的全称叫SD/SDIO MMC card host interface
,SD/SDIO MMC 卡 主机接口,通俗的来说,就是这个接口支持SD卡,支持SDIO设备,支持MMC卡。
知识小卡片结束啦~
首先查看小熊派开发板的原理图:
然后根据原理图配置 SDMMC 接口:
使用STM32CubeMX配置FATFS文件系统非常方便,只需要在软件中开启即可,软件会自动帮我们移植好。
这里需要修改两个配置:
STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz
即可:
因为之前开启FATFS选择了长文件名动态缓存在栈中,所以我们要将栈空间修改大一点:
最后设置生成独立的初始化文件:
点击GENERATE CODE
即可生成MDK-V5工程:
参考:【STM32Cube_09】重定向printf函数到串口输出的多种方法。
正常SD卡不需要该步骤!
如果已经使用SD卡进行了裸机读写SD卡的实验(【STM32Cube-19】使用SDMMC接口读写SD卡数据),那么需要注意:该实验中读写的是0扇区,实验之后已经破坏了SD卡的分区表和FAT文件系统信息!
重新建立SD卡的分区表和FAT文件系统有两种方法:
DiskGenius
软件重新分区和格式化这里我使用第二种方法,比较简单方便,如果对FATFS提供的API感兴趣,请前去FATFS官网查看:
首先使用读卡器将SD卡插到电脑上,会显示如下:
然后直接右键选择格式化:
如果第二种方法没用的话,可以使用第三种方法,来打开 DiskGenius
软件查看SD卡:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tF4pvH8V-1571741039011)(http://mculover666.cn/blog/20191022/10vaq858v4oe.png?imageslim)]
重新建立分区表并格式化:
之后可以看到SD卡恢复正常,可以进行FATFS实验啦:
注意:在挂载之前必须要保证SD卡正常拥有FAT文件系统。
挂载文件系统使用f_mount
API,该API将文件系统对象注册/注销到FatFs模块,API原型如下:
FRESULT f_mount (
FATFS* fs, /* [IN] Filesystem object */
const TCHAR* path, /* [IN] Logical drive number */
BYTE opt /* [IN] Initialization option */
);
在main.c文件中添加如下代码,先定义FATFS所使用的一些全局变量:
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
FATFS fs; /* FATFS 文件系统对象 */
FRESULT fr; /* FATFS API 返回值 */
/* USER CODE END PV */
然后在 main 函数中,while(1)之前添加如下代码:
/* USER CODE BEGIN 2 */
printf("FATFS test...\r\n");
/* 挂载SD卡 */
fr = f_mount(&fs, "", 0);
if(fr == FR_OK)
{
printf("SD card mount ok!\r\n");
}
else
{
printf("SD card mount error, error code:%d.\r\n",fr);
}
/* USER CODE END 2 */
编译下载,运行结果如下:
要想操作文件,需要先创建文件对象:
/* USER CODE BEGIN PV */
FATFS fs; /* FATFS 文件系统对象 */
FRESULT fr; /* FATFS API 返回值 */
FIL fd; /* FATFS 文件对象 */
/* USER CODE END 2 */
在main函数中的开始定义要写入文件的内容:
/* USER CODE BEGIN 1 */
//要操作的文件名
char filename[] = "test.txt";
//文件写入内容
uint8_t write_dat[] = "Hello,FATFS!\n";
//用于接收API返回写入成功的字节数
uint16_t write_num = 0;
/* USER CODE END 1 */
然后在挂载操作成功之后进行打开->写入->关闭
一个完整的操作:
/* 打开文件(若文件不存在则创建) */
fr = f_open(&fd, filename, FA_CREATE_ALWAYS | FA_WRITE);
if(fr == FR_OK)
{
printf("open file \"%s\" ok! \r\n", filename);
}
else
{
printf("open file \"%s\" error : %d\r\n", filename, fr);
}
/* 向打开的文件中写入内容 */
fr = f_write(&fd, write_dat, sizeof(write_dat), (void *)&write_num);
if(fr == FR_OK)
{
printf("write %d dat to file \"%s\" ok,dat is \"%s\".\r\n", write_num, filename, write_dat);
}
else
{
printf("write dat to file \"%s\" error,error code is:%d\r\n", filename, fr);
}
/* 操作完成,关闭文件 */
fr = f_close(&fd);
if(fr == FR_OK)
{
printf("close file \"%s\" ok!\r\n", filename);
}
else
{
printf("close file \"%s\" error, error code is:%d.\r\n", filename, fr);
}
实验结果如下:
再将SD卡插到电脑,可以看到文件及其内容:
同样的,先在main函数开始开辟一块缓冲区,用于存放读取的数据:
/* USER CODE BEGIN 1 */
//要操作的文件名
char filename[] = "test.txt";
//文件写入内容
uint8_t write_dat[] = "Hello,FATFS!";
//用于接收API返回写入成功的字节数
uint16_t write_num = 0;
//用于存放从文件中读取出的内容
uint8_t read_dat[20];
//用于接收API返回成功读取的字节数
uint16_t read_num = 0;
/* USER CODE END 1 */
然后进行打开->读取->关闭
一个完整的操作:
/* 打开文件用于读取 */
fr = f_open(&fd, filename, FA_READ);
if(fr == FR_OK)
{
printf("open file \"%s\" ok! \r\n", filename);
}
else
{
printf("open file \"%s\" error : %d\r\n", filename, fr);
}
/* 从打开的文件中读取内容 */
fr = f_read(&fd, read_dat, sizeof(read_dat), (void *)&read_num);
if(fr == FR_OK)
{
printf("read %d dat to file \"%s\" ok,dat is \"%s\".\r\n", read_num, filename, read_dat);
}
else
{
printf("read dat to file \"%s\" error,error code is:%d\r\n", filename, fr);
}
/* 操作完成,关闭文件 */
fr = f_close(&fd);
if(fr == FR_OK)
{
printf("close file \"%s\" ok!\r\n", filename);
}
else
{
printf("close file \"%s\" error, error code is:%d.\r\n", filename, fr);
}
实验现象如下:
不知道大家有没有注意到,在本文中所有使用FATFS API的时候,都是如下的格式:
FRESULT
类型的变量fr接收API返回值那么,API 所返回的错误码,有什么用呢?下面用一个实例来给大家演示一下~
假如本文中的实验现象如下:
可以看到,FATFS创建文件时,返回的错误码是13,那么如何定位该问题呢?13
代表什么?
打开FATFS的ff.h
文件即可看到所有错误码所表示的含义:
这样问题就定位到了,我们使用的SD卡是之前用于裸机实验的卡,SD卡分区被破坏,SD卡文件系统被破坏,所以FATFS创建文件时才会提示FR_NO_FILESYSTEM
问题。
至此,我们已经学会如何使用硬件SDMMC接口读取SD数据,STM32CubeMX系列教程完结。
更多精彩文章及资源,请关注我的微信公众号:『mculover666』。