正点原子--阿波罗开发板STM32F429IGT6
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