⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdmmc.c

📁 SD卡的其本操作函数
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "..\define.h"
#include "..\all.h"

data	bit	gc_SysCardInsert;
data	bit	SDHC=0;

xdata	U8	gc_SD_OCR[4];
xdata	U8	gc_SD_RCA[2];
xdata	U8	gc_SD_CID[16];
xdata	U8	gc_SD_CSD[16];
xdata	U32	gw_SD_BlockNum;	
xdata	U16	gw_SD_BlockSize;
xdata	U16	gw_WaitTimeOut;

extern	data	U8	gc_SectorUnit;

extern	xdata	U32	gdw_DOS_SectorPerCard;

void	SD_SetClock(U8 ClockValue);
void	SdDetect(void);
void	CommandToSd(U8 *ComBuff);
void	SdTxDummy(void); 
void	SDWaitIdle(void);
void	SD_SetBlockLen(U16 BlockSize);
bit		STORAGE_Detect();
U8		SD_SetInterface(U8 tc_CurrCard);
U8		SDIdentification(U8 tc_CurrCard);
U8		SDToRespond(U8 *tc_RespBuff,U8 tc_RespType, U8 tc_CRC);
U8		SDCheckDat0(void);
U8		SD_SetBusWidth(U8 tc_BusMode);
U8		SD_Initializes(U8 tc_CurrCard);
U8		SD_StandByToTrans(void);
U8		SD_STORAGE_Initialize(void);
U8		SD_Read_LogicSector (U32 tdw_LogicSectorAddr,U32 tdw_ReadSectorNumber);
U8		SD_Write_LogicSector(U32 tdw_LogicSectorAddr,U32 tdw_WriteSectorNumber);
U8		UsbReadWaitSD(U8 tc_ReadOrWrite);
U8		UsbReadWaitBank1USB(U8 tc_ReadOrWrite);

extern U8 USER_READSAR(U8 tc_SARChannel);


void SD_SetClock(U8 ClockValue)
{
	// 0=24M 1=12M 2=6M 3=375K
	U8 tmp;

	tmp = XBYTE[REG_SD_TIMER];
   	tmp = (tmp&0xfc)|(ClockValue&0x03);
	XBYTE[REG_SD_TIMER]=tmp;
}


void SdDetect(void)
{
	U8 tc_Loop;
	U32 tdw_Bitcompare;
	
	tdw_Bitcompare = 0x80000000;
	
	for (tc_Loop = 0; tc_Loop < 32; tc_Loop ++)
	{
		if (gdw_CARD_TotalSizeMB & tdw_Bitcompare)
		{
			if ((gdw_CARD_TotalSizeMB & (~tdw_Bitcompare)) == 0)
			{
				gdw_CARD_TotalSizeMB = tdw_Bitcompare;
			}
			else
			{
				gdw_CARD_TotalSizeMB = tdw_Bitcompare << 1;
		   	}			
		}
		tdw_Bitcompare >>= 1;
	}
}


U8 SD_SetInterface(U8 tc_CurrCard)
{
 	FlashExchang(tc_CurrCard,gc_CurrentCard,1);
	XBYTE[REG_WAITRSPTIME] = 0xff;//REG_WAITRSPTIME	= 0xB457
	XBYTE[REG_WAITCRCTIME] = 0x08;//REG_WAITCRCTIME = 0xB458
	if(tc_CurrCard==CURRENT_MEDIA_SD)
	{
		XBYTE[REG_SD_TIMER] = 0x30;  //set sd card mode
	}
	else if(tc_CurrCard==CURRENT_MEDIA_MMC)
	{
		XBYTE[REG_SD_TIMER] = 0x70;	 //set mmc card mode
	}
	
	XBYTE[0xB451]&=0xf7;

	SD_SetClock(3);
	XBYTE[REG_SD_TIMER]&=0xfb;//set the clock frequency 6MHZ
	SD_SetBlockLen(C_BLOCKSIZE);//C_BLOCKSIZE = 512

	if(SDIdentification(tc_CurrCard))
	{//not insert  		
		if(SDIdentification(tc_CurrCard))
		{
			gc_ReadWriteTimeOut = 0;
			return 1;	
		}
	}
	gc_ReadWriteTimeOut = 0;
	return 0;
}


U8 SDIdentification(U8 tc_CurrCard)
{
	U8 	tc_ComBuff[5],tc_RespBuff[17];
	U8 	tc_Ture,tc_i;
	U8 	tc_ReadBl_Len;
	U16 tw_BlockLen;
	U16	tw_Mult;
	U32	tw_CSize;
	U8  tc_CSizeMult;	
	U32 tdw_CardTotalSize;
	
	// Tx 100 clock for power on sequence
	for(tc_i=0; tc_i<100; tc_i++)
	{			
		SdTxDummy();
	}
	
	SDHC=0;

	// CMD0
	tc_ComBuff[0]=0x40; 
	tc_ComBuff[1]=0x00; 
	tc_ComBuff[2]=0x00; 
	tc_ComBuff[3]=0x00; 
	tc_ComBuff[4]=0x00; 
	CommandToSd(tc_ComBuff);

	// 8 dummy clock
	SdTxDummy();

	if(tc_CurrCard==CURRENT_MEDIA_SD)
	{	
		// CMD8
		tc_ComBuff[0]=0x48; 
		tc_ComBuff[1]=0x00; 
		tc_ComBuff[2]=0x00; 
		tc_ComBuff[3]=0x01; 
		tc_ComBuff[4]=0x17; 
		CommandToSd(tc_ComBuff); 
		tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,0);
		if((tc_Ture==0)&&(tc_RespBuff[0]==0x08)&&(tc_RespBuff[4]==0x17))
		{
			SDHC=1;
		}

		// CMD55
		while(1)
		{  
			tc_ComBuff[0]=0x77; 
			tc_ComBuff[1]=0x00; 
			tc_ComBuff[2]=0x00; 
			tc_ComBuff[3]=0x00; 
			tc_ComBuff[4]=0x00; 
			CommandToSd(tc_ComBuff); 
			tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,0);
			if((tc_Ture)||(tc_RespBuff[0]!=0x37))
			{
			   	return 1;	
			}

			// ACMD41
			tc_ComBuff[0]=0x69; 
			if(SDHC==1)
			{
				tc_ComBuff[1]=0x40; 
				tc_ComBuff[2]=0xFF;
				tc_ComBuff[3]=0x80; 
				tc_ComBuff[4]=0x00; 
			}
			else
			{
				tc_ComBuff[1]=0x00; 
				tc_ComBuff[2]=0x04;
				tc_ComBuff[3]=0x00; 
				tc_ComBuff[4]=0x00; 
			}

			CommandToSd(tc_ComBuff);           
			tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,0);
			//检查回应是否有错误	
			if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
			{
			   	return 1;	
			}
		
			if(tc_RespBuff[1]&0x80)
			{
				if((tc_RespBuff[1]&0x40)==0)	// SD 2.0 standard capacity, maxliao 20071224
				{
					SDHC=0;	
				}
				break;
			}
		}
		gc_SD_RCA[0]=0;
		gc_SD_RCA[1]=0;	
	}
	else if(tc_CurrCard==CURRENT_MEDIA_MMC)
	{
		SDHC=0;
		//send cmd1 to make mmc to ready state
		do{
			tc_ComBuff[0]=0x41; 
			tc_ComBuff[1]=0x00; 
			tc_ComBuff[2]=0x04; 
			tc_ComBuff[3]=0x00; 
			tc_ComBuff[4]=0x00; 
			CommandToSd(tc_ComBuff);
			tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,C_NotCrcCheck);
			
			//检查回应是否有错误	
			if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
			{
			   	return 1;	
			} 
		    //等待card的power up status bit 						
		   }while((tc_RespBuff[1]&0x80)==0);
	
		gc_SD_RCA[0]=0x55;
		gc_SD_RCA[1]=0xaa;	
	}

	for(tc_i=0; tc_i<4; tc_i++)
	{
		gc_SD_OCR[tc_i] = tc_RespBuff[tc_i+1];
	}	

	// CMD2
	tc_ComBuff[0]=0x42; 
	tc_ComBuff[1]=0x00; 
	tc_ComBuff[2]=0x00; 
	tc_ComBuff[3]=0x00; 
	tc_ComBuff[4]=0x00;
	CommandToSd(tc_ComBuff);
	tc_Ture=SDToRespond(tc_RespBuff,C_136BitRsp,C_NotCrcCheck);
	if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
	{
	   	return 1;	
	}

	for(tc_i=0; tc_i<16; tc_i++)
	{
		gc_SD_CID[tc_i] = tc_RespBuff[tc_i+1];
	}
	
	// CMD3
	tc_ComBuff[0]=0x43; 
	tc_ComBuff[1]=gc_SD_RCA[0]; 
	tc_ComBuff[2]=gc_SD_RCA[1]; 
	tc_ComBuff[3]=0x00; 
	tc_ComBuff[4]=0x00; 
	CommandToSd(tc_ComBuff);      
    tc_Ture=SDToRespond(tc_RespBuff,C_48BitRsp,C_NeedCrcCheck);
	if((tc_Ture)||(tc_RespBuff[0]!=0x03))
	{
	   	return 1;	
	}

	if(tc_CurrCard==CURRENT_MEDIA_SD)
	{
		gc_SD_RCA[0]=tc_RespBuff[1];
		gc_SD_RCA[1]=tc_RespBuff[2];
	}
	
	// CMD9
	tc_ComBuff[0] =	0x49;
	tc_ComBuff[1] =	gc_SD_RCA[0];
	tc_ComBuff[2] =	gc_SD_RCA[1];
	tc_ComBuff[3] =	0x00;
	tc_ComBuff[4] =	0x00;
	CommandToSd(tc_ComBuff);			
    tc_Ture=SDToRespond(tc_RespBuff,C_136BitRsp,C_NotCrcCheck); 
    	
	if((tc_Ture)||(tc_RespBuff[0]!=0x3f))
	{
	   	return 1;	
	}

	for(tc_i=0; tc_i<16; tc_i++)
	{		
		gc_SD_CSD[tc_i]=tc_RespBuff[tc_i+1];
	}
	
	tc_ReadBl_Len=gc_SD_CSD[5]&0x0f;	
    tw_BlockLen=0x01<< tc_ReadBl_Len;
	gw_SD_BlockSize = tw_BlockLen;
	
	if(SDHC==1)
	{
		tw_CSize=(((U32)gc_SD_CSD[7])<<16)|((U32)gc_SD_CSD[8]<<8)|((U32)gc_SD_CSD[9]); 
		gw_SD_BlockNum = (tw_CSize+1)*1024;
	}
	else
	{
		tw_CSize	= (((U16)gc_SD_CSD[6]) << 10) |	((U16)gc_SD_CSD[7] << 2) | ((U16)gc_SD_CSD[8] >> 6); 
		tc_CSizeMult=((gc_SD_CSD[9] & 0x03) << 1) | (gc_SD_CSD[10] >> 7); 
		tw_Mult =	0x0001 << (tc_CSizeMult + 2);
		gw_SD_BlockNum = (U32)(tw_CSize +	1) * (U32)tw_Mult;              //get block num
	}

	tdw_CardTotalSize = gw_SD_BlockNum*(U32)tw_BlockLen;
	gdw_DOS_SectorPerCard = tdw_CardTotalSize/512;
	gdw_CARD_TotalSizeMB = tdw_CardTotalSize>>20;

	SdDetect();//将容量转换成整数
	SD_SetClock(1);

	return 0;			
}


