#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£¬
D£¬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); //éèÖÃ
C8,PC9,PC10,PC11,PC12Îa¸′óÃíÆíìêä3ö
GPIO_Config(GPIOD,PIN2,GPIO_ALTER_PUPP50M,1); //éèÖÃ
D2Î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); //·¢Ëícmd9£¬3¤Ïìó|£¬2ÎêyÎaμØÖ·£¬¶áè¡CSDμÄÖμ
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ÄüSD¿¨
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 7));
SDIO->ICR = 0x5ff;
SD_Send_CMD(16,1,8); //·¢Ëícmd16£¬¶ìÏìó|£¬8¸ö×Ö½ú
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 16));
SD_Send_CMD(55,1,RCA<<16); //·¢Ëícmd55£¬¶ìÏìó|£¬RCAμØÖ·
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); //·¢Ëíacmd51£¬¶ìÏìó|£¬2ÎêyÎ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); //·¢Ëícmd55£¬¶ìÏìó|£¬RCAμØÖ·
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 55));
SDIO->ICR = 0x5ff;
SD_Send_CMD(6,1,2); //·¢Ëíacmd6£¬éèÖÃSD¿¨Îa4λÏß¿í¡£
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 6));
SDIO->ICR = 0x5ff;;;
SDIO->CLKCR &= ~(3<<11);
SDIO->CLKCR |= 1<<11; //éèÖÃÎa4λλ¿í
SDIO->CLKCR |= 0<<14;
temp = SDIO->CLKCR;
temp &= 0xffffff00;
temp |= 0;
SDIO->CLKCR = temp; //¸ü¸Äê±ÖóÎa24M
}
//==================================================================================================================
//¡¾1|Äü¡¿D′èëCmdÃüáî
//¡¾èë¿ú2Îêy¡¿ Cmd£oÃüáîDòoÅ
// Waitrsp£oÆú′yÃüáîÏìó| 0£»ÎTÏìó|£¬1¶ìÏìó|£¬33¤Ïìó|
// Arg£oÃüáî2Îêy
//¡¾3ö¿ú2Îêy¡¿ ÎT
//==================================================================================================================
void SD_Send_CMD(u8 Cmd,u8 Waitrsp,u32 Argment)
{
u32 temp;
SDIO->ARG = Argment; //éèÖÃÃüáî2Îêy
temp = SDIO->CMD; //¶áè¡CMD¼Ä′æÆ÷
temp &= 0xfffff800; //λ0~λ10 Çåáã
temp |= Cmd&0x3f; //ÃüáîË÷òyÎaCmd
temp |= Waitrsp<<6; //éèÖÃÏìó|ààDí
temp |= 0<<8; //ÎTμè′y
temp |= SDIO_CMD_CPSMEN; //ê1ÄüÃüáîí¨μà×′쬻ú
SDIO->CMD = temp; //½«ÖμD′èëCMD¼Ä′æÆ÷
}
//==================================================================================================================
//¡¾1|Äü¡¿SDIO êy¾Y2ù×÷ÅäÖÃoˉêy
//¡¾èë¿ú2Îêy¡¿ timeout£o3¬ê±ê±¼ä
// blocklen£o′«êäêy¾YμÄ3¤¶è(0~65535)
// dir£oêy¾Y′«êäμÄ·½Ïò 0,′ó¿ØÖÆÆ÷μ½¿¨£¬1′ó¿¨μ½¿ØÖÆÆ÷
//¡¾3ö¿ú2Îêy¡¿ ÎT
//¡¾×¢òa¡¿ÔúD′èëêy¾Y¿ØÖƼÄ′æÆ÷SDIO->DCTRL֮ǰ£¬±ØDëÏèD′èë3¬ê±¼Ä′æÆ÷SDIO->DTIMERoíêy¾Y3¤¶è¼Ä′æÆ÷SDIO->DLEN
//==================================================================================================================
void SD_Data_Cfg(u32 timeout,u16 blocklen,u8 size,u8 dir)
{
u32 temp;
SDIO->DTIMER = timeout; //éèÖÃ3¬ê±ê±¼ä
SDIO->DLEN = blocklen&0x1ffffff; //éèÖÃ′«êäμÄ×Ö½ú£¬òòÎaêÇSDHC¸ßèYá¿¿¨£¬êôóú¿é′«ê䣬ÿ¿é′óD¡Îa512
temp = SDIO->DCTRL; //¶áè¡DCRTL¼Ä′æÆ÷
temp &= 0xffffff00; //Çå3y֮ǰéèÖÃ
temp |= size<<4; //éèÖÃêy¾Y¿é′óD¡Îa512×Ö½ú 1001
temp |= 0<<2;
temp |= (dir&0x01) << 1; //éèÖÃêy¾Y′«êäμÄ·½Ïò
temp |= SDIO_DCTRL_DTEN; //ê1Äüêy¾Y×′쬻ú
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); //·¢ËíCMD17£¬¶ìÏìó|£¬¶áè¡μÄμØÖ·
while((!(SDIO->STA & SDIO_STA_CMDREND))||(SDIO->RESPCMD != 17));
delay(1);
SDIO->ICR = 0x5ff; //Çå3yÖD¶Ï
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);//μ¥¸ösectorμĶá2ù×÷
//memcpy(buf,SDIO_DATA_BUFFER,512);
buf+=512;
}
}else
{
if(cnt==1)sta=SD_Read_Block(buf,lsector,512); //μ¥¸ösectorμĶá2ù×÷
//else sta=SD_ReadMultiBlocks(buf,lsector,512,cnt);//¶à¸ö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;
// }
// }
//}
一周热门 更多>