当前位置: 首页 > news >正文

STM32完全学习——FATFS0.15移植SD卡

一、下载FATFS源码

大家都知道使用CubMAX可以很快的将,FATFS文件管理系统移植到单片机上,但是别的芯片没有这么好用的工具,就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题,然后再移植FATFS文件管理系统。

二、SD卡的DMA读写实现

 这个我们直接使用工具生成就可以了,需要注意上面的那几点,不然会工作不正常。为了让大家看得更加清楚,下面的几个函数下的都比较简单,没有过多的判断。尽可能地缩短代码。下面这几个函数的实现是必须的不能在减少了。

//获取卡的状态
uint8_t SD_GetCardState(void)
{HAL_SD_CardStatusTypeDef pStatus;if (HAL_SD_GetCardStatus(&hsd, &pStatus) != 0){return HAL_BUSY;}else{return HAL_OK;}}
void SD_ReadBlocks_DMA(uint8_t *buf, uint32_t sector, uint32_t cnt)
{HAL_SD_ReadBlocks_DMA(&hsd, buf, sector, cnt);//通过DMA读取SD卡n个扇区while(SD_GetCardState() != SD_TRANSFER_OK);//等待SD卡读完
}
uint8_t SD_WriteBlocks_DMA(uint8_t *buf, uint32_t sector, uint32_t cnt)
{HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)buf, sector, cnt);//通过DMA写SD卡n个扇区//等待SD卡写完while(SD_GetCardState()!=SD_TRANSFER_OK)
}

 三、FATFS中diskio.c里面相关函数的实现

