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

📄 sd.c

📁 SD卡驱动程序,用于ARM7单片机,完全能用
💻 C
📖 第 1 页 / 共 4 页
字号:
	fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2;				/* 读超时时间因数 read timeout factor */
	
	if(time_v == 0)	return SD_ERR_CARD_PARAM;							/* 卡参数有错误 card parameter is error */
	
	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)*/
	
	if (sds.card_type == CARDTYPE_SD)
	{
		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;
	}
	else
	{
		sds.timeout_read  = sds.timeout_read * 10 / 8;					/* 实际值为计算值的10倍 */
		sds.timeout_write = sds.timeout_write * 10 / 8;
	}
	
	sds.timeout_erase = sds.timeout_write;
	
	
	return SD_NO_ERR;	
}
/*******************************************************************************************************************
** 函数名称: INT8U SD_GetCardInfo()				Name:	  INT8U SD_GetCardInfo()
** 功能描述: 获得SD/MMC卡的信息					Function: get the information of SD/MMC card
** 输   入: INT8U cardtype: 卡类型				Input:    INT8U cardtype: card type	
** 输    出: 0:   成功    >0:  错误码			Output:	  0:  right			>0:  error code
*******************************************************************************************************************/
unsigned char SD_GetCardInfo(void)
{
	unsigned int tmp;
	unsigned char csdbuf[16],ret;

	ret = SD_ReadCSD(16, csdbuf);	 								    		/* 读CSD寄存器    read CSD register */
	if (ret != SD_NO_ERR)
	{	
//		Uart0_SendByte(0xa1); 
		return ret;	
	}
	
	SD_CalTimeout(csdbuf);	//计算读,写,擦时间
	
	/* 计算块的最大长度  */														/* calculate the size of a sector */
	sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK);  			/* (2 ^ READ_BL_LEN) */
	
	
