HAL库 CubeMX STM32通过SDIO模式实现对SD卡的读写

您所在的位置:网站首页 单片机sd卡读写速度慢 HAL库 CubeMX STM32通过SDIO模式实现对SD卡的读写

HAL库 CubeMX STM32通过SDIO模式实现对SD卡的读写

2024-07-16 21:01| 来源: 网络整理| 查看: 265

开发环境: STM32CubeMX 5.6.0 Keil MDK 5.33 STM32F103RET6开发板 16G SD-Micro存储卡

SD卡

SD卡大家一定都不陌生,不过我想很多年龄不是很大的人(比如我)可能都对SD卡不是很了解,在我们的意识中,可能大家以为SD卡长这样在这里插入图片描述 不过这只是SD卡的一种,这种卡属于SD-Micro,是一种小型的卡,就如卡面上也写着Micro一样,当然SD卡除了这种卡之外,还有两种分别是SD和mini-SD,他们分别长这样:在这里插入图片描述 在这里插入图片描述 SD卡的四个角有一个是没有的,以便我们认识正反来使用它,SD卡的一侧还有一个可以扳动的读写保护开关,这三种卡里面SD卡最大,SD-Micro最小。在这里插入图片描述 根据SD卡的容量,可划分为SDSC(SD Standard Capacity)、SDHC(SD High Capacity)、SDXC(SD Extended Capacity)三种标准。现今,市场的主流SD产品是SDHC和SDXC这两种较大容量的存储卡,而SDSC卡因容量过小,已逐渐被市场淘汰。SD卡(三种卡的统称)的存储空间是由一个一个扇区组成的,SD卡的扇区大小是固定的,为512byte(这一点很重要) ,若干个扇区又可以组成一个分配单元(也被成为簇),分配单元常见的大小为4K、8K、16K、32K、64K。 需要注意的是,SD-Micro只有8个引脚,而SD卡是有九个引脚的,这两种都可以直线4线通讯。想了解更多关于SD卡的信息,给大家推荐一篇科普文:【科普】解密SD卡的种类、规格、速度、容量和寿命,附SD卡选购指南.

工程的创建

选中开发板之后,首先对系统内核进行配置:在这里插入图片描述 在这里插入图片描述 这里为什么选择TIM2,是因为我后面要用FreeRtos,FreeRtos要抢占SysTick,所以我要提前让出来。 然后配置SDIO和串口:在这里插入图片描述 我这里配置串口1是与串口调试助手交互,串口2我是为了与另一个板子通讯,不需要的可以忽略。 在这里插入图片描述 在这里插入图片描述 SDIO使用4线通讯,这样速度更快,关于clock divide的配置,这里要跟大家说一下,我们用的卡一般的频率为0~25MHz, 卡频率(SDIO_CK) = 适配器频率(SDIOCLK)/(2+分频值)。 这里的分频值便是clock divide,数值多少自己根据自己单片机SDIO模块所在总线的频率来确定。 接下来配置时钟树: 在这里插入图片描述 如图所示,我配置成了最大时钟频率:72MHz。此时SDIO总线上的频率为72MHz。 最后配置存储路径生成工程就可以了 在这里插入图片描述 在这里插入图片描述 到这里,我们的工程就创建完了。

代码编写

接下来接进行SD卡读取的代码编写,在代码编写之前,需要做些准备工作: 1、确定你的开发板上有SDIO模块 2、你的SD卡为一块小于或等于32G的存储卡,因为目前大多数单片机只支持SC和HC类型的卡,这与单片机所遵循的SD卡协议有关系,总之,你的单片机很有可能不支持XC类型的卡,如果确定支持XC的卡也可以用。 3、对你的SD卡用读卡器进行格式化,格式化为FAT32模式的文件系统,分配单元自己定,分配单元越小,空间利用率越高(第三步格式化为FAT32模式,也为用FatFs系统开发做准备)。 以上便是我们的准备工作,打开我们生成的工程之后,首先带领大家认识几个我们会用到的函数: 在stm32f1xx_hal_sd.c源文件中的SD卡初始化函数: 在这里插入图片描述 在stm32f1xx_hal_sd.c源文件中的SD卡擦除函数: 在这里插入图片描述 在stm32f1xx_hal_sd.c源文件中的SD卡对扇区写函数: 在这里插入图片描述 在stm32f1xx_hal_sd.c源文件中的SD卡对扇区读函数: 在这里插入图片描述 函数内具体怎么实现的我就不清楚了,本人能力有限,这也是我为什么应CubaMX的原因,对小白友好,如果读者也是初学者,大可不必取深究函数内部结构,只需要会用即可。 接下来展示代码: 别忘了声明头文件:

#include "stdio.h"

首先在/* Private define /下的/ USER CODE BEGIN PD /和/ USER CODE END PD */之间定义一些宏(不在这里定义也可以,但是这里是官方给大家定义的写宏的区域,我希望大家初学养成一个规范的好习惯)

#define BLOCK_SIZE 512 // SD卡块大小 #define NUMBER_OF_BLOCKS 1 // 测试块数量(小于15) #define WRITE_READ_ADDRESS 0x00000000 // 测试读写地址

然后在/* Private variables /下的/ USER CODE BEGIN PD /和/ USER CODE END PD */创建写数组和读数组

/* 注意我们这里设置的数字一个元素占4字节,元素个数为128个, 所以这一个数组申请的内存空间为512字节,正好为我们SD卡的一个扇区 */ __align(4) uint32_t Buffer_Block_Tx[BLOCK_SIZE*NUMBER_OF_BLOCKS/4]; //将要写入的数据放在这里,__align(4)是四字节对齐关键词 __align(4) uint32_t Buffer_Block_Rx[BLOCK_SIZE*NUMBER_OF_BLOCKS/4]; //将读出的数据放在此数组

接下来进行SD卡的读写操作 在/* USER CODE BEGIN 2 /和/ USER CODE END 2 */之间添加代码

HAL_SD_InitCard(&hsd); //初始化SD卡,注意句柄 if(HAL_SD_Erase(&hsd,WRITE_READ_ADDRESS,WRITE_READ_ADDRESS + 0x00000200) == HAL_OK) { printf("Erase Successful\r\n"); HAL_Delay(20); //如果不延时可能到值写操作失败 if(HAL_SD_WriteBlocks(&hsd, (uint8_t *)Buffer_Block_Tx, WRITE_READ_ADDRESS, NUMBER_OF_BLOCKS, 0xFFFF) == HAL_OK ) { printf("Write Successful\r\n"); HAL_Delay(20); if(HAL_SD_ReadBlocks(&hsd, (uint8_t *)Buffer_Block_Rx, WRITE_READ_ADDRESS, NUMBER_OF_BLOCKS, 0xFFFF) == HAL_OK) { printf("Raed Successful\r\n"); uint8_t j = 0; for(uint16_t i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3