STM32CUBEMX_SDIO和FATFS_读写SD卡

news2024/12/24 22:11:36

STM32CUBEMX_SDIO和FATFS_读写SD卡

简述
FATFS是一个完全免费开源,专为小型嵌入式系统设计的FAT(File Allocation Table)文件系统模块。FATFS的编写遵循ANSI C,并且完全与磁盘I/O层分开。支持FAT12/FAT16/FAT32,支持多个存储媒介,有独立的缓冲区,可对多个文件进行读写。兼容Windows文件系统。

1、使用STM32cubemx配置工程
2、移植工程测试SD卡的读写

1、配置外部时钟
在这里插入图片描述
2、配置st-link调试接口
在这里插入图片描述
3、配置SDIO的模式
在这里插入图片描述
4、配置FATFS文件系统
在这里插入图片描述
5、栈调大一点
在这里插入图片描述
6、移植工程

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "fatfs.h"
#include "sdio.h"
#include "usb_device.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @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_SDIO_SD_Init();
  MX_FATFS_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
	uint32_t byteswritten;                /* File write counts */
	uint32_t bytesread;                   /* File read counts */
	uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
	uint8_t rtext[100];                   /* File read buffers */
	char filename[] = "STM32cube.txt";
	char SensorBuff[100];
	usb_printf("********* STM32CubeMX FatFs Example *********\r\n\r\n");
	/**********新建STM32cube.txt并写入字符串**********/	
	if(f_mount(&SDFatFS,SDPath,1) == FR_OK){
    	usb_printf("f_mount sucess!!! \r\n");
		if(f_open(&SDFile,filename,FA_CREATE_ALWAYS|FA_WRITE) == FR_OK){
      		usb_printf("f_open file sucess!!! \r\n");
			if(f_write(&SDFile,wtext,sizeof(wtext),&byteswritten) == FR_OK){
        		usb_printf("f_write file sucess!!! \r\n");
        		usb_printf("f_write Data : %s\r\n",wtext);
				if(f_close(&SDFile) == FR_OK)
					usb_printf("f_close sucess!!! \r\n");
				else
					usb_printf("f_close error : %d\r\n",retSD);
      		}
			else
				usb_printf("f_write file error\r\n");    
    	}
		else
			usb_printf("f_open file error\r\n");  
  	}else
		usb_printf("f_mount error : %d \r\n",retSD);
	/**********新建STM32cube.txt并写入字符串**********/	
		
	/**********读取STM32cube.txt内容*********/	
	retSD = f_open(&SDFile, filename, FA_READ);
	if(retSD)
			usb_printf("f_open file error : %d\r\n",retSD);
	else
			usb_printf("f_open file sucess!!! \r\n");

	retSD = f_read(&SDFile, rtext, sizeof(rtext), (UINT*)&bytesread);
	if(retSD)
			usb_printf("f_read error!!! %d\r\n",retSD);
	else{
			usb_printf("f_read sucess!!! \r\n");
			usb_printf("f_read Data : %s\r\n",rtext);
	}

	retSD = f_close(&SDFile);
	if(retSD)
			usb_printf("f_close error!!! %d\r\n",retSD);
	else
			usb_printf("f_close sucess!!! \r\n");

	if(bytesread == byteswritten)
			usb_printf("FatFs is working well!!!\r\n");
	/**********读取STM32cube.txt内容*********/	

	/*********模拟传感器数据存储在Sensor.csv表格文件中**********/	
	if(f_open(&SDFile,(const char*)"Sensor.csv",FA_CREATE_ALWAYS|FA_WRITE) == FR_OK){
		usb_printf("Sensor.csv was opened/created!!!\r\n");
		sprintf(SensorBuff, "Item,Temp,Humi,Light\r\n");
		f_write(&SDFile,SensorBuff,strlen(SensorBuff),&byteswritten);
	
		for(int i = 0; i < 10; i++){
			sprintf(SensorBuff, "%d,%d,%d,%d\r\n",i + 1, i + 20, i + 30, i + 40);
			f_write(&SDFile,SensorBuff,strlen(SensorBuff),&byteswritten);
			f_sync(&SDFile);
		}
		f_close(&SDFile);
	}
	/*********模拟传感器数据存储在Sensor.csv表格文件中**********/	

  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
		usb_printf("%s","hello");
		HAL_Delay(500);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

7、执行效果
在这里插入图片描述
8、把SD卡插入电脑可以看到其中的文件
在这里插入图片描述
9、介绍几个常用操作函数

f_mount:在FATFS模块上注册/注销一个工作区(文件系统对象)

FRESULT f_mount(FATFS* fs, const TCHAR* path, BYTE opt);
参数--> fs:fs工作区(文件系统对象)指针,如果赋值为 NULL 可以取消物理设备挂载
		path:注册/注销工作区的逻辑设备编号,使用设备根路径表示
		opt:注册或注销选项(可选01),0表示不立即挂载,1表示立即挂载

f_mkfs:格式化物理设备

