本质: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模块】
待完成