使用CubeMX配置SDIO的4bit模式,对TF卡进行测试(MicroSD卡)

来自QQ群 Linux && 技术分享 311078264,有问题可以入群讨论
打开链接可以加入QQ群:https://jq.qq.com/?_wv=1027&k=5Gr3bAx

参考:
http://www.stmcu.org/module/forum/thread-604576-1-1.html
https://blog.csdn.net/zxh912516636/article/details/77679103

描述:使用STM32CubeMX,配置SDIO的4bit模式,对SD卡进行读写测试。
SDIO只支持SD模式,而不支持SPI模式。
SDIO支持MMC,CE-ATA,SD,SDIO等存储卡。

而SD存储卡则分为SD1.X和2.0(SDSC、SDHC标准和高容量两种)。这些信息可以使用SDIO读SD卡寄存器而实现。
我们常用的3个寄存器为OCR,CID,CSD,用不同的命令来读这三个寄存器,这三个寄存器作为命令响应返回给主机,其中有长响应和短响应。

一、配置CubeMX


在SDIO选项里,习惯性开启全局中断和DMA使能:

初始化SDIO:MX_SDIO_SD_Init();//这个函数由CubeMX生成并调用


下面的部分为新手经常缺少的操作,我看过的多数资料都没有提及:

为了保证SDIO正常工作,我们还要添加两个函数来初始化。这两个函数CubeMX没有生成调用,需要我们自己添加。
• HAL_SD_Init(&hsd, &SDCardInfo);
• HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B);

在bsp_driver_sd.c这个文件夹下面,BSP_SD_Init这个函数里就包括有以上提到的两句初始化代码。
所以实际在main函数中的用户代码段中调用该函数,既可配置成功,又没有重新添加代码的烦恼。

注:
我个人觉得上面的方法涉及到底层的函数,不是最合适的解决办法,我的解决方法是使用:
HAL_StatusTypeDef status = HAL_SD_Init(&hsd);
只需要上面这个一个函数就可以实现上面的功能,亲测有效。


介绍HAL_SD_Init的用法
这个函数用来初始化SD卡,CubeMX之所以没有生成这个函数的调用,具体原因不清楚。

如何检测SD卡是否在卡槽:
一、通过检测卡槽的CD引脚(通过电平或者中断方式)

二、轮询,通过不断调用 state = HAL_SD_GetCardState(&hsd);,查看返回值state来确定是否有卡
(这种方式浪费CPU的资源,而且检测方法太暴力了,推荐使用上面的方法)

到此CubeMX的配置完成,下面是测试的程序:
MX_GPIO_Init();

MX_SDIO_SD_Init();

void sd_test_thread(void *argument)
{
	HAL_StatusTypeDef status;   
	
	status = HAL_SD_Init(&hsd);
	if(status != HAL_OK)
	{
		printf("SD card initialize failed!\n");
		while(1) osDelay(1000);
	}
		
	while(1)
	{	
		HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(&hsd);
		
		if(state == HAL_SD_CARD_TRANSFER)
		{
			HAL_SD_GetCardCID(&hsd, &SD_CardCID);
			printf("\nInitialize SD card sucessfully!\n");
			printf("SD card information\n");
			printf("Capacity              :%llu\n", ((unsigned long long)hsd.SdCard.BlockSize*hsd.SdCard.BlockNbr));
			printf("BlockSize             :%d\n", hsd.SdCard.BlockSize);
			printf("RCA                   :%d\n", hsd.SdCard.RelCardAdd);
			printf("CardType              :%d\n", hsd.SdCard.CardType);
			printf("ManufacturerID        :%d\n", SD_CardCID.ManufacturerID);			
		}
		else
		{		
			printf("SD card initialize failed.\n");
		}	
		
		osDelay(1000);
	}	
}











使用 STM32CubeMX 配置 SDIO 接口进行 SD 读写操作时,如果出现数据乱码问题,可能是由于以下几个方面导致的: 1. **SD初始化配置错误** 在 STM32CubeMX 中,需要确保 SDIO 的初始化参数与 SD 的通信协议兼容。例如,SD 的块大小(Block Size)必须正确设置为 512 字节,否则可能导致数据传输异常[^4]。此外,在初始化过程中,需要确保发送 CMD0、CMD8、ACMD41 等命令以正确识别 SD 版本并进入正确的操作模式。 2. **文件系统挂载失败或格式不支持** 如果使用 FatFs 文件系统,需确保 FAT 分区表结构完整且格式化为 FAT32 或 exFAT 格式。若 SD 未被正确识别或挂载失败,则后续的读写操作将无法正常进行,从而导致数据错误或乱码。 3. **缓冲区对齐和内存访问问题** SDIO 数据传输通常依赖于 DMA 操作,因此必须确保用于读写的缓冲区地址是 4 字节对齐的。在 STM32 平台上,可以通过使用 `__ALIGN` 宏来定义缓冲区,如: ```c uint8_t buffer[512] __ALIGN(4); ``` 若缓冲区未对齐,DMA 可能无法正确访问内存,从而导致数据损坏。 4. **SPI/Sdio 通信速率设置过高** 初始阶段应使用较低的 SPI 或 SDIO 时钟频率(例如 400kHz),待 SD 初始化完成后再切换到高速模式(如 24MHz)。过高的通信速率可能导致数据采样错误,进而引起乱码。 5. **写入方式与文件流控制不当** 使用 FatFs 进行文件写入时,应确保每次写入后调用 `f_sync()` 函数以刷新缓冲区内容到物理介质。若未及时同步文件流,可能造成部分数据未实际写入 SD ,从而导致读取时出现异常内容[^2]。 6. **电源稳定性与硬件连接问题** SD 模块供电不稳定或信号线接触不良也可能引发数据传输错误。建议检查 VCC、GND、CLK、CMD、DAT0-DAT3 等引脚连接是否牢固,并使用上拉电阻保证信号完整性。 7. **代码逻辑错误或未处理返回状态** 在执行 SD 读写操作时,必须检查每个函数调用的返回值。例如,`HAL_SD_ReadBlocks()` 和 `HAL_SD_WriteBlocks()` 返回 HAL 状态,若为 `HAL_OK` 表示操作成功,否则应记录错误并采取相应恢复措施。 ### 示例代码片段:SD读写基本流程 ```c // 初始化SD if (HAL_SD_Init(&hsd) != HAL_OK) { // 错误处理 } // 读取一个扇区 uint8_t readBuffer[512]; if (HAL_SD_ReadBlocks(&hsd, readBuffer, 0, 1, HAL_MAX_DELAY) != HAL_OK) { // 错误处理 } // 写入一个扇区 uint8_t writeBuffer[512] = "Hello World"; if (HAL_SD_WriteBlocks(&hsd, writeBuffer, 0, 1, HAL_MAX_DELAY) != HAL_OK) { // 错误处理 } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值