FRESULT f_mkfs(const TCHAR* path, BYTE sfd, UINT au);
参数--> path:逻辑设备编号,使用设备根路径表示
		sfd:01,0表示为硬盘设备;1表示为软盘设备
		au:指定扇区大小,若为0表示通过disk_ioctl函数获取

f_open:创建/打开一个文件对象

FRESULT f_open(FIL* fp, const TCHAR* path, BYTE mode);
参数--> fp:将创建或打开的文件对象指针
		path:文件名指针,指定将创建或打开的文件名(包含文件类型后缀名)
		mode:访问类型和打开方法
mode可选值:
FA_READ		指定读访问对象。可以从文件中读取数据。 与FA_WRITE结合可以进行读写访问。   
FA_WRITE	指定写访问对象。可以向文件中写入数据。与FA_READ结合可以进行读写访问。   
FA_OPEN_EXISTING	打开文件。如果文件不存在,则打开失败。(默认)  
FA_OPEN_ALWAYS		如果文件存在,则打开;否则,创建一个新文件。  
FA_CREATE_NEW   	创建一个新文件。如果文件已存在,则创建失败。   
FA_CREATE_ALWAYS  	创建一个新文件。如果文件已存在,则它将被截断并覆盖。

f_close:关闭一个打开的文件

FRESULT f_close (FIL *fp)
参数--> fp:将被关闭的已打开的文件对象结构的指针

f_write:写入数据到一个已打开的文件

FRESULT f_write (FIL* fp, const void *buff, UINT btw, UINT* bw)
参数--> fp:指向将被写入的已打开的文件对象结构的指针
		buff:指向存储写入数据的缓冲区的指针
		btw:要写入的字节数
		bw:指向返回已写入字节数的UINT变量的指针,返回为实际写入的字节数

f_read:从一个打开的文件中读取数据

FRESULT f_read (FIL* fp, const void *buff, UINT btr, UINT* br)
参数--> fp:指向将被读取的已打开的文件对象结构的指针
		buff:指向存储读取数据的缓冲区的指针
		btr:要读取的字节数
		br:指向返回已读取字节数的UINT变量的指针,返回为实际读取的字节数

10、电路图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/126236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django入门

Django 中文官网&#xff1a;初识 Django | Django 文档 | Django (djangoproject.com) Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。 使用 Django&#xff0c;只要很少的代码&#xff0c;Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部…

Python 学习笔记001-发布

Python 学习笔记001-发布Python如何发布为EXE文件发给别人装X0 我的开发环境Step 1 安装PyInstaller包Step2 打包Python文件Step 3 运行Python程序Step 4 最后附上Atm.py的代码Python如何发布为EXE文件发给别人装X 0 我的开发环境 Python : 3.10 PyCharm:2022.03 社区版 Ste…

VIAVI唯亚威光纤高分辨率多模 OTDR 测试方案

VIAVI Solutions 高分辨率多模 OTDR 测试方案设计用于飞机、宇宙飞船、潜艇和舰船中部署的超短多模光纤的特性分析和故障定位 高分辨率多模 OTDR 测试方案是业界紧凑、轻巧的便携装置。它的用户界面经过专门设计&#xff0c;简化了 OTDR 测试和结果读取。 特点 紧凑、轻巧、现…

Oracle --- 视图 索引 语法结构

目录 视图 概念 优点 创建视图 查看视图 ​修改视图 删除视图 索引 概念 分类 普通索引 唯一索引 复合索引 反向键索引 位图索引 存储函数 概念 语法结构 视图 概念 视图 是一种数据库对象&#xff0c;是从 一个或者多个 数据表或视图中导出的 虚表。 视图所…

C#,图像二值化(07)——全局阈值的迭代算法及其源代码

1、 全局阈值的迭代算法 图像阈值分割---迭代算法 (1) 为全局阈值选择一个初始估计值T(图像的平均灰度)。 (2) 用T分割图像。产生两组像素&#xff1a;G1有灰度值大于T的像素组成&#xff0c;G2有小于等于T像素组成。 (3) 计算G1和G2像素的平均灰度值m1和m2&#xff1b; (4) …

机器学习笔记之Sigmoid信念网络(二)醒眠算法

机器学习笔记之Sigmoid信念网络——醒眠算法引言回顾Sigmoid\text{Sigmoid}Sigmoid信念网络的模型表示Sigmoid\text{Sigmoid}Sigmoid信念网络——对数似然梯度求解过程中的问题醒眠算法基于平均场假设变分推断求解后验概率平均场理论求解后验的弊端醒眠算法引言 上一节介绍了对…

jsp+servlet+mysql实现的在线图书商城源码附带论文开题报告及视频指导教程

今天给大家演示的是一款由jspservletmysql实现的在线图书商城系统&#xff0c;主要分为前台后后台管理员功能&#xff0c;前台用户可以浏览查看各类图书信息&#xff0c;可自定义搜索&#xff0c;注册登录后可以将书添加到购物车&#xff0c;购物车中的商品可以提交订单&#x…

【复习笔记】JavaWeb实验重点代码

