当前位置: 首页 > news >正文

STM 32_HAL_SDIO_SD卡

STM32的SDIO(Secure Digital Input Output)

        接口是一种用于SD卡和MMC卡的高速数据传输接口。它允许STM32微控制器与多种存储卡和外设进行通信,支持多媒体卡(MMC卡)、SD存储卡、SDI/O卡和CE-ATA设备。STM32的SDIO控制器与多媒体卡系统规格书版本4.2完全兼容,支持三种不同的数据总线模式:1位(默认)、4位和8位。

  1. 接口简介:STM32的SDIO接口基于SD卡接口发展而来,兼容之前的SD卡,并可连接SDIO接口设备,如蓝牙、WiFi、照相机等。STM32的SDIO控制器支持多媒体卡(MMC卡)、SD存储卡、SDI/O卡和CE-ATA设备。

  2. 特点:STM32的SDIO控制器与多媒体卡系统规格书版本4.2完全兼容,支持三种不同的数据总线模式:1位(默认)、4位和8位。它还与较早的多媒体卡系统规格版本全兼容,与SD存储卡规格版本2.0全兼容,并完全支持CE-ATA功能。

  3. 时钟配置:SDIO接口需要配置卡时钟(SDIO_CK)和SDIO适配器时钟(SDIOCLK)。SDIO_CK用于命令和数据线传输,而SDIOCLK用于驱动SDIO适配器。

  4. 命令与响应:SDIO的命令分为应用相关命令(ACMD)和通用命令(CMD)。所有命令和响应都在SDIO_CMD引脚上传输。响应分为短响应(48位)和长响应(136位)。

  5. 块数据传输:SDIO与SD卡通信通常以数据块的形式进行传输。多数据块读操作和写操作都带CRC校验,且需要在SD卡非繁忙时进行数据块写操作。

SDIO框图

STM32CudeMX

1配置时钟

2打开SDIO并选择存储类型和数据引脚的个数(我的是sd卡,4引脚)

SDIO的配置我的

Parameter Settings 进行具体参数配置。

Clock transition on which the bit capture is made: Rising transition。主时钟 SDIOCLK 产生 CLK 引脚时钟有效沿选择,可选上升沿或下降沿,它设定 SDIO 时钟控制寄存器(SDIO_CLKCR)的 NEGEDGE 位的值,一般选择设置为上升沿

SDIO Clock divider bypass: Disable。时钟分频旁路使用,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 BYPASS 位。如果使能旁路,SDIOCLK 直接驱动 CLK 线输出时钟;如果禁用,使用 SDIO_CLKCR 寄存器的 CLKDIV 位值分频 SDIOCLK,然后输出到 CLK 线。一般选择禁用时钟分频旁路

SDIO Clock output enable when the bus is idle: Disable the power save for the clock。节能模式选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 PWRSAV 位的值。如果使能节能模式,CLK 线只有在总线激活时才有时钟输出;如果禁用节能模式,始终使能 CLK 线输出时钟。

SDIO hardware flow control: The hardware control flow is disabled。硬件流控制选择,可选使能或禁用,它设定 SDIO_CLKCR 寄存器的 HWFC_EN 位的值。硬件流控制功能可以避免 FIFO 发送上溢和下溢错误。

SDIOCLK clock divide factor: 6。时钟分频系数,它设定 SDIO_CLKCR 寄存器的 CLKDIV 位的值,设置 SDIOCLK 与 CLK 线输出时钟分频系数:CLK 线时钟频率=SDIOCLK/([CLKDIV+2])。

SDIO_CK 引脚的时钟信号在卡识别模式时要求不超过 400KHz,而在识别后的数据传输模式时则希望有更高的速度(最大不超过 25MHz),所以会针对这两种模式配置 SDIOCLK 的时钟。 这里参数描述建议将SDIOCLK clock divede factor 参数使用默认值为0,SDIOCLK为72MHz,可以得到最大频率36MHz,但请注意,有些型号的SD卡可能不支持36MHz这么高的频率,所以还是要以实际情况而定。

CLK 线时钟频率 = SDIOCLK / (CLKDIV + 2)

SDIOCLK 是 SDIO 总线的时钟源频率

CLKDIV 是时钟分频器的值

CLK 线时钟频率:SDIO输出的频率

可以生成代码了

代码编写

注意

在使用HAL库时,初始化时如果SD没有检测到会进入Error_Handler() 将会进入死循环

HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation删除(我的卡不支持宽模式,不删除会影响程序)

Error_Handler() 函数通常是在嵌入式系统中的硬件抽象层(HAL)中定义的一个占位符函数,用于在发生错误时提供一个统一的处理点。默认情况下,这个函数可能是空的,也可能包含一些基本的错误处理代码,例如禁用中断、记录错误信息、进入一个死循环或者复位系统。

要将MX_SDIO_SD_Init();中的上面函数注释掉

void MX_SDIO_SD_Init(void)
{/* USER CODE BEGIN SDIO_Init 0 *//* USER CODE END SDIO_Init 0 *//* USER CODE BEGIN SDIO_Init 1 *//* USER CODE END SDIO_Init 1 */hsd.Instance = SDIO;hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;hsd.Init.BusWide = SDIO_BUS_WIDE_4B;hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;hsd.Init.ClockDiv = 6;if (HAL_SD_Init(&hsd) != HAL_OK){//Error_Handler();}if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK){// Error_Handler();}/* USER CODE BEGIN SDIO_Init 2 *//* USER CODE END SDIO_Init 2 */}

用HAL_SD_Init(&hsd)函数看返回是否位HAL_OK 可以判断是否有SD卡,顺便重新初始化了

HAL_SD_Init(&hsd) 和 MX_SDIO_SD_Init()作用是一样的。

有哪些函数

  1. HAL_SD_Init - 初始化 SDIO 接口和 SD 卡
  2. HAL_SD_ConfigWideBusOperation - 配置 SD 卡以使用宽总线模式(4位数据线)。
  3. HAL_SD_DeInit - 去初始化 SDIO 接口
  4. HAL_SD_GetCardInfo - 获取 SD 卡的信息,如卡类型、容量等
  5. HAL_SD_GetCardState - 获取 SD 卡的当前状态。
  6. HAL_SD_GetStatus - 获取 SD 卡的状态信息。
  7. HAL_SD_ReadBlocks - 从 SD 卡读取一个或多个块数据。(DMA   中断)
  8. HAL_SD_WriteBlocks - 向 SD 卡写入一个或多个块数据
  9. HAL_SD_Get_OCR - 获取 SD 卡的操作条件寄存器(OCR)内容。
  10. HAL_SD_GetCID - 获取 SD 卡的卡识别(CID)信息。
  11. HAL_SD_GetCSD - 获取 SD 卡的卡特定数据(CSD)信息。
  12. HAL_SD_Abort - 中止当前的传输操作。
  13. HAL_SD_AbortIT - 中止当前的传输操作并产生中断。
  14. HAL_SD_IRQHandler - SDIO中断处理函数。
  15. HAL_SD_RxCpltCallback - 接收完成回调函数。
  16. HAL_SD_TxCpltCallback - 传输完成回调函数。
  17. HAL_SD_ErrorCallback - 错误回调函数。

检测是否有SD卡(实例1)

/* USER CODE BEGIN Header */
/********************************************************************************* @file    sdio.c* @brief   This file provides code for the configuration*          of the SDIO instances.******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "sdio.h"/* USER CODE BEGIN 0 *//* USER CODE END 0 */SD_HandleTypeDef hsd;
DMA_HandleTypeDef hdma_sdio;/* SDIO init function */void MX_SDIO_SD_Init(void)
{/* USER CODE BEGIN SDIO_Init 0 *//* USER CODE END SDIO_Init 0 *//* USER CODE BEGIN SDIO_Init 1 *//* USER CODE END SDIO_Init 1 */hsd.Instance = SDIO;hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;hsd.Init.BusWide = SDIO_BUS_WIDE_4B;hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_ENABLE;hsd.Init.ClockDiv = 6;if (HAL_SD_Init(&hsd) != HAL_OK){//Error_Handler();}if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK){//Error_Handler();}/* USER CODE BEGIN SDIO_Init 2 *//* USER CODE END SDIO_Init 2 */}void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(sdHandle->Instance==SDIO){/* USER CODE BEGIN SDIO_MspInit 0 *//* USER CODE END SDIO_MspInit 0 *//* SDIO clock enable */__HAL_RCC_SDIO_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();__HAL_RCC_GPIOD_CLK_ENABLE();/**SDIO GPIO ConfigurationPC8     ------> SDIO_D0PC9     ------> SDIO_D1PC10     ------> SDIO_D2PC11     ------> SDIO_D3PC12     ------> SDIO_CKPD2     ------> SDIO_CMD*/GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);GPIO_InitStruct.Pin = GPIO_PIN_2;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);/* SDIO DMA Init *//* SDIO Init */hdma_sdio.Instance = DMA2_Channel4;hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE;hdma_sdio.Init.MemInc = DMA_MINC_ENABLE;hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;hdma_sdio.Init.Mode = DMA_NORMAL;hdma_sdio.Init.Priority = DMA_PRIORITY_LOW;if (HAL_DMA_Init(&hdma_sdio) != HAL_OK){Error_Handler();}/* Several peripheral DMA handle pointers point to the same DMA handle.Be aware that there is only one channel to perform all the requested DMAs. *//* Be sure to change transfer direction before callingHAL_SD_ReadBlocks_DMA or HAL_SD_WriteBlocks_DMA. */__HAL_LINKDMA(sdHandle,hdmarx,hdma_sdio);__HAL_LINKDMA(sdHandle,hdmatx,hdma_sdio);/* SDIO interrupt Init */HAL_NVIC_SetPriority(SDIO_IRQn, 0, 0);HAL_NVIC_EnableIRQ(SDIO_IRQn);/* USER CODE BEGIN SDIO_MspInit 1 *//* USER CODE END SDIO_MspInit 1 */}
}void HAL_SD_MspDeInit(SD_HandleTypeDef* sdHandle)
{if(sdHandle->Instance==SDIO){/* USER CODE BEGIN SDIO_MspDeInit 0 *//* USER CODE END SDIO_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SDIO_CLK_DISABLE();/**SDIO GPIO ConfigurationPC8     ------> SDIO_D0PC9     ------> SDIO_D1PC10     ------> SDIO_D2PC11     ------> SDIO_D3PC12     ------> SDIO_CKPD2     ------> SDIO_CMD*/HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);/* SDIO DMA DeInit */HAL_DMA_DeInit(sdHandle->hdmarx);HAL_DMA_DeInit(sdHandle->hdmatx);/* SDIO interrupt Deinit */HAL_NVIC_DisableIRQ(SDIO_IRQn);/* USER CODE BEGIN SDIO_MspDeInit 1 *//* USER CODE END SDIO_MspDeInit 1 */}
}/* USER CODE BEGIN 1 *//* USER CODE END 1 */

main.h文件

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.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 ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* 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_DMA_Init();MX_SDIO_SD_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */
char data_UART1[]={"SD卡已插入"};
char data_UART2[]={"SD卡未插入,请插入SD卡"};/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){if(HAL_SD_Init(&hsd)==HAL_OK){//判断是否插入SD卡HAL_UART_Transmit(&huart1,(uint8_t*)data_UART1,11,50);}else{HAL_UART_Transmit(&huart1,(uint8_t*)data_UART2,22,50);}HAL_Delay(1000);/* 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 RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/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_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses 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_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}/* 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 */__disable_irq();while (1){}/* 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,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

返回SD卡信息(实例2)

HAL_SD_CardInfoTypeDef sd_typeDef;//结构体内的意思

  • sd_typeDef.BlockNbr: 这个变量表示SD卡上的总块数。块是SD卡存储数据的基本单位,通常大小为512字节。

  • sd_typeDef.BlockSize: 这个变量表示SD卡上每个数据块的大小,以字节为单位。对于标准SD卡,块大小通常是512字节。

  • sd_typeDef.CardType: 这个变量表示SD卡的类型,例如标准SD卡、SDHC(高容量SD卡)或SDXC(扩展容量SD卡)。

                    SD卡:标准SD卡                      0
    SDHC卡:高容量SD卡                     1
    SDXC卡:扩展容量SD卡                2

  • sd_typeDef.CardVersion: 这个变量表示SD卡的版本信息。

  • sd_typeDef.Class: 这个变量表示SD卡的类别,反映了卡的性能等级,例如_class_2, _class_4, class_6 或 class_10,这些等级定义了卡的最低写入速度。

  • sd_typeDef.LogBlockNbr: 这个变量表示用于日志的块数。在某些情况下,SD卡可能会使用逻辑块地址,这个变量就是用来存储逻辑块的数量。

  • sd_typeDef.LogBlockSize: 这个变量表示用于日志的块大小。与 BlockSize 类似,但它可能用于特定的日志记录或文件系统结构。

  • sd_typeDef.RelCardAdd: 这个变量表示SD卡的相对卡地址。在某些SD卡操作中,使用相对地址而不是绝对地址。

main.h文件

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.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 ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* 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_DMA_Init();MX_SDIO_SD_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */
char data_UART1[]={"SD卡已插入"};
char data_UART2[]={"SD卡未插入,请插入SD卡"};/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){HAL_Delay(1000);if(HAL_SD_Init(&hsd)==HAL_OK){//判断是否插入SD卡//MX_SDIO_SD_Init();HAL_UART_Transmit(&huart1,(uint8_t*)data_UART1,11,50);char SD_Data [35];HAL_SD_CardInfoTypeDef sd_typeDef;if(HAL_SD_GetCardInfo(&hsd,&sd_typeDef)==HAL_OK){//获取SD卡信息sprintf(SD_Data,"卡的类型:%lu  快的数量 :%lu",sd_typeDef.CardType,sd_typeDef.BlockNbr);HAL_UART_Transmit(&huart1 ,(uint8_t*)SD_Data,30,50);}}else{HAL_UART_Transmit(&huart1,(uint8_t*)data_UART2,22,50);}//HAL_Delay(1000);/* 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 RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/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_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses 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_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}/* 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 */__disable_irq();while (1){}/* 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,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

实现读写

开关在关闭(向下)位置时,SD卡可以读写;在打开(向上)位置时,SD卡处于写保护状态。 

注意写入时也要时间

/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** Copyright (c) 2024 STMicroelectronics.* All rights reserved.** This software is licensed under terms that can be found in the LICENSE file* in the root directory of this software component.* If no LICENSE file comes with this software, it is provided AS-IS.********************************************************************************/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "sdio.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.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 ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* 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_DMA_Init();MX_SDIO_SD_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */
char data_UART1[]={"SD卡已插入"};
char data_UART2[]={"SD卡未插入,请插入SD卡"};
uint8_t buffer_1[512];
uint8_t buffer_2[512];
//数组赋值for(int i=0;i<512;i++){buffer_1[i]='l';}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){HAL_Delay(1000);if(HAL_SD_Init(&hsd)==HAL_OK){//判断是否插入SD卡HAL_UART_Transmit(&huart1,(uint8_t*)data_UART1,11,50);char SD_Data [35];HAL_SD_CardInfoTypeDef sd_typeDef;if(HAL_SD_GetCardInfo(&hsd,&sd_typeDef)==HAL_OK){//获取SD卡信息sprintf(SD_Data,"卡的类型:%lu  快的数量 :%lu",sd_typeDef.CardType,sd_typeDef.BlockNbr);HAL_UART_Transmit(&huart1 ,(uint8_t*)SD_Data,30,50);}//读取数据DMA //1:指针 2:数据 3:地址 4:几块  if(HAL_SD_ReadBlocks(&hsd,buffer_2,77,1,10000)==HAL_OK){char SD_Data [10]={"读取成功"};HAL_UART_Transmit(&huart1 ,(uint8_t*)SD_Data,10,50);}else{char SD_Data [10]={"读取失败"};HAL_UART_Transmit(&huart1 ,(uint8_t*)SD_Data,10,50);}//写入数据阻塞if(HAL_SD_WriteBlocks_DMA(&hsd,buffer_1,77,1)==HAL_OK){char SD_Data [10]={"写入成功"};HAL_UART_Transmit(&huart1 ,(uint8_t*)SD_Data,10,50);}else{char SD_Data [10]={"写入失败"};HAL_UART_Transmit(&huart1 ,(uint8_t*)SD_Data,10,50);}//打印数据for(int i=0;i<512;i++){char a[3];sprintf(a,"%c",buffer_2[i]);HAL_UART_Transmit(&huart1 ,(uint8_t*)a,1,50);}}else{HAL_UART_Transmit(&huart1,(uint8_t*)data_UART2,22,50);}//HAL_Delay(1000);/* 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 RCC Oscillators according to the specified parameters* in the RCC_OscInitTypeDef structure.*/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_MUL9;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses 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_DIV2;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK){Error_Handler();}
}/* 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 */__disable_irq();while (1){}/* 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,ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

相关文章:

STM 32_HAL_SDIO_SD卡

STM32的SDIO&#xff08;Secure Digital Input Output&#xff09; 接口是一种用于SD卡和MMC卡的高速数据传输接口。它允许STM32微控制器与多种存储卡和外设进行通信&#xff0c;支持多媒体卡&#xff08;MMC卡&#xff09;、SD存储卡、SDI/O卡和CE-ATA设备。STM32的SDIO控制器…...

人脸识别系统之动态人脸识别

二&#xff0e;动态人脸识别 1.摄像头人脸识别 1.1.导入资源包 import dlib import cv2 import face_recognition from PIL import Image, ImageTk import tkinter as tk import os注&#xff1a;这些导入语句允许您在代码中使用这些库和模块提供的功能&#xff0c;例如创建…...

Opencv实用笔记(一): 获取并绘制JSON标注文件目标区域(可单独保存目标小图)

文章目录 背景代码 背景 如果我们想要根据json标注文件&#xff0c;获取里面的指定目标的裁剪区域&#xff0c;那么我们可以根据以下代码来实现&#xff08;也可以校验标注情况&#xff09;。 代码 from tqdm import tqdm import os, json, cv2, copy import numpy as npdef…...

LabVIEW在高校电力电子实验中的应用

概述&#xff1a;本文介绍了如何利用LabVIEW优化高校电力电子实验&#xff0c;通过图形化编程实现参数调节、实时数据监控与存储&#xff0c;并与Simulink联动&#xff0c;提高实验效率和数据处理能力。 需求背景高校实验室在进行电机拖动和电力电子实验时&#xff0c;通常使用…...

rtsp python实现

1. rtsp rtp rtcp https://hope-wisdom.blog.csdn.net/article/details/138259027 2.rtsp加速 https://mp.weixin.qq.com/s/0C1b-8pFw0HaE1xpNbrxxw 3. 实现了一部分获取数据 import socket import base64 import threading import struct# 定义 RTSP 请求 def send_rtsp_…...

RHCE (Linux进阶) Ubuntu 操作系统安装教程

一、在官网下载iso镜像文件 下载地址&#xff1a; https://cn.ubuntu.com/download/server/step1#downloads&#xff08;下载最新的Ubuntu 20.04 LTS服务器版本&#xff09; 二、VMware安装配置过程 基本安装过程 1、新建虚拟机 2、选择典型即可 3、设置下载好的Ubuntu对应路…...

vue-router 源码分析——1. 路由匹配

这是对vue-router 3 版本的源码分析。 本次分析会按以下方法进行&#xff1a; 按官网的使用文档顺序&#xff0c;围绕着某一功能点进行分析。这样不仅能学习优秀的项目源码&#xff0c;更能加深对项目的某个功能是如何实现的理解。这个对自己的技能提升&#xff0c;甚至面试时…...

百度云下载不限速方式集合

使用解析网站配合Motrix工具软件 下载Motrix工具&#xff1a;Motrix下载链接打开解析网址&#xff1a;解析网站获取&#xff0c;将百度网盘链接粘贴到解析网站&#xff0c;获取下载链接。在Motrix中配置Aria2 RPC地址&#xff1a;ws://localhost:16800/jsonrpc开始下载&#x…...

2024年6月1日 (周六) 叶子游戏新闻

Embracer探讨单机游戏大作涨价超过70美元的可能性在Embracer集团等待公布新公司名称的同时&#xff0c;他们对游戏大作的价格上涨做出了评论。几年来&#xff0c;游戏大作的价格已经达到了70美元的门槛。Embracer集团的CEO Lars Wingefors在采访中表示&#xff0c;电子游戏行业…...

MathorCup挑战赛获奖名单公示,第九届研讨会及颁奖典礼即将举行

近日&#xff0c;备受瞩目的2024年第十四届MathorCup高校数学建模挑战赛圆满落幕&#xff0c;竞赛组委会于近日公示了获奖名单初稿。本届竞赛自2024年4月12日至16日举行&#xff0c;吸引了来自全国740所高校的9119支队伍踊跃参与&#xff0c;其中包括本科生、研究生、专科生及教…...

vulnhub靶机xptosystem

下载地址&#xff1a;https://download.vulnhub.com/xpto/xptosystem.ova 主机发现 端口扫描 服务扫描 漏洞扫描 看一下web 目录爆破 那不用说肯定看看robots.txt 要检查readme去看看 看不懂 这个是靶场吧很像 在最后看着挺像url路径的 还真是&#xff0c;我直接base64 坏了还…...

Spring Boot详解:深入了解与实践

文章目录 1. Spring Boot简介1.1 什么是Spring Boot&#xff1f;1.2 Spring Boot的历史背景1.3 Spring Boot的核心特点 2. Spring Boot的核心概念2.1 自动配置2.1.1 自动配置原理2.1.2 自定义配置 2.2 Spring Boot Starter2.3 Spring Boot CLI 3. Spring Boot的主要功能模块3.1…...

FreeRtos进阶——中断的内部逻辑

中断与非中断API的区别 BaseType_t xQueueSendToBack(QueueHandle_t xQueue,const void *pvItemToQueue,TickType_t xTicksToWait); BaseType_t xQueueSendToBackFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWok…...

Centos7对比Ubuntu一些常用操作差异点

Centos7对比Ubuntu一些常用操作差异点 CentOS 7将于2024年6月30日停止维护&#xff0c;CentOS8已经转为Rhel的上游项目。同时Centos7的软件仓库中&#xff0c;部分软件版本较老。后续使用过程中可以考虑切换到Ubuntu。 下面总结了一些两个系统的常见差异点&#xff0c;包括软…...

24、matlab二维和三维网格(meshgrid函数)以及散点数据插值 griddata()函数

1、二维和三维网格(meshgrid函数) 语法 语法1:[X,Y] = meshgrid(x,y) 基于向量 x 和 y 中包含的坐标返回二维网格坐标。 语法2:[X,Y] = meshgrid(x) 与 [X,Y] = meshgrid(x,x) 相同,并返回网格大小为 length(x)length(x) 的方形网格坐标。 语法3:[X,Y,Z] = meshgrid(x,y,…...

Codeforces Round 950 (Div. 3)

好久没写题解了&#xff0c;今天来写个题解。 A - 问题 Generator #include "bits/stdc.h" using namespace std;#define int long long #define endl \n #define IOS ios::sync_with_stdio(0),cin.tie(0); #define all(x) x.begin(),x.end() #define pi pair<in…...

弘君资本炒股开户:如何看待股价波动?

在股票商场上股价的动摇无疑是投资者最为关心的话题之一&#xff0c;面临股价的起伏不定投资者往往会感到迷茫和焦虑。关于怎么看待股价动摇&#xff0c;弘君资本下面就为大家详细介绍一下。 股价动摇是股市运行的常态&#xff0c;股市是国民经济的晴雨表&#xff0c;股票价格…...

操作系统实验六 文件系统验证实验

前言 当时由于假期的原因&#xff0c;我们不需要做实验五&#xff0c;所以实验六是我们做的最后一个实验&#xff0c;因此实验五就需要靠大家自己完成了。 1.实验目的 初步掌握Linux系统文件权限和IO操作。 2.实验内容 熟悉Linux系统文件权限和使用相关IO函数进行文件创建和…...

python中的循环控制语句break与continue

学习这两个语句之前&#xff0c;我们要先了解这两个语句是什么意思&#xff1a; break&#xff1a;中断、打破的意思。所以它的跳出循环的意思 continue&#xff1a;继续的意思&#xff0c;意思是跳过当前条件&#xff0c;继续循环 新需求来了&#xff01;我们不仅要告诉 Py…...

C语言笔记23 •文件操作•

1.为什么要使用文件&#xff1f; 文件&#xff0c;顾名思义就是存储我们所写在电脑上的文本内容。如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失 了&#xff0c;等再次运⾏程序&#x…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Linux部署私有文件管理系统MinIO

最近需要用到一个文件管理服务&#xff0c;但是又不想花钱&#xff0c;所以就想着自己搭建一个&#xff0c;刚好我们用的一个开源框架已经集成了MinIO&#xff0c;所以就选了这个 我这边对文件服务性能要求不是太高&#xff0c;单机版就可以 安装非常简单&#xff0c;几个命令就…...

Spring AOP代理对象生成原理

代理对象生成的关键类是【AnnotationAwareAspectJAutoProxyCreator】&#xff0c;这个类继承了【BeanPostProcessor】是一个后置处理器 在bean对象生命周期中初始化时执行【org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization】方法时…...

向量几何的二元性:叉乘模长与内积投影的深层联系

在数学与物理的空间世界中&#xff0c;向量运算构成了理解几何结构的基石。叉乘&#xff08;外积&#xff09;与点积&#xff08;内积&#xff09;作为向量代数的两大支柱&#xff0c;表面上呈现出截然不同的几何意义与代数形式&#xff0c;却在深层次上揭示了向量间相互作用的…...

leetcode_69.x的平方根

题目如下 &#xff1a; 看到题 &#xff0c;我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历&#xff0c;我们是整数的平方根&#xff0c;所以我们分两…...