W806開發板SDIO方式初始化SD卡時發送CMD2讀取CID時R2響應失敗

發布於 2022-11-01 16:33:50

W806使用SDIO方式初始化SD卡時,發送CMD2命令後獲取響應R2失敗,希望大神指點。
1.PNG
2.PNG
發送CMD2獲取CID的R2響應時失敗,SD卡2.0手冊R2響應Bit[135-128]=0x3F,程序讀取該值一直為0
程序如下:{{sdio.c(uploading...)}}

3.jpg

define SDIO SDIO_HOST

define CMD_BUFF[x] CMD_BUF[x]

define SDIO_CLK PB6

define SDIO_CMD PB7

define SDIO_D0 PB8

define SDIO_D1 PB9

define SDIO_D2 PB10

define SDIO_D3 PB11//OPT2

define SDIO_GPIO GPIOB

uint8 SD_CardType=0;
// SD卡類型定義

define SD_TYPE_ERR 0x00

define SD_TYPE_MMC 0x01

define SD_TYPE_V1 0x02

define SD_TYPE_V2 0x04

define SD_TYPE_V2HC 0x06

//SD卡指令表

define CMD0 0 //卡複位

define CMD1 1

define CMD2 2

define CMD3 3

define CMD8 8 //命令8 ,SEND_IF_COND

define CMD9 9 //命令9 ,讀CSD數據

define CMD10 10 //命令10,讀CID數據

define CMD12 12 //命令12,停止數據傳輸

define CMD16 16 //命令16,設置SectorSize 應返回0x00

define CMD17 17 //命令17,讀sector

define CMD18 18 //命令18,讀Multi sector

define CMD23 23 //命令23,設置多sector寫入前預先擦除N個block

define CMD24 24 //命令24,寫sector

define CMD25 25 //命令25,寫Multi sector

define CMD41 41 //命令41,應返回0x00

define CMD55 55 //命令55,應返回0x01

define CMD58 58 //命令58,讀OCR信息

define CMD59 59 //命令59,使能/禁止CRC,應返回0x00

define MMC_CMD1_ARG 0x80FF8000 //MMC卡CMD1命令參數

//MMC_IO配置

define MMC_IO_NoAction 0 //MMC_IO無操作

define MMC_IO_JusCret8nck 0x24 //MMC_IO生成8個空閑時鐘

define MMC_IO_SendCmd6 0x04 //發送6字節命令

define MMC_IO_Response6 0x0C //接收6字節響應

define MMC_IO_Response17 0x1C //接收17字節響應

define MMC_IO_Cmd8nclk 0x84 //傳輸命令+8個空閑時鐘

define MMC_IO_CmdRecSp 0x44 //傳輸命令+接收響應

define MMC_IO_RradCidCsdRecp 0x54 //傳輸命令+接收CSD、CID

define MMC_IO_CmdResp8nclk 0xC4 //

define MMC_IO_ReadDat8nck 0x03 //讀MMC_BYTECNT字節

define MMC_IO_WriteDat8nck 0x01 //寫MMC_BYTECNT字節

enum SdCardResponse {SDIOCmdError,SDIOCmdTrue};//命令響應判斷
enum SDflag { SDTrue,SDFall}; //函數返回值:成功/失敗

define SDIO_CLK_EN 18

define SDIO_CLK_RE 27

define Max_RepeatCount 100 //定義重複發送數據最大值

void Init_SDIO_IO()
{

RCC->RST&=~BIT(SDIO_CLK_RE);
RCC->RST|=BIT(SDIO_CLK_RE);
while(!(RCC->RST&BIT(SDIO_CLK_RE)));    //複位SDIO模塊

RCC->CLK_EN|=BIT(SDIO_CLK_EN);
RCC->CLK_MASK|=BIT(1);                    //時鐘使能

SDIO_GPIO->DATA_B_EN|=BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3);
SDIO_GPIO->PULLUP_EN&=~(BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3));
SDIO_GPIO->DIR|=BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3);
SDIO_GPIO->DATA|=BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3);

SDIO_GPIO->AF_SEL|=BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3);
SDIO_GPIO->AF_S0|=BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3);
SDIO_GPIO->AF_S1&=~(BIT(SDIO_CLK)|BIT(SDIO_CMD)|BIT(SDIO_D0)|BIT(SDIO_D1)|BIT(SDIO_D2)|BIT(SDIO_D3));

}

void SDIO_LowSpeed()
{

SDIO->MMC_CTL&=0x7C7;        
SDIO->MMC_CTL|=BIT(5)|BIT(3);
SDIO->MMC_CARDSEL&=0xC0;    
SDIO->MMC_CARDSEL|=0x18;     
SDIO->MMC_CTL&=~BIT(6);        

}