#define DEV_FALSH   0
#define DEV_SD      1#define SECTOR_SIZE 4096               //定义扇区大小DSTATUS disk_status (BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{DSTATUS stat;switch (pdrv) {case DEV_FALSH :stat = EN25QXX_ReadSR();  //读取FLASH状态的函数return stat;case DEV_SD :stat = SD_GetCardState(); //读取SD卡状态的函数return stat;		}return STA_NOINIT;
}
DSTATUS disk_initialize (BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{DSTATUS stat = 0;;switch (pdrv) {case DEV_FALSH :   return stat;   //如果你在外面已经做过了相关模块的初始化啥的这里直接返回接可以了case DEV_SD :return stat;}return STA_NOINIT;
}
DRESULT disk_read (BYTE pdrv,		/* Physical drive nmuber to identify the drive */BYTE *buff,		/* Data buffer to store read data */LBA_t sector,	/* Start sector in LBA UINT count		/* Number of sectors to read */
)
{uint32_t i = 0;uint8_t result = 0;switch (pdrv) {case DEV_FALSH :{uint32_t addr = sector*SECTOR_SIZE;for (i=0; i<count; i++){EN25QXX_Read((BYTE *)buff, addr, SECTOR_SIZE);addr += SECTOR_SIZE;buff += SECTOR_SIZE;}return RES_OK;}case DEV_SD :{SD_ReadBlocks_DMA(buff, sector, count);return RES_OK;}}return RES_PARERR;
}

 这里需要注意的是FLASH和SD卡里面的两个函数是不太一样的,FLASH里面的函数只能写一个扇区,要想写多个扇区那你就得循环写,在FATFS文件系统里面,他的sector地址是从0-0xffffffff他是一个连续的地址,一个sector就是一个地址,但是在FLASH里面他的最小单位不是扇区,他有比扇区更小的操作也就是页,但是他最小的单位是可以按字节来读取的,也就是说他是一个字节一个地址,如果我们直接将FATFS里面的地址传过来,在FLASH里面他就会认为是字节地址,因此我们需要一个地址的偏移,也就是FLASH里面一个扇区的大小,也就是4096.理解这里你需要知道他们呢两个的基本操作的单元是不一样的。但是在SD卡里面就不需要这样的偏移,因为SD卡里面他就是以扇区为大小来进行读取的。也就是SD卡里面每个地址是512个字节。他的最小读写单元就是512个字节,也就是一个扇区。因此我们在传入参数的时候不需要将地址进行偏移。而且SD卡的读写函数是一次可以读多个扇区的,因此可以直接将count传入,他也是可以直接读的。其实说白了就是如果你的最小读写单元就是512个字节那么你就不需要地址的偏倚,否则你就要根据自己设置的扇区大小进行偏移。

DRESULT disk_write (BYTE pdrv,			/* Physical drive nmuber to identify the drive */const BYTE *buff,	/* Data to be written */LBA_t sector,		/* Start sector in LBA */UINT count			/* Number of sectors to write */
)
{uint32_t i = 0;uint8_t result = 0;switch (pdrv) {case DEV_FALSH :{uint32_t addr = sector*SECTOR_SIZE;for (i=0; i<count; i++){EN25QXX_Erase_Sector(addr);EN25QXX_Write_Sector((BYTE *)buff, addr, SECTOR_SIZE);addr += SECTOR_SIZE;buff += SECTOR_SIZE;}return RES_OK;}case DEV_SD :{SD_WriteBlocks_DMA((BYTE *)buff, sector, count);return RES_OK;}}return RES_PARERR;
}
DRESULT disk_ioctl (BYTE pdrv,		/* Physical drive nmuber (0..) */BYTE cmd,		/* Control code */void *buff		/* Buffer to send/receive control data */
)
{
//	DRESULT res = 0;
//	int result;switch (pdrv) {case DEV_FALSH :{switch (cmd){case CTRL_SYNC:return RES_OK;case GET_SECTOR_COUNT:{*(DWORD *)buff = 4096;     //表示扇区的个数return RES_OK;}		case GET_SECTOR_SIZE:{*(WORD *)buff = SECTOR_SIZE;  //表示每个扇区的大小return RES_OK;}	}}case DEV_SD :{switch (cmd){case CTRL_SYNC:return RES_OK;case GET_SECTOR_COUNT:{*(DWORD *)buff = 31116288;     //表示扇区的个数return RES_OK;}		case GET_SECTOR_SIZE:{*(WORD *)buff = 512;  //表示每个扇区的大小return RES_OK;}	case GET_BLOCK_SIZE:{*(DWORD *)buff = 512;  //表示每个扇区的大小return RES_OK;}default :return RES_PARERR;}}}return RES_PARERR;
}

上面这个函数的实现我是直接将数据写到里面的,这样操作如果换了别的SD卡,就完蛋了,严谨一点的操作是使用相关函数,读出来。我这里就比较粗糙的实现了,主打一个能用就行。

四、进行挂载

如果你的挂载直接就返回0,那么恭喜你直接就成功了,但是在大多数的情况下我们的挂载是不能成功的。下面就针对几个返回值进行故障的排除。

f_mount返回11  也就是你要使用几个外设,如果你就一个SD卡,那么问题,如果有2个你这里就得改成2,不然就会返回错误代码11

 f_mount返回1,当这些函数没有正确的返回值就会报这个错误,我将哪里注释掉之后,就会产生这个错误。

还有一种就是返回值是13的错误,他的意思是卡上面没有文件系统导致的。但是我将卡格式化后发现,还是识别不上。还是返回13。经过一夜的查找发现是DMA设置那里没有设置地址的递增,就导致他一次只能读几个字节,后面的读写完全就是不正常的,内存里面是有一个缓冲区的,如果地址传完不发生偏移,那这个缓冲区就是没有意义的,因此只要你传入的DMA里面的buf[]数组里面的元素不止一个那么这里就得设置地址偏移。

	res = f_mount(&fs, "1:/", 1);

 一般来讲只要能挂载成功,其他的函数都是可以正常工作的,前提是你挂载的时候,后面选项里面一定要是 1,如果是0,就算有问题,他写会显示挂载成功的,这时候肯定是不行的。

相关文章:

STM32完全学习——FATFS0.15移植SD卡

一、下载FATFS源码 大家都知道使用CubMAX可以很快的将&#xff0c;FATFS文件管理系统移植到单片机上&#xff0c;但是别的芯片没有这么好用的工具&#xff0c;就需要自己从官网下载源码进行移植。我们首先解决SD卡的驱动问题&#xff0c;然后再移植FATFS文件管理系统。 二、SD…...

Linux -- 生产消费模型之环形队列、信号量

目录 前言 环形队列 如何用环形队列实现生产消费模型&#xff1f; 信号量 sem_t sem_init&#xff08;初始化信号量&#xff09; sem_destroy&#xff08;销毁信号量&#xff09; 什么是PV操作&#xff1f; sem_wait&#xff08;P操作&#xff0c;减少信号量&#xff…...

Ashy的考研游记

文章目录 摘要12.1112.2012.21 DAY1&#xff08;政治/英语&#xff09;政治英语 12.22 DAY2&#xff08;数学/专业课&#xff09;数学专业课 结束估分 摘要 在24年的12月里&#xff0c;Ashy完成了他的考研冲刺&#xff0c;顺利的结束了他本年度的考研之旅。 在十二月里&#…...

MySQL线上事故:使用`WHERE`条件`!=xxx`无法查询到NULL数据

前言 在一次 MySQL 的线上查询操作中&#xff0c;因为 ! 的特性导致未能正确查询到为 NULL 的数据&#xff0c;险些引发严重后果。本文将详细解析 NULL 在 SQL 中的行为&#xff0c;如何避免类似问题&#xff0c;并提供实际操作建议。 1. 为什么NULL会查询不到&#xff1f; 在…...

vue3学习笔记(11)-组件通信

1.props 父传子 子传夫 父传子 接收用defineProps([]) 空字符串也是假 2.自定义事件 $event:事件对象 ref定义的数据在模板里面引用的时候可以不用.value 3.子传父 宏函数 触发事件 声明事件 defineEmits() 挂载之后3s钟触发 4.命名 肉串命名 5.任意组件通信 mitt pubs…...

【PDF物流单据提取明细】批量PDF提取多个区域内容导出表格或用区域内容对文件改名,批量提取PDF物流单据单号及明细导出表格并改名的技术难点及小节

相关阅读及下载&#xff1a; PDF电子物流单据&#xff1a; 批量PDF提取多个区域局部内容重命名PDF或者将PDF多个局部内容导出表格&#xff0c;具体使用步骤教程和实际应用场景的说明演示https://mp.weixin.qq.com/s/uCvqHAzKglfr40YPO_SyNg?token720634989&langzh_CN扫描…...

张量与数据类型

Pytorch最基本的操作对象——张量&#xff08;tensor&#xff09;&#xff0c;张量是Pytorch中重要的数据结构&#xff0c;可认为是一个高维数组。一般的&#xff0c;标量&#xff08;scalar&#xff09;是只有大小没有方向的量&#xff0c;如1、2、3等&#xff1b;向量&#x…...

torchvision.utils.make_grid 解释下

torchvision.utils.make_grid 是 PyTorch 中 torchvision 库提供的一个实用函数,用于将多个图像拼接成一个网格,方便进行可视化。 主要功能 make_grid 将一批图片组织成一个网格形式,输出一个单一的张量,便于使用可视化工具(如 Matplotlib)查看图像。 参数解释 torchvi…...

Android原生Widget使用步骤

需要创建三个XML文件以及一个Class文件 三个XML文件分别是 Widget布局文件 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_p…...

实验八 指针2

7-1 利用指针返回多个函数值 分数 30 全屏浏览 切换布局 作者 陈晓梅 单位 广东外语外贸大学 读入n个整数&#xff0c;调用max_min()函数求这n个数中的最大值和最小值。 输入格式: 输入有两行&#xff1a; 第一行是n值&#xff1b; 第二行是n个数。 输出格式: 输出最大…...

1 数据库(下):多表设计 、多表查询 + SQL中的with查询语法(MySQL8.0以后版本才支持这种新语法)+ 数据库优化(索引优化)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、多表设计1 多表设计-概述2 三种多表关系一对多&#xff08;多对一&#xff09;&#xff08;1&#xff09;无外键约束&#xff08;逻辑外键&#xff09;&…...

什么是.net framework,什么是.net core,什么是.net5~8,版本对应关系

我不知道有多少人和我一样&#xff0c;没学习过.netCore&#xff0c;想要学习&#xff0c;但是版本号太多就蒙了&#xff0c;不知道学什么了&#xff0c;这里解释下各个版本的关系 我们一般开始学习微软的时候&#xff0c;都是开始学习的.netframework&#xff0c;常用的就是4…...

vulhub-wordpress靶场

一.主题上传漏洞 来到靶场点击主题选择add new 这里有一个上传主题的地方 我们可以去网上找到wordpress主题下载一个 wordpress模板 网页设计模板 免费 免费下载 - 爱给网 下载完成后对我们有用的东西只有这一个目录&#xff0c;把它拖出来 点开moban目录后&#xff0c;创建…...

安装与配置

《PHP Libxml》是一个在PHP中处理XML和HTML文档的重要库。它提供了丰富的API&#xff0c;支持DOM、SimpleXML和XMLReader等多种解析方式&#xff0c;广泛应用于各种编程语言和项目中。 安装与配置 安装: 在PHP中&#xff0c;libxml扩展通常是默认启用的。如果你需要手动安装&…...

斗鱼Android面试题及参考答案

常用的图片框架有哪些? Glide:是一个快速高效的 Android 图片加载库,专注于平滑滚动。它支持多种图片格式,包括 GIF,具有高效的缓存策略,能自动管理图片的生命周期,避免内存泄漏和 OOM 错误。其 API 简洁易用,可轻松实现图片的加载、显示和缓存等功能,如一行代码即可实…...

Could not install Gradle distribution from 的解决办法

在安装完成AndroidStudio之后,运行工程出现如下错误 Could not install Gradle distribution from https://services.gradle.org/distributions/gradle-6.5-bin.zip. 错误原因是:对应版本的Gradle文件下载失败了,我这里是gradle-6.5-bin.zip,不同版本的android studio也可…...

基于 SensitiveWordBs 实现敏感词过滤功能

在现代的互联网应用中&#xff0c;敏感词过滤已成为一个必不可少的功能&#xff0c;尤其是在社交媒体、评论审核等需要保证内容健康的场景下。本文将基于开源库https://github.com/houbb/sensitive-word&#xff0c;详细讲解如何通过自定义敏感词库和工具类实现高效的敏感词过滤…...

网络安全威胁2024年中报告

下载地址&#xff1a; 网络安全威胁2024年中报告-奇安信...

批次特征组杂记

批次特征组杂记 运维的时候新增了一个批次特征&#xff0c;然后发现不能按照要求跑到之前已经分好的批次特征组。 研究了半天原来是通过布局实现的。 特此记录。...

【HarmonyOS】解决自定义弹框和键盘之间安全距离的问题

【HarmonyOS】解决自定义弹框和键盘之间安全距离的问题 一、问题背景 我们在应用开发评论输入框时&#xff0c;常规的需求样式是&#xff1a;输入框view和键盘贴近&#xff0c;上半部展示信息区的形式&#xff0c;这样的设计&#xff0c;方便用户不割裂的去评论发言。 但是在…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...