STM32之完成对SD卡的数据写入

本文内容:本文主要掌握SD卡协议原理,用STM32F103完成对SD卡的数据读取。

一、SD卡模块介绍

(一)简介

SD存储卡是一种基于半导体快闪记忆器的新一代记忆设备,由于它体积小、数据传输速度快、可热插拔等优良的特性,被广泛地于便携式装置上使用,例如数码相机、平板电脑和多媒体播放器等。控制器对 SD 卡进行读写通信操作一般有两种通信接口可选,一种是 SPI 接口,另外一种是 SDIO 接口。

(二)物理结构

一张SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器5 个部分。
存储单元是存储数据部件,存储单元通过存储单元接口与卡控制单元进行数据传输;
电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时,它会使控制单元和存储单元接口复位;
卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器;
接口驱动器控制 SD 卡引脚的输入输出。
在这里插入图片描述

二、依托协议

SD卡也是通过SPI协议进行通信,SPI协议在我之前的博客里有介绍过,这里不多做赘述。

SPI协议博客:
https://blog.csdn.net/m0_58414679/article/details/121411882?spm=1001.2014.3001.5501

三、实验过程

笔者目前的能力有限,还不能自己写出完整的SD卡读取程序,所以本实验主要是对现成的代码进行验证,工程放在网盘里了

链接:https://pan.baidu.com/s/1MFVI8M022kbmuOlGbAl6aw 提取码:xhc1

下面是

试错过程(可跳过)

开始,32只发送给上位机一个mian,怀疑是卡在某个函数没有进去
在这里插入图片描述
通过对函数的跟踪,发现是卡在这里没有出去
在这里插入图片描述
此函数下,在一些关键地方加入输出充当断点
在这里插入图片描述
发现程序只能输出到3
在这里插入图片描述
追踪发现卡在这里,这是一个发送命令的函数,说明32现在发送的命令不能被SD卡模块接受,后来用逻辑信号分析仪分析也确实是发送数据得不到响应(图这里就不放了,找不到了)
在这里插入图片描述
在这里插入图片描述
偶然间经老师点播或许可以5V供电试试
多次按复位键后依旧是原样的输出,正当我准备关掉上位机的时候,出现了4和5,SD卡初始化成功!
在这里插入图片描述
后面就是一些小的容易解决的问题了,虽说初始化成功了,但依旧挂载失败,怀疑是线太长了,更换短线之后,果然测试成功
在这里插入图片描述

正片(可直接跳转至此)

注意:
1.确保SD格式化成FAT文件模式
2.单片机的供电和SD卡模块的供电最好是5V,不然可能带不动
3.杜邦线连接要尽可能的短
4.连接最好紧一点,有时候稍微松一点就不行
5.可能要等一会才初始化成功,别急

四、代码分析

主函数

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_FATFS_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
	HAL_UART_Receive_IT(&huart1,&aRxBuffer1,1); 	//enable uart	

	printf(" mian \r\n");

	Get_SDCard_Capacity();	//得到使用内存并选择格式化



  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {		
		WritetoSD(WriteBuffer,sizeof(WriteBuffer));			
		HAL_Delay(500);
		WriteBuffer[0] = WriteBuffer[0] +0;
		WriteBuffer[1] = WriteBuffer[1] +1;
		write_cnt ++;		
		while(write_cnt > 10)
		{	
			printf(" while \r\n");
			HAL_Delay(500);
		}			
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

SD卡写入函数

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);		 //取消挂载
	
}

程序首先进行相关初始化,完成后输出mian,之后进行SD卡格式化,成功后进入循环,进入SD卡读写函数,先后进行SD卡的初始化,挂载,创文件,写入,写入超过10次,输出while

五、接线

SD卡STM32
CSPB0
SCKPA5
MISOPA6
MOSIPA7

在这里插入图片描述

六、实验结果

SD卡中生成一个新的hello.txt文件
内容如下
在这里插入图片描述
更改写入内容
在这里插入图片描述
只写入两次,效果如下
在这里插入图片描述

七、总结

本次实验并不难,只是没找到问题所在,花了很多时间来找错,虽说最后只是一个幼稚的错误吧,但却是一次宝贵的试错经验,我认为这时间花的值,感觉过程的价值已经大于结果了,在此记录,多年之后再来回看,或许成为一个有趣的回忆。

八、参考文章

https://blog.csdn.net/zhanglifu3601881/article/details/89236537
https://www.stm32cube.com/question/718

  • 8
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小张从未入门

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值