void WaiteCmdTransOver()
{

while(!(SDIO->MMC_INT_SRC&BIT(0)));//等待命令傳輸完成
SDIO->MMC_INT_SRC|=BIT(0);        //清零標志位

}

void SD_SendCmd(uint8 cmd,uint32 cmdarg,uint8 mmcio)
{

SDIO->CMD_BUFF[4]=(cmd|0x40);
SDIO->CMD_BUFF[3]=((cmdarg>>24)&0xFF);
SDIO->CMD_BUFF[2]=((cmdarg>>16)&0xFF);
SDIO->CMD_BUFF[1]=((cmdarg>>8)&0xFF);
SDIO->CMD_BUFF[0]=(cmdarg&0xFF);

SDIO->MMC_INT_SRC|=0x1FF;
SDIO->MMC_IO=mmcio;        

if(cmd==CMD12)
{
    //
}

}

void Init_SDIO_Reg()
{

SDIO->MMC_CARDSEL|=BIT(7)|BIT(6);
SDIO->MMC_CTL=BIT(1)|BIT(0);//1bit模式
SDIO->MMC_PORT=0xFF;
SDIO->MMC_CRCCTL=BIT(7)|BIT(6);

}
uint8 SDIO_GetResponseR1(uint8 cmd,uint32 指針符號 responR1)
{

while(!(SDIO->MMC_INT_SRC&BIT(6)))
{
    if(SDIO->MMC_INT_SRC&BIT(0))
    {
        SDIO->MMC_INT_SRC|=BIT(0);
        if((SDIO->CMD_BUFF[4]&0x3F)==cmd)
        {
            指針符號 responR1=((SDIO->CMD_BUFF[3]<<24)+(SDIO->CMD_BUFF[2]<<16)+(SDIO->CMD_BUFF[1]<<8)+(SDIO->CMD_BUFF[0]));
            return SDIOCmdTrue;
        }
    }
}
SDIO->MMC_INT_SRC|=BIT(6);
return SDIOCmdError;    

}
uint8 SDIO_GetResponseR2(uint8 指針符號 responR2buff)
{

uint8 i=0;

for(i=0;i<200;i++)
{
    while(!(SDIO->MMC_INT_SRC&BIT(0)));
    SDIO->MMC_INT_SRC|=BIT(0);
    printf("ResponR2[135-128]=%d\n",SDIO->CMD_BUFF[15]);//R2響應失敗

    if(SDIO->CMD_BUFF[15]==0x3F)
    {
        printf("ResponR2[135-128]=%d\n",SDIO->CMD_BUFF[15]);
        for(i=0;i<15;i++)
            {
                指針符號 responR2buff++=SDIO->CMD_BUFF[i];
                printf("CID[%d]=%d\n",i,SDIO->CMD_BUFF[i]);
            }
            return SDIOCmdTrue;
    }else
    {
        SD_SendCmd(CMD2,0,MMC_IO_RradCidCsdRecp);
    }
    
}
return SDIOCmdError;

}

uint8 SDIO_GetResponseR3(uint32 指針符號 responR3)
{

while(!(SDIO->MMC_INT_SRC&BIT(6)))
{
    if(SDIO->MMC_INT_SRC&BIT(0))
    {
        SDIO->MMC_INT_SRC|=BIT(0);
        
        指針符號 responR3=((SDIO->CMD_BUFF[3]<<24)+(SDIO->CMD_BUFF[2]<<16)+(SDIO->CMD_BUFF[1]<<8)+(SDIO->CMD_BUFF[0]));
        return SDIOCmdTrue;

    }
}
SDIO->MMC_INT_SRC|=BIT(6);
return SDIOCmdError;    

}

uint8 Init_SDCard()
{

uint8 respon,cnt=0;
uint32 ReState;
uint16 SD_RCA,SD_State;
uint8 cid_csd_buff[16];    //獲取CID、CSD緩存

Init_SDIO_IO();
Init_SDIO_Reg();
SDIO_LowSpeed();

for(cnt=0;cnt<10;cnt++)// 74個CLK
{
    SDIO->MMC_IO=MMC_IO_JusCret8nck;
    while(SDIO->MMC_IO&BIT(2));
}

SD_SendCmd(CMD0,0,MMC_IO_SendCmd6);//複位卡
WaiteCmdTransOver();

查看更多

關注者
0
被浏覽
2.3k
1 個回答
isme
isme 認證專家 2022-11-07
冰鎮大西瓜

可以看看這篇文章,可能對你有幫助。http://ask.winnermicro.com/article/36.html

撰寫答案

請登錄後再發布答案,點擊登錄

發布
問題

分享
好友

手機
浏覽

掃碼手機浏覽