U8 SDToRespond(U8 *tc_RespBuff,U8 tc_RespType, U8 tc_CRC) 

{
	U8 tc_FullFlag,tc_CRC7;
	U8 tc_i;
	
	if(tc_RespType == C_48BitRsp)
	{
		XBYTE[REG_SD_TIMER]&=0xf7;	
	}
	else
	{
		XBYTE[REG_SD_TIMER]|=0x08;
	}
	XBYTE[REG_WAITRSPTIME]=0xff; 

	XBYTE[REG_SD_TRIGGER]|=C_bit_RxRsp;

	do
	{
		tc_FullFlag=(XBYTE[REG_SD_STATE0]&0x02);
	}while((tc_FullFlag==0)&&((XBYTE[REG_SD_STATE0]&0x40)==0)); 

   if((tc_FullFlag==0)&&((XBYTE[REG_SD_STATE0]&0x40)))
	{
		XBYTE[0xB450] = 0x03;//reset SD interface
		gc_ReadWriteTimeOut = 1;
		return 0x01;	
	}

	if (tc_RespType == C_48BitRsp)
	{
		//send 8 dummy clock
		SdTxDummy();    
		{
			U16 tw_TimeOut;
			tw_TimeOut = K_CARD_TIMEOUTSECONDS;
			while ((XBYTE[REG_SD_STATE1] & 0x0F) != 0x00)	//wait the card into idle 
			{
	
				tw_TimeOut --;
				
				if (gc_SysCardInsert)
	     		{//if CD pin is HIGH,the C 	 
			 		tw_TimeOut = 0;
	     		}
	
				if (!tw_TimeOut)
				{
					XBYTE[0xB450] = 0x03;//reset SD interface
					gc_ReadWriteTimeOut = 1;
					break; 
				} 
			
	  		}
	  	} 		
	}
	//先取出48bit数据
	tc_RespBuff[0] = XBYTE[REG_RESPBUF1];
	tc_RespBuff[1] = XBYTE[REG_RESPBUF2];
	tc_RespBuff[2] = XBYTE[REG_RESPBUF3];
	tc_RespBuff[3] = XBYTE[REG_RESPBUF4];
	tc_RespBuff[4] = XBYTE[REG_RESPBUF5];
	tc_RespBuff[5] = XBYTE[REG_RESPBUF6];
	
	tc_CRC7=tc_RespBuff[5];
	//如果为136bit数据回应,则取出剩余bit数据
	if(C_136BitRsp==tc_RespType)	//(tc_RespType)
	{
		for(tc_i=0;tc_i<11;tc_i++) 
		{
			//等待回应直到数据接收到或者为时间超
			do
			{
				tc_FullFlag=XBYTE[REG_SD_STATE0]&0x02;	            	
		
			}while((tc_FullFlag==0)&&((XBYTE[REG_SD_STATE0]&0x40)==0)); 

			//如果为数据空并且为超时状态,设置错误返回
			if((tc_FullFlag==0)&&(XBYTE[REG_SD_STATE0]&0x40))
			{
				gc_ReadWriteTimeOut = 1;	
				XBYTE[0xB450] = 0x03;//reset SD interface
		 		return 0x01;	
			}			
			tc_RespBuff[6+tc_i] = XBYTE[REG_RESPBUF6];		
		}
		tc_CRC7=tc_RespBuff[16];

	}
	//检查命令校验码是否相同
	//如果不需要CRC检验则跳过
	if((tc_CRC7!=XBYTE[REG_CRC7BUF])&&tc_CRC)
	{//CRC error
		XBYTE[0xB450] = 0x03;//reset SD interface
		gc_ReadWriteTimeOut = 1;
		return 0x01;		
	}
	if (tc_RespType == C_136BitRsp)
	{
		//send 8 dummy clock
		SdTxDummy();    
		//等待SD卡进入idle状态                           
		{
			U16 tw_TimeOut;
			tw_TimeOut = K_CARD_TIMEOUTSECONDS;
			while ((XBYTE[REG_SD_STATE1] & 0x0F) != 0x00)	//wait the card into idle 
			{
	
				tw_TimeOut --;
				
				if (gc_SysCardInsert)
	     		{//if CD pin is HIGH,the C 	 
			 		tw_TimeOut = 0;
	     		}
	
				if (!tw_TimeOut)
				{
					XBYTE[0xB450] = 0x03;//reset SD interface
					gc_ReadWriteTimeOut = 1;
					break; 
				} 
			
	  		}
	  	} 		
	}
	return 0;	
}


void CommandToSd(U8 *ComBuff)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -