STM32F407,SD卡读取时crc错误,原代码

2019-07-20 03:34发布

#include "stm32f407xx.h"
#include "system.h"
#include "SD.h"
#include "led.h"

static u32 CID_tab[4],CSD_tab[4],RCA = 0,SCR_tab[2];
static void SD_Send_CMD(u8 Cmd,u8 Waitrsp,u32 Argment);
static void SD_Data_Cfg(u32 timeout,u16 blocklen,u8 size,u8 dir);
__align(4) u8 SDIO_DATA_BUFFER[512];

//==================================================================================================================
//¡¾1|Äü¡¿SD¿¨¸ßèYá¿¿¨3õê¼»ˉ
//¡¾èë¿ú2Îêy¡¿  ÎT
//              
//              
//¡¾3ö¿ú2Îêy¡¿  ÎT
//==================================================================================================================
void SD_Init(void)
{
u32 temp;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_DMA2EN; //ê1ÄüPC£&#172D£¬DMA2ê±Öó
RCC->APB2ENR |= RCC_APB2ENR_SDIOEN;                                             //ê1ÄüSDIOíaéèê±Öó
RCC->APB2RSTR |= RCC_APB2RSTR_SDIORST;                                          //¸′λíaéèSDIOê±Öó

GPIO_Config(GPIOC,PIN8|PIN9|PIN10|PIN11|PIN12,GPIO_ALTER_PUPP50M,1);              //éèÖ&#195C8,PC9,PC10,PC11,PC12Îa¸′óÃíÆíìêä3ö
GPIO_Config(GPIOD,PIN2,GPIO_ALTER_PUPP50M,1);                                     //éèÖ&#195D2Îa¸′óÃíÆíìêä3ö
GPIO_SetAF(GPIOC,PIN8|PIN9|PIN10|PIN11|PIN12,GPIO_AF_FMC_SDIO);                 //PC8,PC9,PC10,PC11,PC12¸′óÃÎaSDIOÄ£ê½
GPIO_SetAF(GPIOD,PIN2,GPIO_AF_FMC_SDIO);                                        //PD2¸′óÃÎaSDIOÄ£ê½

RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST;                                         //¸′λ½áêø



/*****************SDIOíaéè¼Ä′æÆ÷éèÖÃÎaĬèÏÖμ********************/
SDIO->OWER = 0;
SDIO->CLKCR = 0;
SDIO->ARG = 0;
SDIO->CMD = 0;
SDIO->DTIMER = 0;
SDIO->DLEN = 0;
SDIO->DCTRL = 0;
SDIO->ICR = 0x00C007FF;                                                         //ÖD¶ÏÇåáã¼Ä′æÆ÷Çåáã
SDIO->MASK = 0;
/**************************éèÖÃÖD¶Ï*****************************/
NVIC_Init(0,0,SDIO_IRQN,2);
/***************************************************************/               //éèÖÃÖD¶Ï

SDIO->CLKCR = 0;                                                                        //Çå¿ÕCLKCR֮ǰμÄéèÖÃ
SDIO->CLKCR |= SDIO_CLKCR_WIDBUS_0;
SDIO->CLKCR |= 0x76;                                                             //éèÖÃê±ÖóÎa400K
SDIO->OWER = SDIO_POWER_PWRCTRL;                                               //éÏμ磬¿aÆôê±Öó
SDIO->CLKCR |= SDIO_CLKCR_CLKEN;                                                //ê±Öóê1Äü

SD_Send_CMD(0,0,0);                                                             //·¢Ëícmd0
while(!(SDIO->STA & SDIO_STA_CMDSENT));                                         //μè′yÃüáî·¢Ëí
SDIO->ICR = 0x5ff;
SD_Send_CMD(8,1,0x01aa);                                                        //·¢ËíCMD8£¬¶ìÏìó|£¬ 01£oμçÑ1·¶Î§2.7~3.6. aa£oĬèÏÖμ
while(!(SDIO->STA & SDIO_STA_CMDREND));
SDIO->ICR = 0x5ff;
SD_Send_CMD(55,1,0);                                                            //·¢Ëícmd55,¶ìÏìó|£¬2ÎêyÎa0
while((!(SDIO->STA & SDIO_STA_CMDREND))&&(SDIO->RESPCMD == 55));                //μè′yR1Ïìó|£¬2¢Çò·μ»ØμÄÃüáîÖμÕyè·
SDIO->ICR = 0x5ff;                                                              //Çå3y±ê־λ
temp = SDIO->RESP1;
//=============================================================
//¸Ã2¿·Öμè′ySD¿¨éÏμ磬2¢ÇòSD¿¨Îa¸ßèYá¿¿¨£¬×¢òa·¢ËíÃüáîÖ®oóμè′yÑó3ù£¬2ÅÄüÕyè·¶áè¡RESP1μÄÖμ
//===============================================================
while(1)
    {

    SD_Send_CMD(55,1,0);                                                            //·¢Ëícmd55£¬¶ìÏìó|£¬2ÎêyÎa0£»
    while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 55));                //μè′yR1Ïìó|£¬2¢Çò·μ»ØμÄÃüáîÖμÕyè·
    SDIO->ICR = 0x5ff;
    temp = SDIO->RESP1;
    SD_Send_CMD(41,1,0x8010000|0x40000000);                                         //·¢Ëícmd41£¬¶ìÏìó|£¬2ÎêyÎa0x8010000|0x40000000
    while(!((SDIO->STA & SDIO_STA_CMDREND)||(SDIO->STA & SDIO_STA_CCRCFAIL)||(SDIO->STA & SDIO_STA_CTIMEOUT)));
    delay(10);                                                                      //ò»¶¨òaóDÑó3ù                           
    temp = SDIO->RESP1;
    SDIO->ICR = 0x5ff;
    if((temp & 0xc0000000) == 0xc0000000)break;
    }
