HAL库记录-SDIO外设SD卡

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

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

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

1.STM32CubeMX配置

 

 

 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 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一份简单的STM32 SD卡驱动程序模板,您可以根据自己的需求进行修改。 首先,您需要在STM32 CubeMX中配置SD卡的引脚和时序,然后生成代码并导出到您的工程中。 接下来,您可以在您的工程中添加以下代码来初始化SD卡的相关参数: ```c /* SD卡句柄定义 */ SD_HandleTypeDef hsd; /* SD卡初始化函数 */ void MX_SDIO_SD_Init(void) { /* 初始化SD卡时钟 */ __HAL_RCC_SDIO_CLK_ENABLE(); /* 初始化DMA时钟 */ __HAL_RCC_DMA2_CLK_ENABLE(); /* 初始化SDIO GPIO引脚 */ GPIO_InitTypeDef GPIO_InitStruct = {0}; 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.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* 初始化DMA配置 */ 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_VERY_HIGH; 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; HAL_DMA_Init(&hdma_sdio_rx); /* 初始化SDIO配置 */ 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; HAL_SD_Init(&hsd, &SDCardInfo); /* 初始化SD卡信息 */ HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B); HAL_SD_GetCardCID(&hsd, &SDCardInfo.CID); HAL_SD_GetCardCSD(&hsd, &SDCardInfo.CSD); HAL_SD_GetCardStatus(&hsd, &SDCardInfo.CardStatus); HAL_SD_GetCardInfo(&hsd, &SDCardInfo); } ``` 接着,您可以添加以下代码来读写SD卡: ```c /* SD卡读取函数 */ uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) { if(HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, BlockAdd, NumberOfBlocks) != HAL_OK) { return 1; } if(HAL_SD_CheckReadOperation(&hsd, (uint32_t)SD_DATATIMEOUT) != HAL_OK) { return 2; } return 0; } /* SD卡写入函数 */ uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks) { if(HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, BlockAdd, NumberOfBlocks) != HAL_OK) { return 1; } if(HAL_SD_CheckWriteOperation(&hsd, (uint32_t)SD_DATATIMEOUT) != HAL_OK) { return 2; } return 0; } ``` 以上是一个简单的SD卡驱动程序模板,您可以根据自己的需求进行修改。需要注意的是,在使用SD卡之前,您需要先对SD卡进行初始化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值