//	Uart0_SendByte(SD_BLOCKSIZE_NBITS); 
//	Uart1_SendByte(sds.block_len>>24);
//	Uart1_SendByte(sds.block_len>>16);
//	Uart1_SendByte(sds.block_len>>8);
//	Uart1_SendByte(sds.block_len>>0); 
	
	//00 00 02 00    00 00 04 00
	/* 计算卡中块的个数 */														/* 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);	
	
//	Uart0_SendByte(sds.block_num>>24);
//	Uart0_SendByte(sds.block_num>>16);
///	Uart0_SendByte(sds.block_num>>8);
//	Uart0_SendByte(sds.block_num>>0);
//	00 07 8A 00    00 1E 4A 00
	
//	252,968,960    2,032,664,576
	MAXBlock_num = sds.block_num;
	/* 计算擦除的单位(单位: 块) */	
	if (sds.card_type == CARDTYPE_MMC)
	{					    
		tmp  = ((csdbuf[ERASE_GRP_SIZE_POS] & ERASE_GRP_SIZE_MSK) >> 2) + 1;  	/* (ERASE_GRP_SIZE + 1)  */ 
		
		/* (ERASE_GRP_SIZE + 1) * (ERASE_GRP_MULTI + 1) */
		tmp *= ((csdbuf[ERASE_GRP_MULTI_POS1] & ERASE_GRP_MULTI_MSK1) << 3) +
		       ((csdbuf[ERASE_GRP_MULTI_POS2] & ERASE_GRP_MULTI_MSK2) >> 5) + 1;	
	}
	else
	{																		/*calculate the size of sector */
		tmp = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +  			
	          ((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1;			/* SD: SECTOR_SIZE */
	}
	sds.erase_unit = tmp;
		    												/* 擦除单位(块) */
															
//	Uart0_SendByte(sds.erase_unit>>24);
//	Uart0_SendByte(sds.erase_unit>>16);
//	Uart0_SendByte(sds.erase_unit>>8);
//	Uart0_SendByte(sds.erase_unit>>0); 
//	00 00 00 20   00 00 00 20
	return SD_NO_ERR;
	
	
}



/********************************************************************************************************************
** 函数名称: INT8U SD_BlockCommand()				Name:	  INT8U SD_BlockCommand()
** 功能描述: 块命令									Function: command about block operation
** 输   入: INT8U cmd	     : 命令字				Input:	  INT8U cmd	      : command byte 
			 INT8U resptype  : 响应类型						  INT8U resptype  : response type
			 INT32U parameter: 块操作参数			 		  INT32U parameter: parameter of block operation
** 输   出: 0:   正确    >0:   错误码		  		Output:	  0:  right		>0:  error code
*********************************************************************************************************************/
unsigned char SD_BlockCommand(unsigned char cmd, unsigned char resptype, unsigned int parameter)
{
	unsigned char param[4],resp,ret;
	
	parameter <<= SD_BLOCKSIZE_NBITS;					 /* 调整地址:左移9位 adjust address: move 9 bits left */

	SD_PackParam(param, parameter);						 /* 将参数转化为字节形式 change the parameter to bytes form */	

	ret = SD_SendCmd(cmd, param, resptype, &resp);
	if (ret != SD_NO_ERR)
	{
	   	 return ret;							 		 /* 结束数据传输失败 stop transmission operation fail */
	}
	if (resp != 0)
	{
		 return SD_ERR_CMD_RESP;		 				 /* 响应错误 response is error */
	}	 
	return SD_NO_ERR;
}




/********************************************************************************************************************
** 函数名称: INT8U SD_ReadSingleBlock()				Name:	  INT8U SD_ReadSingleBlock()
** 功能描述: 读单块命令								Function: read single block command
** 输   入: INT32U blockaddr: 块地址				Input:	  INT32U blockaddr: block address
** 输   出: 0:   正确    >0:   错误码		  		Output:	  0:  right	>0:  error code
*********************************************************************************************************************/
unsigned char SD_ReadSingleBlock(unsigned int blockaddr)
{
	return (SD_BlockCommand(CMD17, CMD17_R, blockaddr)); /* 读单块命令 command that read single block */
}



/*******************************************************************************************************************
** 函数名称: INT8U SD_ReadBlockData()			Name:	  INT8U SD_ReadBlockData()
** 功能描述: 从卡中读取数据块					Function: read block data from card
** 输   入: INT32U len    : 长度				Input:	  INT32U len    : length
			 INT8U *recbuf : 接收缓冲区					  INT8U *recbuf : the buffer of receive
** 输   出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
*******************************************************************************************************************/
unsigned char SD_ReadBlockData(unsigned int len, unsigned char *recbuf)
{
	unsigned char tmp;
    unsigned int i = 0,timeout;
    
	timeout = sds.timeout_read;							/* 等待接收数据开始令牌最长时间 wait time that receive data start token */
	
	SPI_CS_Assert();    
    do
    { 											    	/* 等待接收数据开始令牌0xFE  wait for receiving data start token 0xFE */
        tmp = SPI_RecByte();
        i++;
    }while((tmp == 0xFF) && (i < timeout));
	


	if (i >= timeout)
	{
		SPI_CS_Deassert();
       	return SD_ERR_TIMEOUT_READ;						/* 返回读超时错误码  return error timeout error code of reading */
	}
	
	if (tmp != SD_TOK_READ_STARTBLOCK)					/* 块读开始令牌错误 read start block token is error */
	{
		SPI_SendByte(0xFF);
		SPI_CS_Deassert();
		return SD_ERR_DATA_START_TOK;
	}
	
	for (i = 0; i < len; i++)
	{
   		recbuf[i] = SPI_RecByte();						/* 接收数据 receive data */
	}
	
	i = SPI_RecByte();								
    i = (i << 8) + SPI_RecByte();    					/* 读取16位CRC get 16-bit CRC */	
	
	
#if SD_CRC_EN 
   	if (i != SD_GetCRC16(recbuf, len))
   	{	
   		SPI_SendByte(0xFF); 							/* CRC校验错误 CRC check is error */
   		SPI_CS_Deassert();		
  		return SD_ERR_DATA_CRC16;						/* 返回RCR16错误  return error of CRC16 */				
  	}    
#endif   

	SPI_SendByte(0xFF); 
	SPI_CS_Deassert();
	
	
  	return SD_NO_ERR;									/* 返回函数执行成功 return function perform sucessfully */

}



/****************************************************************************
** 函数名称: INT8U SD_WriteSingleBlock()			
** 功能描述: 写单块命令								
** 输   入: INT32U blockaddr: block address		
** 输   出: 0:   正确    >0:   错误码		  		
****************************************************************************/
unsigned char SD_WriteSingleBlock(unsigned int blockaddr)
{
	return (SD_BlockCommand(CMD24, CMD24_R, blockaddr)); /* 写单块命令 command that write single block */
}



/**************************************************************************
** 函数名称: SD_WaitBusy()						
** 功能描述: 查询SD卡是否处于忙状态					
** 输   入: INT32U waittype: 超时类型				
** 输   出: 0: 未超时  >0: 错误码					
***************************************************************************/
unsigned char SD_WaitBusy(unsigned char waittype)
{
	unsigned int timeout, i = 0;
	unsigned char tmp;
	if (waittype == SD_WAIT_WRITE)
	{
  		timeout = sds.timeout_write;				/* 等待类型为写操作 wait type is write operation */
  	}
	else
	{
  		timeout = sds.timeout_erase;   				/* 等待类型为擦除操作 wait type is erase operation */
	}
	
	
	SPI_CS_Assert();
   	do
   	{ 												/* 等待忙结束 wait for being busy end */
        tmp = SPI_RecByte();
        i++;
    }while ((tmp != 0xFF) && (i < timeout));		/* 忙时收到的值为0 always receive 0 when card is busy */    



	if(i < timeout) 
	{
		tmp = SD_NO_ERR;							/* 返回0,表示没超时 return 0 indicate that operation is not time out */
	}
	else
	{ 
		tmp = SD_ERR_TIMEOUT_WAIT;					/* 返回错误码,表示超时 return error code indicate that operation is time out */
	}
	
	SPI_SendByte(0xFF);
	SPI_CS_Deassert();								
	return tmp;										/* 返回执行结果 */	
}



/****************************************************************************
** 函数名称: INT8U SD_ReadBlock()					
** 功能描述: 从SD/MMC卡中读一个块					
** 输   入: INT32U blockaddr: 块地址				
			 INT8U *recbuf   : 接收缓冲区,长度512Bytes	 	  
** 输    出: 0:   成功    >0:  错误码				
******************************************************************************/
unsigned char SD_ReadBlock(unsigned int blockaddr, unsigned char *recbuf)
{
	unsigned char ret;
	if (SD_INSERT_STATUS())							
    {
    	return SD_ERR_NO_CARD;   					/* 卡没完全插入卡中 card is not inserted entirely */
	}
	
	if (blockaddr >= (sds.block_num*(sds.block_len/SD_BLOCKSIZE)))	
	{
		return SD_ERR_OVER_CARDRANGE;				/* 操作超出卡容量范围 operate over the card range */
	}
	
	ret = SD_ReadSingleBlock(blockaddr);			/* 读单块命令 read single blocks command */						
 	if (ret != SD_NO_ERR)
 	{								
 		return ret;
 	}
	
	ret = SD_ReadBlockData(SD_BLOCKSIZE, recbuf);	/* 读出数据 read data from sd card */	
	
	return ret;
}


#include "../Uart1/Uart1.h"
/***************************************************************************
** 函数名称: INT8U SD_WriteBlockData()				
** 功能描述: 向卡写数据块							
** 输   入: INT8U bmulti  : 是否为多块操作1:是0:否 
			 INT32U len    : 长度						  	  
			 INT8U *sendbuf: 发送缓冲区					 	  
** 输   出: 0:   正确    >0:   错误码		  		
**************************************************************************/
unsigned char SD_WriteBlockData(unsigned char bmulti, unsigned int len, unsigned char *sendbuf)
{
	unsigned short i;
	unsigned char tmp;
	SPI_CS_Assert();
		
    SPI_SendByte(0xFF);								/* 开始发送数据之前发送8个clock clock out 8 clk before start */
	
	if (bmulti == 1)
	{
        SPI_SendByte(SD_TOK_WRITE_STARTBLOCK_M);	/* 写多块开始令牌 start token of write multi blocks */
	}
	else
	{
		SPI_SendByte(SD_TOK_WRITE_STARTBLOCK);		/* 写单块开始令牌 start token of write single block */
	}
	
	for (i = 0; i < len; i++)
	{
        SPI_SendByte(sendbuf[i]);					/* 发送数据 send data */
	}
	
#if SD_CRC_EN	
	i = SD_GetCRC16(sendbuf,len);					/* 计算CRC16 calculate CRC16 */
#endif

	SPI_SendByte((i >> 8) & 0xFF);
	SPI_SendByte(i & 0xFF); 						/* 发送CRC16校验码 send CRC16 check code */
	
	tmp = SPI_RecByte();
	
  	if ((tmp & SD_RESP_DATA_MSK) != SD_RESP_DATA_ACCETPTED)	
  	{	
	//	Uart1_SendByte(tmp); 	
   		SPI_SendByte(0xFF);							/* 返回之前发送8个clock  clock out 8 clk before return */
   		SPI_CS_Deassert();
   		return SD_ERR_DATA_RESP;					/* 数据响应错误 data response error */
    }
	
	SPI_CS_Deassert();
     		
    if (SD_WaitBusy(SD_WAIT_WRITE) != SD_NO_ERR)
	{			
    	return SD_ERR_TIMEOUT_WRITE;				/* 写入超时 write time out */
	}
	else
	{
    	return SD_NO_ERR; 							/* 写入正确 write right */
	}
	
}



/************************************************************************
** 函数名称: INT8U SD_ReadCard_Status()				
** 功能描述: 读SD/MMC卡的 Card Status 寄存器		
** 输   入: INT8U len: 	 寄存器长度(固定为2)			  
			 INT8U *recbuf : 接收缓冲区					      
** 输   出: 0:   正确    >0:   错误码		  		
*************************************************************************/
unsigned char SD_ReadCard_Status(unsigned int len, unsigned char *buffer)
{
    unsigned char param[4] = {0,0,0,0};

    return (SD_SendCmd(CMD13, param, CMD13_R, buffer)); /* 读 Card Status 寄存器 */
    									 	 			/* read register of Card Status */
}




/************************************************************************
** 函数名称: EfficacyData()				
** 功能描述: SD卡数据效验		
** 输   入: blockaddr: 	 块地址			  
			 Data 数据指针					      
** 输   出: 0:   正确    >0:   错误码		  		
*************************************************************************/
unsigned char EfficacyData(unsigned int blockaddr, unsigned char *sendbuf)
{
	unsigned int i,j;
	unsigned char c1,c2;
	unsigned char tmp;
	c1 = 0 ;
	for( i = 0 ; i < SD_BLOCKSIZE ; i++ )
	{
		c1 +=  sendbuf[i];		
	}
	
	
	for( j = 0 ; j < 10 ; j++ )
	{
		tmp = SD_ReadBlock(blockaddr,sendbuf);
		if(tmp == SD_NO_ERR)
		{
			break;
		}
	}
	
	
	if(j>=10)
	{
		return SD_READ_ERR;
	}
	
	
	c2 = 0 ;
	for( i = 0 ; i < SD_BLOCKSIZE ; i++ )
	{
		c2 +=  sendbuf[i];		
	}
	
	if(c1==c2)
	{
		return SD_NO_ERR;
	}
	else
	{
		return SD_Efficacy_ERR;	
	}
	
}
/****************************************************************************
** 函数名称: INT8U SD_WriteBlock()					
** 功能描述: 向SD/MMC卡中写入一个块					

⌨️ 快捷键说明

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