sdcard.c

来自「ARM7 lpc2132+vs1003+sdcard 制作的 MP3 此程序在」· C语言 代码 · 共 1,442 行 · 第 1/5 页

C
1,442
字号
	while (((tmp & 0x80) != 0) && (i < SD_CMD_TIMEOUT));

    if (i >= SD_CMD_TIMEOUT)
    {												 
        SPI1_CS_SET();
        return SD_ERR_CMD_TIMEOUT;					 /* 返回命令超时 return response timeout of command */
    }
    
    for (i = rlen - 1; i >= 0; i--)
    {
        resp[i] = tmp;
        tmp = SPI1_SrByte(0XFF);					 /* 循环的最后发送8clock  at the last recycle,clock out 8 clock */
    }
      
    SPI1_CS_SET();
	
    return (SD_NO_ERR);								 /* 返回执行成功 return perform sucessfully */
}	
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadReg()				Name:	INT8U SD_ReadReg()
** 功能描述: 从SD卡读取数据							Function: read data from SD card
** 输     入 : INT32U len	  : 长度				Input:	  INT32U len   : length
				INT8U *recbuf: 接收缓冲区					  INT8U *recbuf: receive buffer
** 输     出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
*********************************************************************************************************************/
INT8U SD_ReadReg(INT32U len, INT8U *recbuf)
{	
	INT32U i = 0;
	INT8U resp;

    SPI1_CS_CLR();
	
    do
	{    												/* 等待数据起始令牌 wait for data start token */
        resp = SPI1_SrByte(0XFF);
    	i++;
    }
	while((resp == 0xFF) && (i < SD_READREG_TIMEOUT));    

	
    if (i >= SD_READREG_TIMEOUT)
    {
    	SPI1_CS_SET();
    	return (SD_ERR_TIMEOUT_READ);					/* 超时, 返回错误 timeout, return error */
  	}
  	
   	if (resp != SD_TOK_READ_STARTBLOCK)				
   	{													/* 不是收到数据起始令牌 not receive data start token */
		recbuf[0] = resp;							
		i = 1;											/* 还有len - 1个字节要接收 still len - 1 bytes will be received */
   	}
   	else
   	{
   		i = 0;											/* 收到数据起始令牌,还有len个字节要接收 received data start token,still len bytes will be received */
   	}
	
    for (; i < len; i++)
    {
		recbuf[i] = SPI1_SrByte(0XFF);					/* 接收数据 receive data */
    }	
    i = SPI1_SrByte(0XFF);								
    i = (i << 8) + SPI1_SrByte(0XFF);    				/* 读取16位CRC get 16-bit CRC */	

	#if SD_CRC_EN 
   		if (i != SD_GetCRC16(recbuf, len))
   		{												/* CRC校验错误 CRC check is error */
   			SPI1_CS_SET();
   			SPI1_SrByte(0xFF);    						
  			return SD_ERR_DATA_CRC16;					/* 返回RCR16错误  return error of CRC16 */				
  		}    
	#endif   
  
    SPI1_SrByte(0xFF);									/* 返回之前发送8个clock  clock out 8 clk before return */
    SPI1_CS_SET();	
    	
	return (SD_NO_ERR);
}	
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadCSD()								Name:	  INT8U SD_ReadCSD()
** 功能描述: 读SD卡的CSD寄存器								Function: read CSD register of sd card 
** 输     入 : INT8U csdlen  : 寄存器长度(固定为16)		INT8U csdlen  : len of register (fixed,is 16)
			    INT8U *recbuf : 接收缓冲区					INT8U *recbuf : recbuffer	
** 输     出: 0:   正确    >0:   错误码		  			Output:	  0:  right		>0:  error code
*********************************************************************************************************************/
INT8U SD_ReadCSD(INT8U csdlen, INT8U *recbuf)
{
    INT8U param[4] = {0,0,0,0};
	INT8U resp;
	INT8U ret;
  
    ret = SD_SendCmd(CMD9, param, CMD9_R, &resp);		/* 读CSD寄存器命令 command that read CSD register */
    if (ret != SD_NO_ERR) 									
	{
		return ret;									
    }
    if (resp != 0)
    {
		return SD_ERR_CMD_RESP;							/* 响应错误 response is error */
    }
	return (SD_ReadReg(csdlen, recbuf));
}
/*******************************************************************************************************************
** 函数名称: 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(INT8U *csdbuf)
{
	INT32U tmp;
	INT8U 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 = SPI1_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卡就完全进入SPI1模式了。当然重复发送命令CMD1是有次数限制的,
		     最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
INT8U SD_ActiveInit(void)
{
	INT8U param[4] = {0,0,0,0};
	INT8U resp[5];
	INT8U ret;
	INT32U 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);
}
/*******************************************************************************************************************
** 函数名称: INT16U SD_GetZLGSDVer()			Name:	  INT16U SD_GetZLGSDVer()
** 功能描述: 得到SD的版本号					Function: get the version of ZLG/SD
** 输   入: 无									Input:    NULL
** 输   出: 版本号								Output:	  Version
*******************************************************************************************************************/
INT16U SD_GetSDVer(void)
{
	return 0x0100;								/* 版本号为 1.00 */
}
/********************************************************************************************************************
** 函数名称: void SD_PackParam()					Name:	  void SD_PackParam()
** 功能描述: 将32位的参数转为字节形式				Function: change 32bit parameter to bytes form 
** 输     入: INT8U *parameter: 字节参数缓冲区		Input:	  INT8U *parameter: the buffer of bytes parameter
			   INT32U value    : 32位参数					  INT32U value    : 32bit parameter
** 输     出: 无									Output:	  NULL
*********************************************************************************************************************/
void SD_PackParam(INT8U *parameter, INT32U value)
{
    parameter[3] = (INT8U)(value >> 24);
    parameter[2] = (INT8U)(value >> 16);
    parameter[1] = (INT8U)(value >> 8);
    parameter[0] = (INT8U)(value);
}
/********************************************************************************************************************
** 函数名称: 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
*********************************************************************************************************************/
INT8U SD_BlockCommand(INT8U cmd, INT8U resptype, INT32U parameter)
{
	INT8U param[4];
	INT8U resp;
	INT8U 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_ResetSD()						Name:	  INT8U SD_ResetSD()
** 功能描述: 复位SD卡								Function: reset sd card
** 输      入: 无									Input:	  NULL
** 输      出: 0:   正确    >0:   错误码		  	Output:	  0:  right		>0:  error code
*********************************************************************************************************************/
INT8U SD_ResetSD(void)
{
	INT8U param[4] = {0,0,0,0},resp;
	
    return (SD_SendCmd(CMD0, param, CMD0_R, &resp));	/* 复位命令 command that reset 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
*******************************************************************************************************************/
INT8U SD_GetCardInfo(void)
{
	INT32U tmp;
	INT8U 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 */

⌨️ 快捷键说明

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