mokongking

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");
}

}

 



 

posted on 2025-03-25 08:15  虎啸岳林  阅读(139)  评论(0)    收藏  举报

导航