//=============================================================
SD_Send_CMD(2,3,0);                                                                 //·¢Ëícmd2£¬3¤Ïìó|£¬2ÎêyÎa0  ÅD¶ÏSD¿¨êÇ·ñ½óèë
while(!(SDIO->STA & SDIO_STA_CMDREND));
delay(10);
CID_tab[0] = SDIO->RESP1;
CID_tab[1] = SDIO->RESP2;
CID_tab[2] = SDIO->RESP3;
CID_tab[3] = SDIO->RESP4;
SDIO->ICR = 0x5ff;
SD_Send_CMD(3,1,0);                                                                 //·¢Ëícmd3£¬¶ìÏìó|£¬2ÎêyÎa0  ¶áè¡SD¿¨μÄμØÖ·
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 3));
temp = SDIO->RESP1;                     
RCA = temp>>16;                                                                     //μÃμ½RCAμÄÖμ
SDIO->ICR = 0x5ff;
SD_Send_CMD(9,3,RCA<<16);                                                           //·¢&#203;ícmd9£&#172;3¤&#207;ìó|£&#172;2&#206;êy&#206;aμ&#216;&#214;·£&#172;&#182;áè&#161;CSDμ&#196;&#214;μ
while(!(SDIO->STA & SDIO_STA_CMDREND));
delay(10);
CSD_tab[0] = SDIO->RESP1;
CSD_tab[1] = SDIO->RESP2;
CSD_tab[2] = SDIO->RESP3;
CSD_tab[3] = SDIO->RESP4;
SDIO->ICR = 0x5ff;
SD_Send_CMD(7,1,RCA<<16);                                                           //ê1&#196;üSD&#191;¨
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 7));  
SDIO->ICR = 0x5ff;
SD_Send_CMD(16,1,8);                                                                //·¢&#203;ícmd16£&#172;&#182;ì&#207;ìó|£&#172;8&#184;&#246;×&#214;&#189;ú
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 16));                    
SD_Send_CMD(55,1,RCA<<16);                                                          //·¢&#203;ícmd55£&#172;&#182;ì&#207;ìó|£&#172;RCAμ&#216;&#214;·
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 55));  
SDIO->ICR = 0x5ff;
SD_Data_Cfg(0xfffffff,8,3,1);
SD_Send_CMD(51,1,0);                                                                 //·¢&#203;íacmd51£&#172;&#182;ì&#207;ìó|£&#172;2&#206;êy&#206;a0
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 51));
SDIO->ICR = 0x5ff;
temp = 0;
while(!(SDIO->STA & SDIO_STA_DBCKEND))
    {
    if(SDIO->STA & SDIO_STA_RXDAVL)
        {
        SCR_tab[temp]=SDIO->FIFO;
        temp++;
        if(temp>=2)break;
        }
    }