JavaWeb实验重点代码笔记 一、课上练习题目汇总&#xff08;部分&#xff09; 题目一 基础HTML、CSS和JavaScript 1.1 问题要求 页面上有下拉菜单、文本框、跳转按钮并排放置&#xff0c;当下拉菜单选中某个具体网站名称时&#xff0c;文本框出现其对应的链接地址&#xff0…

Linux环境下vs code中Markdown与PlantUML联合工作

PlantUML是一个可以让你快速编写UML图的组件。 在线服务器 https://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000 Markdown是一种轻量级标记语言&#xff0c;排版语法简洁&#xff0c;让人们更多地关注内容本身而非排版。它使用易读易写的纯文本格式编写…

零膨胀泊松回归案例分析

零膨胀泊松回归分析 计数研究模型中&#xff0c;常用泊松回归模型&#xff0c;但泊松回归模型理论上是要求平均值与标准差相等&#xff0c;如果不满足&#xff0c;则可使用负二项回归模型 在实际研究中&#xff0c;会出现一种情况即因变量为计数变量&#xff0c;并且该变量包…

Lua闭包和Upvalue上值

一、lua中的作用域 在Lua语言中声明的变量默认是全局变量&#xff0c;声明局部变量需要使用local关键字&#xff0c;和其他语言相比这有点特殊。 -- 全局变量 a 10function func()b 100 -- 仍然是全局变量local c 20 -- func的局部变量 end func()print(a b) -- 输出…

终极.NET混淆器丨.NET Reactor产品介绍

无与伦比的 .NET 代码保护系统&#xff0c;可完全阻止任何人反编译您的代码。 产品优势 01、混淆技术 .NET Reactor通过向 .NET 程序集添加不同的保护层来防止逆向工程。除了标准的混淆技术之外&#xff0c;它还包括NecroBit、虚拟化、x86代码生成或防篡改等特殊功能。NET Re…

xilinx srio ip学习笔记之初识srio

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 xilinx srio ip学习笔记之初识srio前言IP 设置总结前言 因为工作原因&#xff0c;需要对rapidio 的协议进行了解&#xff0c;在xilinx的IP核中&#xff0c;是对应着Serial R…

这支隐藏“球队”,颠覆消费品「赛场」

【潮汐商业评论/原创】 大好的黄金周末&#xff0c;Fred约了几个朋友来家里看球。按照他的计划&#xff0c;周五准备下班后&#xff0c;他赶紧得去一趟附近的大型超市扫货&#xff0c;买一批零食酒水招待朋友。没想到的是&#xff0c;好不容易等到快下班了&#xff0c;领导通知…

外包呆一年,外包的工作经历怎么写?外包的项目经验怎么写?

0. 先来看下大家的各种问题&#xff1f; 外包的工作经历怎么写&#xff1f;外包的项目经验怎么写&#xff1f;外包如何优化简历&#xff1f;进入外包后黑化了简历&#xff0c;如何成功跳出外包圈&#xff1f;外包该如何提升自己&#xff1f;外包仔如何自我救赎&#xff1f; ……

前端基础_离线Web应用概述

离线Web应用概述 在Web应用中使用缓存的原因之一是为了支持离线应用。在全球互联的时代&#xff0c;离线应用仍有其实用价值。当无法上网的时候&#xff0c;你会做什么呢&#xff1f;你可能会说如今网络无处不在&#xff0c;而且非常稳定&#xff0c;不存在没有网络的情况。但…

【服务器数据恢复】误操作导致ocfs2文件系统被格式化的数据恢复案例

服务器故障&#xff1a; 用户误操作将linux文件系统误装入到Ocfs2文件系统的数据卷上&#xff0c;导致原始Ocfs2文件系统被格式化为Ext4文件系统。 因为Ext4文件系统每隔几百兆就会写入文件系统的原始信息&#xff0c;所以本案例中的原始Ocfs2文件系统中的数据可能受到一定程度…

搭建开源版个人图床

在微博图床、gitee、jsDelivr 陆续被 ban 的今天&#xff0c;很有必要搭建自己的图床系统了。 兰空图床 兰空图床官网&#xff1a;https://www.lsky.pro docker版本&#xff1a;https://hub.docker.com/r/halcyonazure/lsky-pro-docker 本次讲解使用 docker 版本进行部署使用 …

linux跟踪技术之ebpf

ebpf简介 eBPF是一项革命性的技术&#xff0c;起源于 Linux 内核&#xff0c;可以在操作系统内核等特权上下文中运行沙盒程序。它可以安全有效地扩展内核的功能&#xff0c;而无需更改内核源代码或加载内核模块。 比如&#xff0c;使用ebpf可以追踪任何内核导出函数的参数&…

漫画电学原理

电是什么 电压 电压是两点的电势差。 电流是指每秒在导线中流动的电量。 电功率是指在1s内消耗的电能。 电的本质是什么 万物都是有原子构成,原子有原子核(正电),核外电子(负电)构成。电子的定向移动形成了电。 电子离开原子,原子的电子减少,从而带正电。带正电的…