STM32完成SD卡的数据写入

news/2025/2/11 8:53:37/

文章目录

    • 一、SD卡模块简介
    • 二、读取SD卡
    • 三、总结
    • 四、参考

一、SD卡模块简介

  • 简介
    SD存储卡是一种基于半导体快闪记忆器的新一代记忆设备,由于它体积小、数据传输速度快、可热插拔等优良的特性,被广泛地于便携式装置上使用,例如数码相机、平板电脑和多媒体播放器等。控制器对 SD 卡进行读写通信操作一般有两种通信接口可选,一种是 SPI 接口,另外一种是 SDIO 接口。
  • 物理结构
    一张SD卡包括有存储单元、存储单元接口、电源检测、卡及接口控制器和接口驱动器5 个部分。
    存储单元是存储数据部件,存储单元通过存储单元接口与卡控制单元进行数据传输;
    电源检测单元保证SD卡工作在合适的电压下,如出现掉电或上状态时,它会使控制单元和存储单元接口复位;
    卡及接口控制单元控制SD卡的运行状态,它包括有8个寄存器;
    接口驱动器控制 SD 卡引脚的输入输出。
    在这里插入图片描述

二、读取SD卡

工程文件
百度网盘链接:https://pan.baidu.com/s/1U5GLGxgHElVVTDzscUy-lQ
提取码:1234
主要代码:
main.c

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                             www.st.com/SLA0044********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "fatfs.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "SDdriver.h"/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;UART_HandleTypeDef huart1;/* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int fputc(int ch, FILE *f)    
{HAL_UART_Transmit(&huart1, (unsigned char *)&ch, 1, 0xFFFF);   return ch;
}
uint16_t uart_value[3];
uint8_t aRxBuffer1;	//uart rx buff void WritetoSD(BYTE write_buff[],uint8_t bufSize);
char SD_FileName[] = "hello.txt";
uint8_t WriteBuffer[] = "01 write buff to sd \r\n";//uint8_t test_sd =0;	//用于测试格式化
uint8_t write_cnt =0;	//写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);		 //取消挂载}void Get_SDCard_Capacity(void)
{FRESULT result;FATFS FS;FATFS *fs;DWORD fre_clust,AvailableSize,UsedSize;  uint16_t TotalSpace;uint8_t res;res = SD_init();		//SD卡初始化if(res == 1){printf("SD卡初始化失败! \r\n");		}else{printf("SD卡初始化成功! \r\n");		}/* 挂载 */res=f_mount(&FS,"0:",1);		//挂载if (res != FR_OK){printf("FileSystem Mounted Failed (%d)\r\n", result);}res = f_getfree("0:", &fre_clust, &fs);  /* 根目录 */if ( res == FR_OK ) {TotalSpace=(uint16_t)(((fs->n_fatent - 2) * fs->csize ) / 2 /1024);AvailableSize=(uint16_t)((fre_clust * fs->csize) / 2 /1024);UsedSize=TotalSpace-AvailableSize;              /* Print free space in unit of MB (assuming 512 bytes/sector) */printf("\r\n%d MB total drive space.\r\n""%d MB available.\r\n""%d MB  used.\r\n",TotalSpace, AvailableSize,UsedSize);}else {printf("Get SDCard Capacity Failed (%d)\r\n", result);}		
} /* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
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 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK){Error_Handler();}
}/*** @brief SPI1 Initialization Function* @param None* @retval None*/
static void MX_SPI1_Init(void)
{/* USER CODE BEGIN SPI1_Init 0 *//* USER CODE END SPI1_Init 0 *//* USER CODE BEGIN SPI1_Init 1 *//* USER CODE END SPI1_Init 1 *//* SPI1 parameter configuration*/hspi1.Instance = SPI1;hspi1.Init.Mode = SPI_MODE_MASTER;hspi1.Init.Direction = SPI_DIRECTION_2LINES;hspi1.Init.DataSize = SPI_DATASIZE_8BIT;hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;hspi1.Init.NSS = SPI_NSS_SOFT;hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi1.Init.TIMode = SPI_TIMODE_DISABLE;hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi1.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI1_Init 2 *//* USER CODE END SPI1_Init 2 */}/*** @brief USART1 Initialization Function* @param None* @retval None*/
static void MX_USART1_UART_Init(void)
{/* USER CODE BEGIN USART1_Init 0 *//* USER CODE END USART1_Init 0 *//* USER CODE BEGIN USART1_Init 1 *//* USER CODE END USART1_Init 1 */huart1.Instance = USART1;huart1.Init.BaudRate = 115200;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;if (HAL_UART_Init(&huart1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN USART1_Init 2 *//* USER CODE END USART1_Init 2 */}/*** @brief GPIO Initialization Function* @param None* @retval None*/
static void MX_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOA_CLK_ENABLE();/*Configure GPIO pin Output Level */HAL_GPIO_WritePin(SD_CS_GPIO_Port, SD_CS_Pin, GPIO_PIN_RESET);/*Configure GPIO pin : SD_CS_Pin */GPIO_InitStruct.Pin = SD_CS_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(SD_CS_GPIO_Port, &GPIO_InitStruct);}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{ /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

SD卡与STM32连接图

CS——PA4
SCK——PA5
MISO——PA6
MOSI——PA7
VCC——5V
GND——GND

编译构建后下载到STM32F103C8T6中,连接好电路后。设置波特率为115200,打开串口
在这里插入图片描述
注:SD卡模块需要5V驱动,打开串口程序后需按下RESET重启
等待串口持续发送while,说明文件写入已完成。通过电脑查看写入的文件HELLO.TXT
在这里插入图片描述

三、总结

本次实验做起来很考验人。做了还就才做成功。之前用的代码有错导致一直不能读取,改正后还是不能读取。换成5V电源后还是不行,就一次次尝试,最后终于读取出来了。

四、参考

https://blog.csdn.net/qq_39758638/article/details/103573843
https://blog.csdn.net/m0_58414679/article/details/122036435?spm=1001.2014.3001.5501


http://www.ppmy.cn/news/256408.html

相关文章

龙芯2K1000实战开发-kernel 开发

文章目录 概要整体架构流程技术名词解释技术细节小结概要 提示:这里可以添加技术概要 例如: 本文主要解释龙芯2K1000的内核开发。 整体架构流程 提示:这里可以添加技术整体架构 1.从 ftp 上下载的 Kernel 源码一般都会有一个 mymake 的脚本,编译和配置可以 直接借用此…

如何使用 Git

Git 是一种分布式版本控制系统&#xff0c;它可以记录文件的变化历史&#xff0c;并且可以在不同的分支上进行开发。在软件开发中&#xff0c;Git 是一个必不可少的工具。本文将介绍如何使用 Git。 安装 Git 首先&#xff0c;你需要在你的电脑上安装 Git。你可以在 Git 的官网…

DETR模型转RKNN

目录 1.前言 2.准备工作 3.开始转模型 4.测试代码 5.不想转&#xff0c;直接用也可以&#xff0c;转好的给你&#xff0c;请关注评论一下 1.前言 RKNN出最新版本了&#xff0c;测试了一下&#xff0c;rk在transformer方面做了很多的工作&#xff0c;至少之前不能转的模型&am…

【面试宝典】优秀求职者的必备技能-如何回答“小伙子,请做一下自我介绍?”

前言 我是沐风晓月,今天起,我的付费专栏《面试宝典》上线了,此专栏由互联网老辛,IT民工金鱼哥,漂流客,极客运维之家,逃离广寒宫的兔子,等多位大佬加持,有以下几个优势: 最贴近面试市场,都是大佬们的学员或者公司的最新面试题 最详细的面试方法,近千名学员面试复盘…

Android AIDL Callback的使用(配源码)

零、示例说明 本示例&#xff0c;完成的功能是&#xff1a;客户端向服务端注册一个回调&#xff0c;服务端是一个商店shop&#xff0c;当商店里的产品 Product 有变化时&#xff0c;调用回调向通知客户端&#xff0c;什么商品更新了。 一、完整源代码 完整源码链接: https:/…

Freeswitch学习笔记(一):Sip协议

目录 1.基本概念 1.1.名词概念 1.2.SIP的基本概念和相关元素 1.3.SIP协议的基本方法和头域简介

【观察】金融行业决策智能化“换挡提速” 华为全球智慧金融峰会2023值得期待...

当前以数字化、智能化为特征的第四次工业革命正“扑面而来”&#xff0c;数字经济浪潮对各行各业都产生着深刻影响。其中&#xff0c;金融行业作为现代经济的核心&#xff0c;也面临着一系列重大的挑战和机遇。 相比于其他企业&#xff0c;金融行业依靠数据分析和智能决策更好地…

MCU 调试运行正常,去掉调试器不运行,解决方法

目录 硬件 现象 处理思路 处理过程记录 us延时准备用systick实现 实现 结论 硬件 官方评估板 现象 sdk例程 独立运行都正常。但是自己写的代码&#xff0c;调试运行正常&#xff0c;独立&#xff08;去掉调试器&#xff09;运行却不行。 处理思路 使用的代码一点点注…