程序设计
根据 SD 卡识别过程和数据传输过程理解 SD 卡驱动函数代码。这部分代码内容也较多,在本文中只对部分核心函数介绍其功能,详细代码可到灵动官网下载参考。
SPIO配置初始化
void SDIO_ConfigInit(void)
{
SDIO_InitTypeDef SDIO_InitStruct;
SDIO_PIN_GPIO_Config();
SDIO_Detect_Pin_Config();
RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, ENABLE);
SDIO_DeInit();
RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, DISABLE);
RCC_AHBPeriphClockCmd(RCC_AHBENR_SDIO, ENABLE);
SDIO_ClockSet(0x2F);
SDIO_StructInit(&SDIO_InitStruct);
SDIO_InitStruct.SDIO_OPMSel = SDIO_MMC_CTRL_OPMSel;
SDIO_InitStruct.SDIO_SelPTSM = SDIO_MMC_CTRL_SelSM;
SDIO_InitStruct.SDIO_DATWT = SDIO_MMC_CTRL_DATWT;
SDIO_Init(&SDIO_InitStruct);
SDIO_CRCConfig(SDIO_MMC_CRCCTL_CMD_CRCEN | SDIO_MMC_CRCCTL_DAT_CRCEN, ENABLE);
}
void show_sdcard_info(void)
{
switch(SDCardInfo.CardType) {
case SDIO_STD_CAPACITY_SD_CARD_V1_1:
printf("Card Type:SDSC V1.1\r\n");
break;
case SDIO_STD_CAPACITY_SD_CARD_V2_0:
printf("Card Type:SDSC V2.0\r\n");
break;
case SDIO_HIGH_CAPACITY_SD_CARD:
printf("Card Type:SDHC V2.0\r\n");
break;
case SDIO_MULTIMEDIA_CARD:
printf("Card Type:MMC Card\r\n");
break;
}
printf("Card ManufacturerID:%d\r\n", SDCardInfo.SD_cid.ManufacturerID); //The manufacturer ID
printf("Card RCA:%d\r\n", SDCardInfo.RCA); //Card relative address
printf("Card Capacity:%d MB\r\n", (u32)(SDCardInfo.CardCapacity >> 20));
printf("Card BlockSize:%d\r\n\r\n", SDCardInfo.CardBlockSize);
}
SD卡的初始化主要进行卡识别和卡状态获取,定义SD_Init()如下:SD_Error SD_Init(void)
{
u32 clk;
RCC_ClocksTypeDef bclk;
u32 targetFreq;
__IO SD_Error errorstatus = SD_OK;
u8 clkdiv = 0;
INTX_DISABLE();
errorstatus = SD_PowerON(); //SD Power On
if (errorstatus != SD_OK) {
return errorstatus;
}
errorstatus = SD_InitializeCards(); //Initialize SD Card
if (errorstatus != SD_OK) {
return errorstatus;
}
errorstatus = SD_GetCardInfo(&SDCardInfo); //Get card information
if (errorstatus != SD_OK) {
return errorstatus;
}
errorstatus = SD_SelectDeselect((u32)(SDCardInfo.RCA << 16)); //Select the SD card
if (errorstatus != SD_OK) {
return errorstatus;
}
errorstatus = SD_EnableWideBusOperation(1); //4 bit width, if it is an MMC card, you cannot use 4 bit mode
if ((errorstatus != SD_OK)) {
if( (SDIO_MULTIMEDIA_CARD == CardType)) {
if (SDCardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1 || SDCardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0) {
clkdiv = 0; //V1.1/V2.0 card with the maximum setting of 48/4=12Mhz
}
else {
clkdiv = 1; //For other cards such as SDHC, the maximum setting is 48/2=24Mhz
}
if(clkdiv != 0) {
targetFreq = 24000000;
}
else {
targetFreq = 12000000;
}
RCC_GetClocksFreq(&bclk);
clk = (bclk.HCLK_Frequency / 2 / 2 / targetFreq - 1);
SDIO_ClockSet(clk);
}
else {
__NOP();
}
}
else {
if (SDCardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V1_1 || SDCardInfo.CardType == SDIO_STD_CAPACITY_SD_CARD_V2_0) {
clkdiv = 0;
}
else {
clkdiv = 1;
}
if(clkdiv != 0) {
targetFreq = 24000000;
}
else {
targetFreq = 12000000;
}
RCC_GetClocksFreq(&bclk);
clk = (bclk.HCLK_Frequency / 2 / 2 / targetFreq - 1);
SDIO_ClockSet(clk);
}
INTX_ENABLE();
return errorstatus;
}
1) SD_PowerON()函数用于查询卡的工作电压和时钟控制配置,并返回 SD_Error 类型错误,该函数是整个 SD 识别的关键函数。
2) SD_InitializeCards()函数初始化SD卡,并将其置入就绪状态;
3) SD_GetCardInfo()函数获取SD卡的信息;
4) SD_SelectDeselect()选择SD卡,发送CMD7命令,选择具有相对地址(RCA)的卡作为ADDR;
5) SD_EnableWideBusOperation()配置SDIO数据宽度;
6) SDIO_ClockSet()配置SDIO的时钟频率。
获取SD卡信息及数据的函数定义如下:void read_sd_card_info(void)
{
u16 i = 5;
SD_Error result;
u32 sd_size;
SDIO_ConfigInit();
printf("SDCARD TEST\r\n");
while(1) {
result = SD_Init();
if(result == SD_OK) {
break;
}
printf("SD Card Error!\r\n");
DELAY_Ms(1);
}
show_sdcard_info();
i = 5;
while(i--) {
if(SD_ReadDisk(&vbuf[0], 0, 1) == 0) {
printf("UART Sending Data...\r\n");
printf("SECTOR 0 DATA:\r\n");
for(sd_size = 0; sd_size < 512; sd_size++) {
printf("%02x ", vbuf[sd_size]);
}
printf("\r\nDATA ENDED\r\n");
printf("UART Send Data Over!\r\n");
}
DELAY_Ms(50);
}
}
实验演示
在MB-039开发板的SDIO/TF卡槽插入SD卡,运行程序,串口调试助手显示如下:
如果SD卡可用,串口调试助手会打印SD卡的信息,包括卡类型、生产ID、RCA、容量和块大小,接着打印扇区0的数据,会连续打印5次该部分内容。
本次实验的例程可以通过MindMotion的官网下载MM32F3270 lib_Samples:
https://www.mindmotion.com.cn/pr ... instream/mm32f3270/
工程路径如下:
~MM32F327x_Samples\ LibSamples\SDIO\SDIO_ReadSDCardInfo
可以看到详细的样例与功能操作。
0