www.pudn.com > SDdriver.rar > sddriver.c


/******************************************************************************************************* 
** Descriptions:		sd 卡驱动软件包: SD卡物理层 用户API函数 
********************************************************************************************************/ 
#include    "define.h" 
 
 
/* SD卡信息结构体变量 the information structure variable of SD Card */ 
sd_struct sds;			 
 
/* 超时时间单位表(单位:0.000000001ns) timeout unit table */ 
const uint32 time_unit[8] = {1000000000,100000000,10000000, 
							 1000000,100000,10000,1000,100}; 
 
/* 超时时间表 timeout value table */							  
const uint8 time_value[16] = { 0,10,12,13,15,20,25,30, 
                              35,40,45,50,55,60,70,80}; 
  
/* 超时时间因数表 timeout factor table */                               
const uint8 r2w_fator[6] = {1,2,4,8,16,32};                            
     
/******************************************************************************************** 
		 
用户API函数:  初始化,读,写,擦 SD卡  User API Function: Initialize,read,write,erase SD Card  
				 
********************************************************************************************/ 
 
				 
/******************************************************************************************************************* 
** 函数名称: INT8U SD_Initialize()				Name:	  INT8U SD_Initialize() 
** 功能描述: 初始化SD卡							Function: initialize sd card 
** 输   入: 无									Input:	  NULL 
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code 
********************************************************************************************************************/ 
uint8 SD_Initialize(void) 
{ 
	uint8 recbuf[4],ret; 
     
    SD_HardWareInit();					    		/* 初始化读写SD卡的硬件条件 Initialize the hardware that access SD Card */ 
 
    SPI_CS_Assert();								/* 1. 置CS为低 assert CS */   
	SD_SPIDelay(30);								/* 2. 至少延时 74 clock delay more than 74 clock */ 
    SPI_CS_Deassert();								/* 3. 置CS为高 dessert CS */ 
    SD_SPIDelay(3);									/* 4. 延时2(8 clock) delay 2(8 clock) */ 
     
    ret = SD_ResetSD();								/* 5. 发出CMDO命令复位SD卡 send CMD0 command to reset sd card */ 
    if (ret != SD_NO_ERR) 
        return ret;									 
 	 
 	ret = SD_ActiveInit();							/* 6. 激活卡进入初始化过程. active card initialize process */ 
 	if (ret != SD_NO_ERR) 
 		return ret; 
         
   	ret = SD_ReadOCR(4, recbuf);  					/* 7. 读OCR寄存器,查询卡支持的电压值 read OCR register,get the supported voltage */ 
    if (ret != SD_NO_ERR) 
        return ret; 
     
    if ((recbuf[1] & MSK_OCR_33) != MSK_OCR_33) 
        return SD_ERR_VOL_NOTSUSP;					/* 不支持3.3V,返回错误码  not support 3.3V,return error code */ 
     
    SPI_ClkToMax();									/* 8. 设置SPI时钟到最大值 set SPI clock to maximum */ 
         
#if SD_CRC_EN         
    ret = SD_EnableCRC(1);							/* 使能CRC校验 enable CRC check */ 
	if (ret != SD_NO_ERR)   
	  	return ret; 
#endif 
 
    ret = SD_SetBlockLen(SD_BLOCKSIZE);				/* 9. 设置块的长度: 512Bytes Set the block length: 512Bytes */ 
    if (ret != SD_NO_ERR)   
        return ret; 
         
	return (SD_GetCardInfo());						/* 10. 读CSD寄存器,获取SD卡信息 read CSD register, get the information of SD card */ 
} 
 