SD_Send_CMD(55,1,RCA<<16);                                                          //·¢&#203;ícmd55£&#172;&#182;ì&#207;ìó|£&#172;RCAμ&#216;&#214;·
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 55));  
SDIO->ICR = 0x5ff;
SD_Send_CMD(6,1,2);                                                                 //·¢&#203;íacmd6£&#172;éè&#214;&#195;SD&#191;¨&#206;a4&#206;&#187;&#207;&#223;&#191;í&#161;£
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 6));
SDIO->ICR = 0x5ff;;;
SDIO->CLKCR &= ~(3<<11);
SDIO->CLKCR |= 1<<11;                                                               //éè&#214;&#195;&#206;a4&#206;&#187;&#206;&#187;&#191;í
SDIO->CLKCR |= 0<<14;
temp = SDIO->CLKCR;
temp &= 0xffffff00;
temp |= 0;
SDIO->CLKCR = temp;                                                                 //&#184;ü&#184;&#196;ê±&#214;ó&#206;a24M
}
//==================================================================================================================
//&#161;&#190;1|&#196;ü&#161;&#191;D′è&#235;Cmd&#195;üá&#238;
//&#161;&#190;è&#235;&#191;ú2&#206;êy&#161;&#191;      Cmd£o&#195;üá&#238;Dòo&#197;
//              Waitrsp£o&#198;ú′y&#195;üá&#238;&#207;ìó| 0£&#187;&#206;T&#207;ìó|£&#172;1&#182;ì&#207;ìó|£&#172;33¤&#207;ìó|
//                  Arg£o&#195;üá&#238;2&#206;êy
//&#161;&#190;3&#246;&#191;ú2&#206;êy&#161;&#191;  &#206;T
//==================================================================================================================
void SD_Send_CMD(u8 Cmd,u8 Waitrsp,u32 Argment)
{
u32 temp;
SDIO->ARG = Argment;                                                            //éè&#214;&#195;&#195;üá&#238;2&#206;êy
temp = SDIO->CMD;                                                               //&#182;áè&#161;CMD&#188;&#196;′&#230;&#198;÷
temp &= 0xfffff800;                                                             //&#206;&#187;0~&#206;&#187;10 &#199;&#229;á&#227;
temp |= Cmd&0x3f;                                                               //&#195;üá&#238;&#203;÷òy&#206;aCmd
temp |= Waitrsp<<6;                                                             //éè&#214;&#195;&#207;ìó|ààDí
temp |= 0<<8;                                                                   //&#206;Tμè′y
temp |= SDIO_CMD_CPSMEN;                                                        //ê1&#196;ü&#195;üá&#238;í¨μà×′ì&#172;&#187;ú
SDIO->CMD = temp;                                                               //&#189;&#171;&#214;μD′è&#235;CMD&#188;&#196;′&#230;&#198;÷
}
//==================================================================================================================
//&#161;&#190;1|&#196;ü&#161;&#191;SDIO êy&#190;Y2ù×÷&#197;&#228;&#214;&#195;oˉêy
//&#161;&#190;è&#235;&#191;ú2&#206;êy&#161;&#191;  timeout£o3&#172;ê±ê±&#188;&#228;
//             blocklen£o′&#171;ê&#228;êy&#190;Yμ&#196;3¤&#182;è(0~65535)
//                  dir£oêy&#190;Y′&#171;ê&#228;μ&#196;·&#189;&#207;ò 0,′ó&#191;&#216;&#214;&#198;&#198;÷μ&#189;&#191;¨£&#172;1′ó&#191;¨μ&#189;&#191;&#216;&#214;&#198;&#198;÷
//&#161;&#190;3&#246;&#191;ú2&#206;êy&#161;&#191;  &#206;T
//&#161;&#190;×¢òa&#161;&#191;&#212;úD′è&#235;êy&#190;Y&#191;&#216;&#214;&#198;&#188;&#196;′&#230;&#198;÷SDIO->DCTRL&#214;&#174;&#199;°£&#172;±&#216;D&#235;&#207;èD′è&#235;3&#172;ê±&#188;&#196;′&#230;&#198;÷SDIO->DTIMERoíêy&#190;Y3¤&#182;è&#188;&#196;′&#230;&#198;÷SDIO->DLEN
//==================================================================================================================
void SD_Data_Cfg(u32 timeout,u16 blocklen,u8 size,u8 dir)
{
u32 temp;
SDIO->DTIMER = timeout;                                                         //éè&#214;&#195;3&#172;ê±ê±&#188;&#228;
SDIO->DLEN = blocklen&0x1ffffff;                                                      //éè&#214;&#195;′&#171;ê&#228;μ&#196;×&#214;&#189;ú£&#172;òò&#206;aê&#199;SDHC&#184;&#223;èYá&#191;&#191;¨£&#172;ê&#244;óú&#191;é′&#171;ê&#228;£&#172;&#195;&#191;&#191;é′óD&#161;&#206;a512
temp = SDIO->DCTRL;                                                             //&#182;áè&#161;DCRTL&#188;&#196;′&#230;&#198;÷
temp &= 0xffffff00;                                                             //&#199;&#229;3y&#214;&#174;&#199;°éè&#214;&#195;
temp |= size<<4;                      //éè&#214;&#195;êy&#190;Y&#191;é′óD&#161;&#206;a512×&#214;&#189;ú 1001
temp |= 0<<2;
temp |= (dir&0x01) << 1;                                                               //éè&#214;&#195;êy&#190;Y′&#171;ê&#228;μ&#196;·&#189;&#207;ò
temp |= SDIO_DCTRL_DTEN;                                                        //ê1&#196;üêy&#190;Y×′ì&#172;&#187;ú
SDIO->DCTRL = temp;
}

