Bootstrap

基于STM32的对SD卡的数据读取

SD卡(Secure Digital Memory Card)在我们的生活中已经非常普遍了,控制器对SD卡进行读写通信操作一般有两种通信接口可选,一种是 SPI接口,另外一种就是 SDIO接口。SDIO 全称是 安全数字输入/输出接口,多媒体卡(MMC)、SD卡、SD I/O卡 都有 SDIO接口。STM32F103系列控制器有一个 SDIO主机接口,它可以与 MMC卡、SD卡、SD I/O卡 以及 CE-ATA 设备进行数据传输。

一、SD卡协议简介

1、SD卡物理结构

    一般SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器 5个部分。

在这里插入图片描述

1、 存储单元是存储数据部件,存储单元通过存储单元接口与卡控制单元进行数据传输;
2、电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时,它会使控制单元和存储单元接口复位;
3、卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器;
接口驱动器控制SD卡引脚的输入输出。SD卡总共有8个寄存器,用于设定或表示SD卡信息。

这些寄存器只能通过对应的命令访问,SDIO定义64个命令,每个命令都有特殊意义,可以实现某一特定功能,SD卡接收到命令后,根据命令要求对SD卡内部寄存器进行修改,程序控制中只需要发送组合命令就可以实现SD卡的控制以及读写操作。

2、SD卡寄存器列表:

在这里插入图片描述

3、SD卡的命令格式

命令CMD0就是0,CMD16就是16,以此类推。

SPI命令格式为6字节构成,高位在前(MSB)。
 在这里插入图片描述
字节1的最高2位固定是01,低6位为命令号(CMD0就是0,CMD16就是16,以此类推),字节2-5为命令参数,有些命令是没有参数的;字节6的高7位为CRC,最低位恒为1。
 
SD卡的命令总共有12类,下表为几个比较重要的命令:
在这里插入图片描述

4、SD卡的初始化

1、初始化与SD卡连接的硬件条件(MCU的SPI配置,IO口配置);

2、上电延时(>74个CLK);

3、复位卡(CMD0),进入IDLE状态;

4、发送CMD8,检查是否支持2.0协议;

5、根据不同协议检查SD卡(命令包括:CMD55、CMD41、CMD58和CMD1等);

6、取消片选,发多8个CLK,结束初始化

5、SD卡读取数据

1、发送CMD17;

2、接收卡响应R1;

3、接收数据起始令牌0XFE;

4、接收数据;

5、接收2个字节的CRC,如果不使用CRC,这两个字节在读取后可以丢掉。

6、禁止片选之后,发多8个CLK。

二、硬件准备

1、SD卡模块及SD卡简介

在这里插入图片描述
内部结构:
在这里插入图片描述

在这里插入图片描述

2、连线

在这里插入图片描述
实物图:
在这里插入图片描述

三、实验过程

完整代码
提取码:tqku

1、代码分析

main主函数:
在这里插入图片描述
write_cnt=0, 从0开始写入。
在这里插入图片描述
写入函数WritetoSD

void WritetoSD(BYTE write_buff[],uint8_t bufSize)
{
	FATFS fs;
	FIL file;
	uint8_t res=0;
	UINT Bw;	
	
	res = SD_init();		//SD卡初始化
	
	if(res == 1)
	{
		printf("SD卡初始化失败! \r\n");		
	}
	else
	{
		printf("SD卡初始化成功! \r\n");		
	}
	
	res=f_mount(&fs,"0:",1);		//挂载
	
//	if(test_sd == 0)		//用于测试格式化
	if(res == FR_NO_FILESYSTEM)		//没有文件系统,格式化
	{
//		test_sd =1;				//用于测试格式化
		printf("没有文件系统! \r\n");		
		res = f_mkfs("", 0, 0);		//格式化sd卡
		if(res == FR_OK)
		{
			printf("格式化成功! \r\n");		
			res = f_mount(NULL,"0:",1); 		//格式化后先取消挂载
			res = f_mount(&fs,"0:",1);			//重新挂载	
			if(res == FR_OK)
			{
				printf("SD卡已经成功挂载,可以进进行文件写入测试!\r\n");
			}	
		}
		else
		{
			printf("格式化失败! \r\n");		
		}
	}
	else if(res == FR_OK)
	{
		printf("挂载成功! \r\n");		
	}
	else
	{
		printf("挂载失败! \r\n");
	}	
	
	res = f_open(&file,SD_FileName,FA_OPEN_ALWAYS |FA_WRITE);
	if((res & FR_DENIED) == FR_DENIED)
	{
		printf("卡存储已满,写入失败!\r\n");		
	}
	
	f_lseek(&file, f_size(&file));//确保写词写入不会覆盖之前的数据
	if(res == FR_OK)
	{
		printf("打开成功/创建文件成功! \r\n");		
		res = f_write(&file,write_buff,bufSize,&Bw);		//写数据到SD卡
		if(res == FR_OK)
		{
			printf("文件写入成功! \r\n");			
		}
		else
		{
			printf("文件写入失败! \r\n");
		}		
	}
	else
	{
		printf("打开文件失败!\r\n");
	}	
	
	f_close(&file);						//关闭文件		
	f_mount(NULL,"0:",1);		 //取消挂载
	
}

可以输出自己想要的文件内容
在这里插入图片描述

2、编译烧录

在这里插入图片描述

在这里插入图片描述

3、查看结果

打开串口助手
在这里插入图片描述
可以看到第一次没有初始化成功,注意接线是否接好,多按一按防止因为接线问题没有成功。
在这里插入图片描述
11次后确实输出while
将SD卡转移到读卡器查看文件
在这里插入图片描述
在这里插入图片描述
可以看到文件乱码
在这里插入图片描述
将图示两行注释掉,发现没有乱码,但是每行前有空格
在这里插入图片描述

四、总结

本次实验了解了SD卡的数据读取,实验只是利用别人的代码简单实现传输,但在实验过程中出现的小问题很多,比如接线接触不好,接3.3V无法成功传输,要注意细节,多耐心调整。
参考:
https://blog.csdn.net/m0_53089598/article/details/121985861

;