/******************************************************************************************************************* 
** 函数名称: INT8U SD_GetCardInfo()				Name:	  INT8U SD_GetCardInfo() 
** 功能描述: 获得SD卡的信息						Function: get the information of SD card 
** 输   入: INT8U cardtype: 卡类型				Input:    INT8U cardtype: card type	 
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code 
*******************************************************************************************************************/ 
uint8 SD_GetCardInfo() 
{ 
	uint32 tmp; 
	uint8 csdbuf[16],ret; 
		 
	ret = SD_ReadCSD(16,csdbuf);	 								    		/* 读CSD寄存器    read CSD register */ 
	if (ret != SD_NO_ERR)	 
		return ret;	 
		 
	SD_CalTimeout(csdbuf);														/* 计算超时时间值 calculate timeout value */ 
		 
	/* 计算块的最大长度  */														/* calculate the size of a sector */ 
	sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK);  			/* (2 ^ READ_BL_LEN) */ 
	 
	/* 计算卡中块的个数 */														/* calculate the sector numbers of the SD Card */ 
	sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) + 
	      			 (csdbuf[C_SIZE_POS2] << 2) + 
	 	 			((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1;				/* (C_SIZE + 1)*/ 
		 	  															 
	tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +    
	      ((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2;				/* (C_SIZE_MULT + 2) */ 
    	 
    /* 获得卡中块的数量 */														/* get the block numbers in card */ 
	sds.block_num = sds.block_num * (1 << tmp);									/* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */ 
																			 
	/* 计算扇区大小 */															/*calculate the size of sector */ 
	sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +  			 
	                 ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1; /* SD (SECTOR_SIZE + 1) */ 
	    			 
	return SD_NO_ERR;															/* 返回执行成功 return perform sucessfully */ 
} 
 
 
/******************************************************************************************************************* 
** 函数名称: INT8U SD_CalTimeout()				Name:	  INT8U SD_CalTimeout() 
** 功能描述: 计算读/写/擦超时时间				Function: get the information of SD card 
** 输   入: INT8U cardtype: 卡类型				Input:    INT8U cardtype: card type	 
			 INT8U *csdbuf : CSD寄存器内容		 	      INT8U *csdbuf : CSD register content 
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code 
*******************************************************************************************************************/ 
void SD_CalTimeout(uint8 *csdbuf) 
{ 
	uint32 tmp; 
	uint8 time_u,time_v,fator; 
	 
	sds.timeout_read = READ_TIMEOUT_100MS;								/* 默认读超时为100ms */ 
	sds.timeout_write = WRITE_TIMEOUT_250MS;							/* 默认写超时为250ms */ 
	sds.timeout_erase = WRITE_TIMEOUT_250MS; 
		 
	time_u = (csdbuf[TAAC_POS] & TAAC_MSK);								/* 读超时时间单位 read timeout unit */ 
	time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3;						/* 读超时时间值   read timeout value */ 
	fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2;				/* 写超时时间因数 write timeout factor */ 
	 
	if(time_v == 0)	return; 
	if(fator >= 6) return; 
	 
	tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u];		/* TACC * f (单位 unit: clock) */ 
	tmp = tmp + csdbuf[NSAC_POS] * 100;									/* TACC * f + NSAC * 100 (单位 unit: clock) */ 
	 
	/* 计算得到的超时值 the timeout value of being calculated */ 
	sds.timeout_read = tmp; 
	sds.timeout_write = tmp * r2w_fator[fator];							/* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/ 
	 
	sds.timeout_read  = sds.timeout_read * 100 / 8;						/* 实际值为计算值的100倍 */ 
	sds.timeout_write = sds.timeout_write * 100 / 8; 
	 
	if (sds.timeout_read > READ_TIMEOUT_100MS)							/* 取计算值与默认值中的最小值 */ 
		sds.timeout_read = READ_TIMEOUT_100MS; 
	 
	if (sds.timeout_write > WRITE_TIMEOUT_250MS) 
		sds.timeout_write = WRITE_TIMEOUT_250MS; 
 
	sds.timeout_erase = sds.timeout_write; 
} 
/******************************************************************************************************************* 
** 函数名称: INT8U SD_CalTimeout()				Name:	  INT8U SD_CalTimeout() 
** 功能描述: 计算读/写/擦超时时间				Function: get the information of SD card 
** 输   入: INT8U *cardtype: 卡类型接收缓冲 	Input:    INT8U *cardtype: card type receive buff 
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code 
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。 
		     当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的, 
		     最大次数为宏定义SD_IDLE_WAIT_MAX. 
*******************************************************************************************************************/ 
uint8 SD_ActiveInit(void) 
{ 
	uint8 param[4] = {0,0,0,0},resp[5],ret; 
	uint32 i = 0; 
 
 	do  
    {													/* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */ 
        ret = SD_SendCmd(CMD1, param, CMD1_R, resp); 
        if (ret != SD_NO_ERR) 
       		return ret; 
   
        i++; 
    } 
	while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i < SD_IDLE_WAIT_MAX)); 
														/* 如果响应R1的最低位Idle位为1,则继续循环 */ 
														 
    if (i >= SD_IDLE_WAIT_MAX) 
        return SD_ERR_TIMEOUT_WAITIDLE;					/* 超时,返回错误 time out,return error */ 
 
	return SD_NO_ERR; 
}