HAL库记录-SDIO外设SD卡

正点原子--阿波罗开发板STM32F429IGT6

有个注意的地方: HAL_SD_Init   函数调用     HAL_SD_InitCard  函数有调用到

HAL_Delay(2); ,芯片滴答定时需要启动

1.STM32CubeMX配置

HAL库记录-SDIO外设SD卡_第1张图片

 HAL库记录-SDIO外设SD卡_第2张图片

 HAL库记录-SDIO外设SD卡_第3张图片

 2.生成的代码

/**
  * Enable DMA controller clock
  */
void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  /* DMA2_Stream6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);

}
SD_HandleTypeDef hsd;
DMA_HandleTypeDef hdma_sdio_rx;
DMA_HandleTypeDef hdma_sdio_tx;

/* 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_DISABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 0;
  if (HAL_SD_Init(&hsd) != HAL_OK)
  {
	  COM_Printf("MX_SDIO_SD_Init Err1\r\n");
    //Error_Handler(); //注意,如果无内存,会进入这个错误函数
  }
  /* USER CODE BEGIN SDIO_Init 2 */
  if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
  {
	  COM_Printf("MX_SDIO_SD_Init Err2\r\n");
    //Error_Handler(); //注意,如果无内存,会进入这个错误函数
  }
  /* 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 Configuration
    PC8     ------> SDIO_D0
    PC12     ------> SDIO_CK
    PD2     ------> SDIO_CMD
    */
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

    /* SDIO DMA Init */
    /* SDIO_RX Init */
    hdma_sdio_rx.Instance = DMA2_Stream3;
    hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
    hdma_sdio_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
    if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(sdHandle,hdmarx,hdma_sdio_rx);

    /* SDIO_TX Init */
    hdma_sdio_tx.Instance = DMA2_Stream6;
    hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
    hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
    hdma_sdio_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
    if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(sdHandle,hdmatx,hdma_sdio_tx);

    /* SDIO interrupt Init */
    HAL_NVIC_SetPriority(SDIO_IRQn, 3, 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 Configuration
    PC8     ------> SDIO_D0
    PC12     ------> SDIO_CK
    PD2     ------> SDIO_CMD
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_8|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 */
  }
}

注意:不要直接配置成4线模式,  要先配置成1位模式后,等初始化化完 HAL_SD_Init(&hsd) != HAL_OK

再手动配置为 4线模式, HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)

3.代码改进(判断是否有TF卡)

无卡初始化是无效的,需要等待卡插入,再次初始化成功后,才可以继续操作SDIO外设

/**
 * @brief :函数作用 : 检测SDIO是否初始成功(也可以判断是否有卡插入)
 * @param :函数入口 : 无
 * @retval:函数返回 : 0:正常 1: HAL_SD_Init()初始化不过  2:HAL_SD_ConfigWideBusOperation()初始化不过
 */
uint8_t SDIO_Check(void)
{
  hsd.Instance                 = SDIO;
  hsd.Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
  hsd.Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide             = SDIO_BUS_WIDE_1B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv            = 0;
  if (HAL_SD_Init(&hsd) != HAL_OK)
  {
	COM_Printf("MX_SDIO_SD_Init Err1\r\n");
    return 1;
  }
  if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
  {
	COM_Printf("MX_SDIO_SD_Init Err2\r\n");
    return 2;
  }
    return 0; //正常
}

4.测试代码

if(SDIO_Check()==0)
{
    COM_Printf("Micro SD Card Test...\r\n");
    /* 检测SD卡是否正常(处于数据传输模式的传输状态) */
    if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER)
    {      
        COM_Printf("Initialize SD card successfully!\r\n");
        // 打印SD卡基本信息
        COM_Printf(" SD card information! \r\n");
        COM_Printf(" CardCapacity  : %lu\r\n", (hsd.SdCard.BlockSize*hsd.SdCard.BlockNbr));// 显示容量
        COM_Printf(" CardBlockSize : %d \r\n", hsd.SdCard.BlockSize);   // 块大小
        COM_Printf(" LogBlockNbr   : %d \r\n", hsd.SdCard.LogBlockNbr); // 逻辑块数量
        COM_Printf(" LogBlockSize  : %d \r\n", hsd.SdCard.LogBlockSize);// 逻辑块大小
        COM_Printf(" RCA           : %d \r\n", hsd.SdCard.RelCardAdd);  // 卡相对地址
        COM_Printf(" CardType      : %d \r\n", hsd.SdCard.CardType);    // 卡类型
        // 读取并打印SD卡的CID信息
        HAL_SD_CardCIDTypeDef sdcard_cid;
        HAL_SD_GetCardCID(&hsd,&sdcard_cid);
        COM_Printf(" ManufacturerID: %d \r\n",sdcard_cid.ManufacturerID);
    }
    else
    {
        COM_Printf("SD card init fail!\r\n" );
    }
}

5.测试结果

Micro SD Card Test...
Initialize SD card successfully!
 SD card information! 
 CardCapacity  : 3046637568
 CardBlockSize : 512 
 LogBlockNbr   : 31116288 
 LogBlockSize  : 512 
 RCA           : 43690 
 CardType      : 1 
 ManufacturerID: 3 

你可能感兴趣的:(HAL库,单片机,stm32,嵌入式硬件)