stm32f103ze sdio,控制sd卡
#include "main.h" #include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> #include "sd.h" SD_HandleTypeDef hsd; // SDIO句柄 DMA_HandleTypeDef hdma_sdio; // DMA句柄 void SD_GPIO_Config() { MCU_SDIO_CK_GPIO_CLK_ENABLE(); MCU_SDIO_CMD_GPIO_CLK_ENABLE(); MCU_SDIO_D0_GPIO_CLK_ENABLE(); MCU_SDIO_D1_GPIO_CLK_ENABLE(); MCU_SDIO_D2_GPIO_CLK_ENABLE(); MCU_SDIO_D3_GPIO_CLK_ENABLE(); __HAL_RCC_SDIO_CLK_ENABLE(); GPIO_InitTypeDef SDIO_GPIO_Initstruct; SDIO_GPIO_Initstruct.Mode = GPIO_MODE_AF_PP; SDIO_GPIO_Initstruct.Pin = MCU_SDIO_CK_PIN|MCU_SDIO_D0_PIN|MCU_SDIO_D1_PIN|MCU_SDIO_D2_PIN|MCU_SDIO_D3_PIN; SDIO_GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOC,&SDIO_GPIO_Initstruct); SDIO_GPIO_Initstruct.Pin = MCU_SDIO_CMD_PIN; HAL_GPIO_Init(GPIOD,&SDIO_GPIO_Initstruct); } void SDIO_DMA_Config(void) { __HAL_RCC_DMA2_CLK_ENABLE(); 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_HIGH; HAL_DMA_Init(&hdma_sdio); __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio); // 关联DMA到SDIO接收 __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio); // 关联DMA到SDIO发送 // 使能DMA中断 __HAL_DMA_ENABLE_IT(&hdma_sdio,DMA_IT_TC); HAL_NVIC_SetPriority(DMA2_Channel4_IRQn, 5, 0); HAL_NVIC_EnableIRQ(DMA2_Channel4_IRQn); } void SD_Init() { SD_GPIO_Config(); 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;//初始化使用1因为初始化速率慢 hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; hsd.Init.ClockDiv = 70;,//cmd命令模式使用一线速率会慢,一定要降低速率分频70,pll时钟过来是72Mhz,72/(70+2)=1Mhz if(HAL_SD_Init(&hsd)!=HAL_OK)//初始化会执行cmd枚举 { Error_Handler(); }
SDIO时钟频率 = 输入时钟频率(HCLK) / (ClockDiv + 2)
- HCLK = 72MHz(常见于STM32F1/F4系列默认配置)。
- ClockDiv = 0x4(即十进制的4)。
代入公式:
SDIO_CLK=4+272=12 MHz
//初始化后切换到4位总线 if(HAL_SD_ConfigWideBusOperation(&hsd,SDIO_BUS_WIDE_4B)!= HAL_OK)//初始化之后要切换成4线高速 { Error_Handler(); } hsd.Init.ClockDiv = 0x4;//最大不能超过48mhz if (HAL_SD_Init(&hsd) != HAL_OK) { Error_Handler(); } HAL_NVIC_SetPriority(SDIO_IRQn, 4, 0); // 设置优先级(最高优先级) HAL_NVIC_EnableIRQ(SDIO_IRQn); // 启用SDIO全局中断 //SDIO_DMA_Config(); }
测试程序
uint8_t Buffer_Tx[100],Buffer_Rx[512] = {0};
uint32_t i;
#define BLOCK_START_ADDR 0 /* Block start address */
#define NUM_OF_BLOCKS 1 /* Total number of blocks */
#define BUFFER_WORDS_SIZE ((BLOCKSIZE * NUM_OF_BLOCKS) >> 2) /* Total data size in bytes */
HAL_StatusTypeDef status ;
int main()
{
SD_int();
printf("Micro SD Card Test...\r\n");
/* 检测SD卡是否正常(处于数据传输模式的传输状态) */
if(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER)
{
printf("Initialize SD card successfully!\r\n");
// 打印SD卡基本信息
printf(" SD card information! \r\n");
printf(" CardCapacity : %llu \r\n", (unsigned long long)hsd.SdCard.BlockSize * hsd.SdCard.BlockNbr);// 显示容量
printf(" CardBlockSize : %d \r\n", hsd.SdCard.BlockSize); // 块大小
printf(" LogBlockNbr : %d \r\n", hsd.SdCard.LogBlockNbr); // 逻辑块数量
printf(" LogBlockSize : %d \r\n", hsd.SdCard.LogBlockSize);// 逻辑块大小
printf(" RCA : %d \r\n", hsd.SdCard.RelCardAdd); // 卡相对地址
printf(" CardType : %d \r\n", hsd.SdCard.CardType); // 卡类型
// 读取并打印SD卡的CID信息
HAL_SD_CardCIDTypeDef sdcard_cid;
HAL_SD_GetCardCID(&hsd,&sdcard_cid);
printf(" ManufacturerID: %d \r\n",sdcard_cid.ManufacturerID);
}
else
{
printf("SD card init fail!\r\n" );
}
/* 擦除SD卡块 */
printf("------------------- Block Erase -------------------------------\r\n");
if(HAL_SD_Erase(&hsd, BLOCK_START_ADDR, NUM_OF_BLOCKS) == HAL_OK)
{
/* Wait until SD cards are ready to use for new operation */
while(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_PROGRAMMING)
{
}
printf("\r\nErase Block Success!\r\n");
}
else
{
printf("\r\nErase Block Failed!\r\n");
}
/* 填充缓冲区数据 */
memset(Buffer_Tx, 0x15, sizeof(Buffer_Tx));
/* 向SD卡块写入数据 */
printf("------------------- Write SD card block data Test ------------------\r\n");
status = HAL_SD_WriteBlocks(&hsd, Buffer_Tx, BLOCK_START_ADDR, NUM_OF_BLOCKS, HAL_MAX_DELAY);
if(status == HAL_OK)
{
while(HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_PROGRAMMING)//是否处于编程态,编程态就是忙碌
{
}
printf("\r\nWrite Block Success!\r\n");
printf("\r\nWrite Block Success!\r\n");
for(i = 0; i < sizeof(Buffer_Tx); i++)
{
printf("0x%02x:%02x ", i, Buffer_Tx[i]);
}
printf("\r\n");
}
else
{
printf("\r\nWrite Block Failed!\r\n");
}
/* 读取操作之后的数据 */
printf("------------------- Read SD card block data after Write ------------------\r\n");
if(HAL_SD_ReadBlocks(&hsd, Buffer_Rx, BLOCK_START_ADDR, NUM_OF_BLOCKS, HAL_MAX_DELAY) == HAL_OK)
{
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER)
{
}
printf("\r\nRead Block Success!\r\n");
for(i = 0; i < sizeof(Buffer_Rx); i++)
{
printf("0x%02x:%02x ", i, Buffer_Rx[i]);
}
printf("\r\n");
}
else
{
printf("\r\nRead Block Failed!\r\n");
}
}
浙公网安备 33010602011771号