u8 SD_Read_Block(u8 *buf,long long addr,u16 blksize)
{
u8 key=0;
u32 count=0,temp=0,*tempbuf = (u32*)buf;
SDIO->DCTRL = 0;
blksize = 512;
addr>>=9;
SD_Data_Cfg(0xffffffff,0,0,0);
if(SDIO->RESP1&0x02000000){LED = 0;while(1);}
SD_Send_CMD(16,1,512);
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 16));
SDIO->ICR = 0x5ff;
delay(1);
SD_Data_Cfg(0xffffffff,512,9,1);
SD_Send_CMD(17,1,0);                                                        //·¢&#203;íCMD17£&#172;&#182;ì&#207;ìó|£&#172;&#182;áè&#161;μ&#196;μ&#216;&#214;·
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 17));  
delay(1);
SDIO->ICR = 0x5ff;                                                      //&#199;&#229;3y&#214;D&#182;&#207;
while(!(SDIO->STA & SDIO_STA_DBCKEND))
    {
    if(SDIO->STA & SDIO_STA_RXFIFOHF)
        {
        for(count=0;count<8;count++)
            {
            *(tempbuf+count) = SDIO->FIFO;
            }
        tempbuf += 8;
        }
     if(SDIO->STA&((1<<5)|(1<<1)|(1<<3)|(1<<9)))
        {
        temp = SDIO->STA;
        if(temp>0)
        LED = 0;
        }
    }

while(SDIO->STA & SDIO_STA_RXDAVL)
    {
    LED = 0;
    *tempbuf = SDIO->FIFO;
    tempbuf++;
    key = 0;
    }
SDIO->ICR = 0x5ff;
return key;
}

u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{
        u8 sta=0;
        long long lsector=sector;
        u8 n;
        lsector<<=9;
        if((u32)buf%4!=0)
        {
                 for(n=0;n<cnt;n++)
                {
                         sta=SD_Read_Block(SDIO_DATA_BUFFER,lsector+512*n,512);//μ¥&#184;&#246;sectorμ&#196;&#182;á2ù×÷
                        //memcpy(buf,SDIO_DATA_BUFFER,512);
                        buf+=512;
                }
        }else
        {
                if(cnt==1)sta=SD_Read_Block(buf,lsector,512);            //μ¥&#184;&#246;sectorμ&#196;&#182;á2ù×÷
                //else sta=SD_ReadMultiBlocks(buf,lsector,512,cnt);//&#182;à&#184;&#246;sector  
        }
        return sta;
}
//void SD_Write_Block(u8 *buf,u32 block)
//{
//u32 timeout,status,temp,count,*tempbuf = (u32*)buf;
//SD_Data_Cfg(0xffffffff,0,0);
//if(SDIO->RESP1&0x02000000){LED = 0;while(1);}
//SD_Send_CMD(16,1,512);
//while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 16));
//SDIO->ICR = 0x5ff;
//SD_Send_CMD(13,1,RCA<<16);
//while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 13));
//delay(10);
//status = SDIO->RESP1;
//SDIO->ICR = 0x5ff;
//timeout = 0xffffffff;
//while((status&0x100)&(timeout>0))
//    {
//    SD_Send_CMD(13,1,RCA<<16);
//    while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 13));
//    delay(10);
//    status = SDIO->RESP1;
//    SDIO->ICR = 0x5ff;
//    }
//if(timeout == 0){LED = 0;while(1);}
//SD_Send_CMD(24,1,block);
//while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 24));
//SDIO->ICR = 0x5ff;
//SD_Data_Cfg(0xffffffff,1,0);
//while(!(SDIO->STA & SDIO_STA_DBCKEND))
//    {
//    temp = SDIO->STA;
//            if(temp>0)
//            LED = 0;
//    if(SDIO->STA & SDIO_STA_TXFIFOHE)
//        {
//        for(count=0;count<8;count++)
//            {
//            SDIO->FIFO = *(tempbuf+count);
//            }
//            tempbuf += 8;
//            temp = SDIO->STA;
//            if(temp>0)
//            LED = 0;
//        }
//     if(SDIO->STA&((1<<5)|(1<<1)|(1<<3)|(1<<9)))
//        {
//        temp = SDIO->STA;
//        if(temp>0)
//        LED = 0;
//        }
//    }
//}




























友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。