1. SDIO相关HAL库驱动
驱动函数 | 关联寄存器 | 功能描述 |
__HAL_RCC_SDIO_CLK_ENABLE | AHBENR/APB2ENR | SDIO时钟使能 |
HAL_SD_Init | SDIO_CLKCR/CMD/ARG/RESP | 初始化SD卡 |
HAL_SD_MspInit | 初始化回调函数 | 初始化SDIO的底层硬件 |
HAL_SD_ConfigWideBusOperation | SDIO_CLKCR/CMD/ARG/RESP | 配置总线宽度 |
HAL_SD_ReadBlocks | SDIO_DCTRL/CMD/ARG/RES | 读取块数据 |
HAL_SD_WriterBlocks | SDIO_DCTRL/CMD/ARG/RES | 写入块数据 |
用于发送SDIO_SendCommand函数,用于接收响应SDIO_GetResponse
HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, /* 句柄结构体指针变量 */
uint8_t *pData, /* 接收数据的缓冲地址 */
uint32_t BlockAdd, /* 要读取的扇区地址 */
uint32_t NumberOfBlocks,/* 要读取的扇区数 */
uint32_t Timeout /* 传输过程超时时间 */
HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd , /* 句柄结构体指针变量 */
uint8_t *pData, /* 写入数据的缓冲地址 */
uint32_t BlockAdd, /* 要写入的扇区地址 */
uint32_t NumberOfBlocks,/* 要写入的扇区数 */
uint32_t Timeout /* 传输过程超时时间 */
2. SDIO相关结构体
SD_HandleTypeDef(SD_InitTypeDef) //外设相关结构体
SDIO_CmdInitTypeDef //命令相关结构体
SDIO_DataInitTypeDef //数据相关结构体
HAL_SD_CardInfoTypeDef //卡信息相关结构体
{
SD_TypeDef *Instance; /*!< SD registers base address */
SD_InitTypeDef Init; /*!< SD required parameters */
HAL_LockTypeDef Lock; /*!< SD locking object */
uint8_t *pTxBuffPtr; /*!< Pointer to SD Tx transfer Buffer */
uint32_t TxXferSize; /*!< SD Tx Transfer size */
uint8_t *pRxBuffPtr; /*!< Pointer to SD Rx transfer Buffer */
uint32_t RxXferSize; /*!< SD Rx Transfer size */
__IO uint32_t Context; /*!< SD transfer context */
__IO HAL_SD_StateTypeDef State; /*!< SD card State */
__IO uint32_t ErrorCode; /*!< SD Card Error codes */
DMA_HandleTypeDef *hdmatx; /*!< SD Tx DMA handle parameters */
DMA_HandleTypeDef *hdmarx; /*!< SD Rx DMA handle parameters */
HAL_SD_CardInfoTypeDef SdCard; /*!< SD Card information */
uint32_t CSD[4]; /*!< SD card specific data table */
uint32_t CID[4]; /*!< SD card identification number table */
}SD_HandleTypeDef;
typedef struct
{
uint32_t ClockEdge; /*!< 数据或指令变化的时钟沿
通常上升沿*/
uint32_t ClockBypass; /*!< 是否设置旁路分频器
enabled or disabled.
不使用旁路分频*/
uint32_t ClockPowerSave; /*!< 空闲状态是否输出时钟
disabled when the bus is idle.
默认disable*/
uint32_t BusWide; /*!< 设置SDIO总线位宽
1B or 4B*/
uint32_t HardwareFlowControl; /*!< 用于使能硬件流控制
enable 避免常见的上溢和下溢*/
uint32_t ClockDiv; /*!< 设置SDIO时钟分频
Min_Data = 0 and Max_Data = 255 */
}SDIO_InitTypeDef;
attention:SDIO初始化最大时钟频率:400KHz
SDIO数据传输最大时钟频率:25HMz
typedef struct
{
uint32_t Argument; /*!< 命令参数 */
uint32_t CmdIndex; /*!< 命令索引 */
uint32_t Response; /*!< 响应类型:
无响应 长响应 短响应
*/
uint32_t WaitForInterrupt; /*!<等待中断请求
等待类型选择,三种状态
通常无等待
无等待,使用超时检测 等待中断 等待传输完成
SDIO_WAIT_NO SDIO_WAIT_IT SDIO_WAIT_PEND*/
uint32_t CPSM; /*!< 是否使用命令通道状态机
enabled 通常使能.
*/
}SDIO_CmdInitTypeDef;
typedef struct
{
uint32_t DataTimeOut; /*!< 数据超时时间*/
uint32_t DataLength; /*!< 数据长度
数据块长度*多少个块(5个)
*/
uint32_t DataBlockSize; /*!< 数据块大小
512B*/
uint32_t TransferDir; /*!< 传输方向(读/写)
TO_CAAD 写
*/
uint32_t TransferMode; /*!< 传输模式(块/流)
SD卡使用块 MMC卡使用数据流类型
*/
uint32_t DPSM; /*!< 是否使用数据通道状态机
enabled
*/
}SDIO_DataInitTypeDef;
SDIO_DataInitTypeDef关联的函数SDIO_ConfigData,发送/接收数据块会使用到。
attention:SD卡操作使用数据块类型,MMC卡才是用数据流类型
typedef struct
{
uint32_t CardType; /*!<卡类型*/
uint32_t CardVersion; /*!<卡版本*/
uint32_t Class; /*!<卡类型*/
uint32_t RelCardAdd; /*!<卡相对位置*/
uint32_t BlockNbr; /*!<整张卡的块数*/
uint32_t BlockSize; /*!<每个块的字节数*/
uint32_t LogBlockNbr; /*!<每张卡的逻辑块数*/
uint32_t LogBlockSize; /*!<逻辑块大小*/
}HAL_SD_CardInfoTypeDef; //与SD卡的CSD寄存器相关(通过长响应获得)
3. HAL库初始化流程
通过HAL_SD_GetCardInfo函数获取卡信息
- 初始化GPIO功能,SDIO时钟不超过400KHz
- 初始化SDIO外设接口(默认配置)
- 开启SDIO电源,为卡提供时钟,并延时两毫秒
- 发送CMD0复位命令,让卡到空闲状态
- 发送CMD8主机支持电压,并询问卡是否支持
- 根据响应判断SD卡版本
- 反复发送ACMD41,等待OCR回应,卡上电完成和卡容量类型
- 检查电源状态,进入准备状态
- 发送CMD2,获得卡信息(CID)
- 发送CMD3,获得卡的相对地址(RCA)
- 发送CMD9,获得卡的数据(CSD)
- 发送CMD7,选择卡,切换到传输状态
4. Cube配置
5. 补写函数
#include "bsp_sd.h"
#include "sdio.h"
//显示SD卡信息函数
void Show_SDMMC_Info(void){
HAL_SD_CardCIDTypeDef SDCard_CID;
HAL_SD_CardInfoTypeDef SDCard_INFO;
uint64_t CardCap; //SD卡容量
HAL_SD_GetCardCID(&hsd,&SDCard_CID); //获取CID
HAL_SD_GetCardInfo(&hsd,&SDCard_INFO); //获取SD卡信息
switch(SDCard_INFO.CardType) //SD卡类型
{
case CARD_SDSC:
if(SDCard_INFO.CardVersion == CARD_V1_X){
printf("Card Type: SDSC V1\r\n");
}
else if(SDCard_INFO.CardVersion == CARD_V2_X){
printf("Card Type: SDSC V2\r\n");
}
break;
case CARD_SDHC_SDXC:
printf("Card Type: SDHC\r\n");
break;
}
CardCap = (uint64_t)(SDCard_INFO.LogBlockNbr)*(uint64_t)(SDCard_INFO.LogBlockSize)/1024/1024; //计算SD卡容量
printf("Card ManufacturerID:%d\r\n",SDCard_CID.ManufacturerID); //制造商ID
printf("Card RCA:%d\r\n",SDCard_INFO.RelCardAdd); //卡相对地址
printf("LogBlockNbr:%d\r\n",SDCard_INFO.LogBlockNbr); //逻辑块数量
printf("LogBlockSize:%d\r\n",SDCard_INFO.LogBlockSize); //逻辑块大小
printf("Card Capacity:%d MB\r\n",(uint32_t)CardCap); //显示容量
printf("Card BlockSize:%d\r\n",SDCard_INFO.BlockSize); //块大小
}
uint8_t bsp_sd_rease(void)
{
if(HAL_SD_Erase(&hsd,0,1) == HAL_OK){
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
printf("\r\nErase Block Success!\r\n");
}
return 0;
}
uint8_t Buffer_Tx[512],Buffer_Rx[512] = {0};
uint8_t bsp_sd_readblocks(void)
{
if(HAL_SD_ReadBlocks(&hsd,Buffer_Rx,0,1,0xffffffff) == HAL_OK){
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
printf("\r\nRead Block Success!\r\n");
for(int i=0;i<sizeof(Buffer_Rx);i++)
printf("%02x ",Buffer_Rx[i]);
printf("\r\n");
}else{
printf("\r\nWrite Block Failed!\r\n");
}
return 0;
}
uint8_t bsp_sd_writeblocks(void)
{
memset(Buffer_Tx,0x15,sizeof(Buffer_Tx));
if(HAL_SD_WriteBlocks(&hsd,Buffer_Tx,0,1,0xffffffff) == HAL_OK){
while(HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER);
printf("\r\nWrite Block Success!\r\n");
for(int 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");
}
return 0;
}
SD卡HAL库驱动文件:stm32f1xx_hal_sd.c和stm32f1xx_ll_sdmmc.c
6. 工程源码
通过百度网盘分享的文件:SD_Test.rar
链接:百度网盘 请输入提取码
提取码:xaod
--来自百度网盘超级会员V6的分享
参考链接: