📄 +
字号:
/*********************************************************************************
* 文件名 :sdio_sdcard.c
* 描述 :MicroSD卡应用函数库(SDIO模式)
* 实验平台:CHD1807-STM32开发板
* 硬件连接:------------------------------
* | PC8-SDIO-D0 :DATA0 |
* | PC9-SDIO-D1 :DATA1 |
* | PC10-SDIO-D2 :DATA2 |
* | PC11-SDIO-D3 :CD/DATA3 |
* | PC12-SDIO-CLK:CLK |
* | PD2-SDIO-CMD :CMD |
* ------------------------------
* 库版本 :ST 3.5.0
**********************************************************************************/
#include "sdio_sdcard.h"
#include "usart1.h"
/* Private macro -------------------------------------------------------------*/
/**
* @brief SDIO Static flags, TimeOut, FIFO Address
*/
#define NULL 0
#define SDIO_STATIC_FLAGS ((uint32_t)0x000005FF)
#define SDIO_CMD0TIMEOUT ((uint32_t)0x00010000)
/**
* @brief Mask for errors Card Status R1 (OCR Register)
*/
#define SD_OCR_ADDR_OUT_OF_RANGE ((uint32_t)0x80000000)
#define SD_OCR_ADDR_MISALIGNED ((uint32_t)0x40000000)
#define SD_OCR_BLOCK_LEN_ERR ((uint32_t)0x20000000)
#define SD_OCR_ERASE_SEQ_ERR ((uint32_t)0x10000000)
#define SD_OCR_BAD_ERASE_PARAM ((uint32_t)0x08000000)
#define SD_OCR_WRITE_PROT_VIOLATION ((uint32_t)0x04000000)
#define SD_OCR_LOCK_UNLOCK_FAILED ((uint32_t)0x01000000)
#define SD_OCR_COM_CRC_FAILED ((uint32_t)0x00800000)
#define SD_OCR_ILLEGAL_CMD ((uint32_t)0x00400000)
#define SD_OCR_CARD_ECC_FAILED ((uint32_t)0x00200000)
#define SD_OCR_CC_ERROR ((uint32_t)0x00100000)
#define SD_OCR_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00080000)
#define SD_OCR_STREAM_READ_UNDERRUN ((uint32_t)0x00040000)
#define SD_OCR_STREAM_WRITE_OVERRUN ((uint32_t)0x00020000)
#define SD_OCR_CID_CSD_OVERWRIETE ((uint32_t)0x00010000)
#define SD_OCR_WP_ERASE_SKIP ((uint32_t)0x00008000)
#define SD_OCR_CARD_ECC_DISABLED ((uint32_t)0x00004000)
#define SD_OCR_ERASE_RESET ((uint32_t)0x00002000)
#define SD_OCR_AKE_SEQ_ERROR ((uint32_t)0x00000008)
#define SD_OCR_ERRORBITS ((uint32_t)0xFDFFE008)
/**
* @brief Masks for R6 Response
*/
#define SD_R6_GENERAL_UNKNOWN_ERROR ((uint32_t)0x00002000)
#define SD_R6_ILLEGAL_CMD ((uint32_t)0x00004000)
#define SD_R6_COM_CRC_FAILED ((uint32_t)0x00008000)
#define SD_VOLTAGE_WINDOW_SD ((uint32_t)0x80100000)
#define SD_HIGH_CAPACITY ((uint32_t)0x40000000)
#define SD_STD_CAPACITY ((uint32_t)0x00000000)
#define SD_CHECK_PATTERN ((uint32_t)0x000001AA)
#define SD_MAX_VOLT_TRIAL ((uint32_t)0x0000FFFF)
#define SD_ALLZERO ((uint32_t)0x00000000)
#define SD_WIDE_BUS_SUPPORT ((uint32_t)0x00040000)
#define SD_SINGLE_BUS_SUPPORT ((uint32_t)0x00010000)
#define SD_CARD_LOCKED ((uint32_t)0x02000000)
#define SD_DATATIMEOUT ((uint32_t)0xFFFFFFFF)
#define SD_0TO7BITS ((uint32_t)0x000000FF)
#define SD_8TO15BITS ((uint32_t)0x0000FF00)
#define SD_16TO23BITS ((uint32_t)0x00FF0000)
#define SD_24TO31BITS ((uint32_t)0xFF000000)
#define SD_MAX_DATA_LENGTH ((uint32_t)0x01FFFFFF)
#define SD_HALFFIFO ((uint32_t)0x00000008)
#define SD_HALFFIFOBYTES ((uint32_t)0x00000020)
/**
* @brief Command Class Supported
*/
#define SD_CCCC_LOCK_UNLOCK ((uint32_t)0x00000080)
#define SD_CCCC_WRITE_PROT ((uint32_t)0x00000040)
#define SD_CCCC_ERASE ((uint32_t)0x00000020)
/**
* @brief Following commands are SD Card Specific commands.
* SDIO_APP_CMD should be sent before sending these commands.
*/
#define SDIO_SEND_IF_COND ((uint32_t)0x00000008)
/* Private variables ---------------------------------------------------------*/
static uint32_t CardType = SDIO_STD_CAPACITY_SD_CARD_V1_1; //存储卡的类型,先把它初始化为1.1协议的卡
static uint32_t CSD_Tab[4], CID_Tab[4], RCA = 0;//存储CSD,DID,寄存器和卡相对地址
static uint8_t SDSTATUS_Tab[16]; //存储卡状态,是CSR的一部分
__IO uint32_t StopCondition = 0; //用于停止卡操作的标志
__IO SD_Error TransferError = SD_OK; //用于存储卡错误,初始化为正常状态
__IO uint32_t TransferEnd = 0; //用于标志传输是否结束,在中断服务函数中调用
SD_CardInfo SDCardInfo; //用于存储卡的信息,DSR的一部分?
/*用于sdio初始化的结构体*/
SDIO_InitTypeDef SDIO_InitStructure;
SDIO_CmdInitTypeDef SDIO_CmdInitStructure;
SDIO_DataInitTypeDef SDIO_DataInitStructure;
/* Private function prototypes -----------------------------------------------*/
static SD_Error CmdError(void);
static SD_Error CmdResp1Error(uint8_t cmd);
static SD_Error CmdResp7Error(void);
static SD_Error CmdResp3Error(void);
static SD_Error CmdResp2Error(void);
static SD_Error CmdResp6Error(uint8_t cmd, uint16_t *prca);
static SD_Error SDEnWideBus(FunctionalState NewState);
static SD_Error IsCardProgramming(uint8_t *pstatus);
static SD_Error FindSCR(uint16_t rca, uint32_t *pscr);
static void GPIO_Configuration(void);
static uint32_t SD_DMAEndOfTransferStatus(void);
static void SD_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize);
static void SD_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize);
uint8_t convert_from_bytes_to_power_of_two(uint16_t NumberOfBytes);
/* Private functions ---------------------------------------------------------*/
/*
* 函数名:SD_DeInit
* 描述 :复位SDIO端口
* 输入 :无
* 输出 :无
*/
void SD_DeInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< Disable SDIO Clock */
SDIO_ClockCmd(DISABLE);
/*!< Set Power State to OFF */
SDIO_SetPowerState(SDIO_PowerState_OFF);
/*!< DeInitializes the SDIO peripheral */
SDIO_DeInit();
/*!< Disable the SDIO AHB Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, DISABLE);
/*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*!< Configure PD.02 CMD line */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/*
* 函数名:NVIC_Configuration
* 描述 :SDIO 优先级配置为最高优先级。
* 输入 :无
* 输出 :无
*/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief Returns the DMA End Of Transfer Status.
* @param None
* @retval DMA SDIO Channel Status.
*/
uint32_t SD_DMAEndOfTransferStatus(void)
{
return (uint32_t)DMA_GetFlagStatus(DMA2_FLAG_TC4); //Channel4 transfer complete flag.
}
/*
* 函数名:SD_DMA_RxConfig
* 描述 :为SDIO接收数据配置DMA2的通道4的请求
* 输入 :BufferDST:用于装载数据的变量指针
BufferSize: 缓冲区大小
* 输出 :无
*/
void SD_DMA_RxConfig(uint32_t *BufferDST, uint32_t BufferSize)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);//清除DMA标志位
/*!< DMA2 Channel4 disable */
DMA_Cmd(DMA2_Channel4, DISABLE); //SDIO为第四通道
/*!< DMA2 Channel4 Config */
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS; //外设地址,fifo
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferDST; //目标地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设为原地址
DMA_InitStructure.DMA_BufferSize = BufferSize / 4; //1/4缓存大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//使能外设地址不自增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //使能存储目标地址自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //外设数据大小为字,32位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; //外设数据大小为字,32位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //不循环,循环模式主要用在adc上
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //通道优先级高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //非 存储器至存储器模式
DMA_Init(DMA2_Channel4, &DMA_InitStructure);
/*!< DMA2 Channel4 enable */ //不设置dma中断?
DMA_Cmd(DMA2_Channel4, ENABLE);
}
/*
* 函数名:SD_DMA_RxConfig
* 描述 :为SDIO发送数据配置DMA2的通道4的请求
* 输入 :BufferDST:装载了数据的变量指针
BufferSize: 缓冲区大小
* 输出 :无
*/
void SD_DMA_TxConfig(uint32_t *BufferSRC, uint32_t BufferSize)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);
/*!< DMA2 Channel4 disable */
DMA_Cmd(DMA2_Channel4, DISABLE);
/*!< DMA2 Channel4 Config */
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SDIO_FIFO_ADDRESS;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BufferSRC;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//外设为写入目标
DMA_InitStructure.DMA_BufferSize = BufferSize / 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不自增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel4, &DMA_InitStructure);
/*!< DMA2 Channel4 enable */
DMA_Cmd(DMA2_Channel4, ENABLE);
}
/*
* 函数名:GPIO_Configuration
* 描述 :初始化SDIO用到的引脚,开启时钟。
* 输入 :无
* 输出 :无
* 调用 :内部调用
*/
static void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*!< GPIOC and GPIOD Periph clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD , ENABLE);
/*!< Configure PC.08, PC.09, PC.10, PC.11, PC.12 pin: D0, D1, D2, D3, CLK pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/*!< Configure PD.02 CMD line */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/*!< Enable the SDIO AHB Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_SDIO, ENABLE);
/*!< Enable the DMA2 Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
}
/*
* 函数名:SD_Init
* 描述 :初始化SD卡,使卡处于就绪状态(准备传输数据)
* 输入 :无
* 输出 :-SD_Error SD卡错误代码
* 成功时则为 SD_OK
* 调用 :外部调用
*/
SD_Error SD_Init(void)
{
/*重置SD_Error状态*/
SD_Error errorstatus = SD_OK;
/* SDIO 外设底层引脚初始化 */
GPIO_Configuration();
/*对SDIO的所有寄存器进行复位*/
SDIO_DeInit();
/*上电并进行卡识别流程,确认卡的操作电压 */
errorstatus = SD_PowerON();
/*如果上电,识别不成功,返回“响应超时”错误 */
if (errorstatus != SD_OK)
{
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return(errorstatus);
}
/*卡识别成功,进行卡初始化 */
errorstatus = SD_InitializeCards();
if (errorstatus != SD_OK) //失败返回
{
/*!< CMD Response TimeOut (wait for CMDSENT flag) */
return(errorstatus);
}
/*!< Configure the SDIO peripheral
上电识别,卡初始化都完成后,进入数据传输模式,提高读写速度
速度若超过24M要进入bypass模式
!< on STM32F2xx devices, SDIOCLK is fixed to 48MHz
!< SDIOCLK = HCLK, SDIO_CK = HCLK/(2 + SDIO_TRANSFER_CLK_DIV) */
SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising; //上升沿采集数据
SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable; //时钟频率若超过24M,要开启此模式
SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; //若开启此功能,在总线空闲时关闭sd_clk时钟
SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b; //1位模式
SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; //硬件流,若开启,在FIFO不能进行发送和接收数据时,数据传输暂停
SDIO_Init(&SDIO_InitStructure);
if (errorstatus == SD_OK)
{
/*----------------- Read CSD/CID MSD registers ------------------*/
errorstatus = SD_GetCardInfo(&SDCardInfo); //用来读取csd/cid寄存器
}
if (errorstatus == SD_OK)
{
/*----------------- Select Card --------------------------------*/
errorstatus = SD_SelectDeselect((uint32_t) (SDCardInfo.RCA << 16)); //通过cmd7 ,rca选择要操作的卡
}
if (errorstatus == SD_OK)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -