目录
  • 一. 准备工作
  • 二.生成MDK工程
  • 三. 编译测试

SDMMC--SD卡

本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的硬件SDMMC外设读取SD卡数据。

一. 准备工作

硬件准备

  • 开发板:小熊派BearPi-IoT_Std开发板
  • Micro SD卡: 小熊派开发板板载 Micro SD 卡槽,最大支持 32 GB,需要提前自行准备一张 Micro SD卡,如图:
### 软件准备

二.生成MDK工程

1.选择芯片型号

打开STM32CubeMX,打开MCU选择器:

搜索并选中芯片STM32L431RCT6:

2.配置时钟源

  • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
  • 如果使用默认内部时钟(HSI),这一步可以略过;

这里使用外部时钟为例:

3.配置串口

小熊派开发板板载ST-Link并且虚拟了一个串口,原理图如下:

这里我将开关拨到AT-MCU模式,使PC的串口与USART1之间连接。

接下来开始配置USART1

4.配置 SDMMC 接口

知识小卡片 —— SDMMC接口

SDMMC接口的全称叫SD/SDIO MMC card host interface,SD/SDIO MMC 卡 主机接口,通俗的来说,就是这个接口支持SD卡,支持SDIO设备,支持MMC卡。

知识小卡片结束啦~

首先查看小熊派开发板的原理图:

然后根据原理图配置 SDMMC 接口:

5.配置时钟树

STM32L4的最高主频到80M,所以配置PLL,最后使HCLK = 80Mhz即可:

6.生成工程设置

7.代码生成设置

最后设置生成独立的初始化文件:

8.生成代码

点击GENERATE CODE即可生成MDK-V5工程:

三. 编译测试

1.编写用户代码

重定向printf( )函数

参考:USART串口——重定向printf

编写测试代码

main.c中首先定义相关变量及宏定义

HAL_SD_CardCIDTypedef SD_CardCID;

#define BLOCK_SIZE            512         // 块大小     
#define NUMBER_OF_BLOCKS      8           // 块数量
#define WRITE_READ_ADDRESS    0x00002000  // 读写地址
#define WRITE_READ_ADDRESS2   0x00004000  // 读写地址

uint32_t Buffer_Block_Tx[BLOCK_SIZE*NUMBER_OF_BLOCKS]; // 据缓存
uint32_t Buffer_Block_Rx[BLOCK_SIZE*NUMBER_OF_BLOCKS] = {1,2}; // 数据缓存
HAL_StatusTypeDef sd_status;    // HAL返回值

main.c中添加测试函数


static void ReadSD(void)//读取SD出厂参数
{
  int State = 0;
  State = HAL_SD_GetCardState(&hsd1);
  if (State == HAL_SD_CARD_TRANSFER) {
    HAL_SD_GetCardCID(&hsd1, &SD_CardCID);
    printf("\r\n Initialize SD card successfully!\r\n\r\n");
    printf(" SD card information! \r\n");
    printf(" CardCapacity  : %llu \r\n", ((unsigned long long)hsd1.SdCard.BlockSize * hsd1.SdCard.BlockNbr));
    printf(" CardBlockSize : %d \r\n", hsd1.SdCard.BlockSize);
    printf(" RCA           : %d \r\n", hsd1.SdCard.RelCardAdd);
    printf(" CardType      : %d \r\n", hsd1.SdCard.CardType);
    printf(" ManufacturerID: %d \r\n", SD_CardCID.ManufacturerID);
  } else {
    printf("SD card init fail!\r\n");
    while (1); // 停机
  }
}

static void SD_Write_Read_Test(int32_t addr, uint8_t* temp)//写入SD卡数据并读出数据
{

  printf("\r\n\r\n*************Write SD card data *************\r\n");
  sd_status = HAL_SD_WriteBlocks(&hsd1, (uint8_t *)temp, addr, NUMBER_OF_BLOCKS, 0xffff);
  printf("Write data:%s,address:%x\r\n", temp, addr);
  HAL_Delay(480);
  if (sd_status == 0) {
    printf("Write data test is OK\r\n");
  } else
    printf("Write data test is fail!\r\n ");
  printf("*************Read SD card data *************\r\n");
  sd_status = HAL_SD_ReadBlocks(&hsd1, (uint8_t *)Buffer_Block_Rx, addr, NUMBER_OF_BLOCKS, 0xffff);
  printf("ReadSDData:%s,address:%x\r\n", (char*)Buffer_Block_Rx, addr);
  if (sd_status == 0) {
    printf("Read data test is OK\r\n");
  } else
    printf("Read data test is fail!\r\n ");
}

修改main函数如下:

int main(void)
{
  /* USER CODE BEGIN 1 */
  uint8_t temp[]="欢迎来到小熊派开源社区";
  uint8_t temp1[]="Welcome to BearPi";
  /* 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();

  /* Configure the peripherals common clocks */
  PeriphCommonClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_SDMMC1_SD_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  ReadSD();//读取SD卡初始化参数
  HAL_SD_ReadBlocks(&hsd1,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS,NUMBER_OF_BLOCKS,0xffff);
  printf("Read SD old data1:%s,address:%x\r\n",(char*)Buffer_Block_Rx,WRITE_READ_ADDRESS); 
  memset(Buffer_Block_Rx,0x00,sizeof(Buffer_Block_Rx));
  HAL_SD_ReadBlocks(&hsd1,(uint8_t *)Buffer_Block_Rx,WRITE_READ_ADDRESS2,NUMBER_OF_BLOCKS,0xffff);
  printf("Read SD old data2:%s,address:%x\r\n",(char*)Buffer_Block_Rx,WRITE_READ_ADDRESS2); 
  memset(Buffer_Block_Rx,0x00,sizeof(Buffer_Block_Rx));
  SD_Write_Read_Test(WRITE_READ_ADDRESS,temp);
  memset(Buffer_Block_Rx,0x00,sizeof(Buffer_Block_Rx));
  SD_Write_Read_Test(WRITE_READ_ADDRESS2,temp1);
  memset(Buffer_Block_Rx,0x00,sizeof(Buffer_Block_Rx));
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

2.编译代码

选择project菜单,点击Build Project编译工程。

如果工具栏上有编译按钮快捷键,可以直接点击工具栏上的编译按钮:

3.设置下载器

4.下载运行

选择Flash菜单,点击Download下载程序到开发板上并运行。

如果工具栏上有下载按钮快捷键,可以直接点击工具栏上的下载按钮:

5.实验现象

下载运行后,可看到以下日志。

至此,我们已经学会如何使用硬件SDMMC接口读取SD数据