本质:NandFlash+控制芯片





1)SDIO接口通信线:CLK/CMD/DAT0-3(数据传输线4根)
2)SPI接口通信线:CS/CLK/MOSI/MISO(数据传输线2根)
3)因为SDIO的传输数据线比SPI传输数据线多,所以SDIO的传输速度比SPI还快



比SD卡少一个电源引脚VSS2






【精选】STM32CubeMX学习笔记(26)——SDIO接口使用(读写SD卡)_stm32 读写sd卡_Leung_ManWah的博客-CSDN博客

SD 4 bits Wide bus四线SD模式




SDIO 外设支持生成 DMA 请求,使用 DMA 传输可以提高数据传输效率,因此在 SDIO 的控制代码中,可以把它设置为 DMA 传输模式或轮询模式,ST 标准库提供 SDIO 示例中针对这两个模式做了区分处理。
应用中一般都使用DMA 传输模式。

点击
DMA Settings添加 SDIO 对应 DMA2 的通道4。DMA模式选择循环模式,方向选为内存到外设。


- #include "stm32f4xx_hal.h"
-
- // SD卡句柄
- SD_HandleTypeDef hsd;
-
- // SD卡初始化
- void SD_Init(void) {
- hsd.Instance = SDIO;
- hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
- hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
- hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
- hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
- hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
- hsd.Init.ClockDiv = 0;
-
- if (HAL_SD_Init(&hsd) != HAL_OK) {
- Error_Handler();
- }
-
- if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK) {
- Error_Handler();
- }
- }
-
- // SD卡读取数据
- void SD_ReadBlocks(uint32_t *pData, uint32_t startBlock, uint32_t numBlocks) {
- if (HAL_SD_ReadBlocks(&hsd, pData, startBlock, numBlocks, HAL_MAX_DELAY) != HAL_OK) {
- Error_Handler();
- }
- }
-
- // SD卡写入数据
- void SD_WriteBlocks(uint32_t *pData, uint32_t startBlock, uint32_t numBlocks) {
- if (HAL_SD_WriteBlocks(&hsd, pData, startBlock, numBlocks, HAL_MAX_DELAY) != HAL_OK) {
- Error_Handler();
- }
- }
-
- // SD卡擦除块
- void SD_EraseBlocks(uint32_t startBlock, uint32_t numBlocks) {
- if (HAL_SD_Erase(&hsd, startBlock, numBlocks) != HAL_OK) {
- Error_Handler();
- }
- }
-
- int main(void) {
- // 初始化HAL库
- HAL_Init();
-
- // 配置系统时钟
- SystemClock_Config();
-
- // 配置GPIO和SDIO
- MX_GPIO_Init();
- SD_Init();
-
- // 读取数据
- uint32_t readBuffer[512];
- SD_ReadBlocks(readBuffer, 0, 1);
-
- // 写入数据
- uint32_t writeBuffer[512];
- // 填充写入数据
- SD_WriteBlocks(writeBuffer, 0, 1);
-
- // 擦除块
- SD_EraseBlocks(0, 1);
-
- while (1) {
- // 主循环
- }
- }
-
- // 错误处理函数
- void Error_Handler(void) {
- while (1) {
- // 发生错误时的处理
- }
- }
-
- // 系统时钟配置
- void SystemClock_Config(void) {
- // 你的时钟配置代码
- }
-
- // GPIO初始化
- void MX_GPIO_Init(void) {
- // 你的GPIO初始化代码
- }
SD卡在HAL库的函数调用流程:
路向1:HAL_SD_Init(hal_sd.c)--->HAL_SD_InitCard(hal_sd.c)-->SDIO_PowerState_ON(ll_sdmmc.c)--->这个只是单纯的使能sd卡
路线2:HAL_SD_Init(hal_sd.c)--->HAL_SD_InitCard(hal_sd.c)-->SD_InitCard(hal_sd.c)--->结束
sd.c中调用的寄存器底层实际上是调用sdmmc.c中的函数

底层操作寄存器的(硬件控制)


在这个函数中调用了【HAL_SD_InitCard】

这个函数包含以下功能:
1)SDIO_PowerState_ON():打开SDIO开关
2)SD_InitCard()【在hal库中】:这个是真正开始使能SDIO,初始化成功


在【HAL_SD_InitCard】中被调用

(1)参考项目驱动创新学习训练营中《基于X210的裸机时钟温度显示器》第2季课程
(2)文件系统(仓库管理员)是一套用来管理存储设备的软件
(3)文件系统给用户提供用文件访问存储的机制,比扇区式访问舒服
(1)网络搜索FAT32文件系统
FAT32指的是文件分配表是采用32位二进制数记录管理的磁盘文件管理方式,因FAT类文件系统的核心是文件分配表,命名由此得来。
(2)官网 http://elm-chan.org/fsw/ff/00index_e.html
(3)CubeMX工具包中middleware里包含了FAT32文件系统
(1)传统开发:自己到官网下载源码,自己移植,自己使用。
(2)CubeMX式开发:直接勾选,默认对接HAL库,少量移植即可使用。
(1)bug发现:f_mount(挂载)不成功,单步追查发现是MBR扇区(扇区0-->目录)读取不对
(2)bug验证:去掉FAT32,原工程中读写异常【应该是STM32中MDA的问题】
(1)研究DMA,尝试修改HAL库源码解决,不推荐。
(2)绕开DMA,使用阻塞读写函数来实现SD读写--》HAL_SD_WriteBlocks【删除DMA模块】
待完成