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

📄 sdcmd.c

📁 LPC2210以SPI方式读写SD/MMC卡的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return SD_NO_ERR;    								 /* 返回执行成功 return perform sucessfully */		
}
#endif

		/*********************************************************
		
		    			下面为一些数据传输函数
		
		**********************************************************/

/********************************************************************************************************************
** 函数名称: INT8U SD_ReadRegister()				Name:	  INT8U SD_ReadRegister()
** 功能描述: 从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_ReadRegister(INT32U len, INT8U *recbuf)
{	
	INT32U i = 0;
	INT8U resp;

    SPI_CS_Assert();
    do{    											/* 等待数据起始令牌 wait for data start token */
        resp = SPI_RecByte();
    	i++;
    }while((resp == 0xFF) && (i < SD_READREG_TIMEOUT));    
    
    if (i >= SD_READREG_TIMEOUT)
    {
    	SPI_CS_Deassert();
    	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] = 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))
   	{												/* CRC校验错误 CRC check is error */
   		SPI_SendByte(0xFF);
   		SPI_CS_Deassert();		
  		return SD_ERR_DATA_CRC16;					/* 返回RCR16错误  return error of CRC16 */				
  	}    
#endif   
  
    SPI_SendByte(0xFF);								/* 返回之前发送8个clock  clock out 8 clk before return */
    SPI_CS_Deassert();	
    	
	return SD_NO_ERR;
}	

/*******************************************************************************************************************
** 函数名称: 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
*******************************************************************************************************************/
INT8U SD_ReadBlockData(INT32U len, INT8U *recbuf)
{
    INT8U tmp;
    INT32U i = 0,timeout;
    
#if SD_UCOSII_EN    
    timeout = SD_UCOSII_SMALLWAIT;						/* 很少的等待时间 small wait time */
#else
	timeout = sds.timeout_read;							/* 等待接收数据开始令牌最长时间 wait time that receive data start token */
#endif  
    
    SPI_CS_Assert();    
    do
    { 											    	/* 等待接收数据开始令牌0xFE  wait for receiving data start token 0xFE */
        tmp = SPI_RecByte();
        i++;
    }while((tmp == 0xFF) && (i < timeout));
	
#if SD_UCOSII_EN    
    if (i >= timeout)
   	{													/* 继续等待(挂起任务) continue to wait(suspend task) */
   		timeout = sds.timeout_read;
   		i = 0;
	    do
    	{
        	OSTimeDly(1);								/* 挂起该任务1 tick(suspend task 1 tick) */
        	tmp = SPI_RecByte();
       	 	i++;
   		}while((tmp == 0xFF) && (i < timeout));
	}
#endif

	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_WriteBlockData()				Name:	  INT8U SD_WriteBlockData()
** 功能描述: 向卡写数据块							Function: write block data to card
** 输   入: INT8U bmulti  : 是否为多块操作1:是0:否 Input:	  INT8U bmulti   : multi blocks operate 1:Y 0:N 
			 INT32U len    : 长度						  	  INT32U len     : length
			 INT8U *sendbuf: 发送缓冲区					 	  INT8U *sendbuf : the buffer of send
** 输   出: 0:   正确    >0:   错误码		  		Output:	  0:  right		>0:  error code
********************************************************************************************************************/
INT8U SD_WriteBlockData(INT8U bmulti, INT32U len, INT8U *sendbuf)
{
	INT16U i;
	INT8U 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)	
  	{		
   		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 */
 }

/*******************************************************************************************************************
** 函数名称: void SD_StopMultiToken()				Name:	  void SD_StopMultiToken(void)
** 功能描述: 发送多块写停止令牌						Function: send the token that stop multiple block write
** 输   入: 无									    Input:	  NULL
** 输   出: 无										Output:	  NULL
********************************************************************************************************************/
void SD_StopMultiToken(void)
{
	SPI_CS_Assert();
	
	SPI_SendByte(0xFF);								/* 先发送8个clock send 8 clock first */
	SPI_SendByte(SD_TOK_STOP_MULTI);				/* 发送停止数据传输令牌 send stop transmission token */
	SPI_RecByte();
	
    SPI_CS_Deassert();
}


/********************************************************************************************************************
** 函数名称: void SD_WaitBusy()						Name:	  void SD_WaitBusy()
** 功能描述: 查询SD卡是否处于忙状态					Function: poll SD Card wheather it is busy
** 输   入: INT32U waittype: 超时类型				Input:	  INT32U timeout: time out type
** 输   出: 0: 未超时  >0: 错误码					Output:	  0: not time out   > 0: error code
*********************************************************************************************************************/
INT8U SD_WaitBusy(INT8U waittype)
{
    INT32U timeout, i = 0;
    INT8U 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 */
    	
#if SD_UCOSII_EN
        timeout = SD_UCOSII_SMALLWAIT;				/* 很少的等待时间 small wait time */
#endif
   
	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 SD_UCOSII_EN
	if (i >= timeout)
	{												/* 很少等待后卡仍忙, after small wait, card is still busy */
  		if (waittype == SD_WAIT_WRITE)
  			timeout = sds.timeout_write;
  		else
  			timeout = sds.timeout_erase;   
			
		i = 0;
   		do
   		{ 	
   			OSTimeDly(1);							/* 操作系统挂起1 tick  OS suspend 1 tick */
       		tmp = SPI_RecByte();
       		i++;
    	}while ((tmp != 0xFF) && (i < timeout));	/* 忙时收到的值为0 always receive 0 when card is busy */    
	}
#endif	

	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;										/* 返回执行结果 */
}

/********************************************************************************************************************
** 函数名称: void SD_SPIDelay()						Name:	  void SD_SPIDelay()
** 功能描述: SPI总线延时							Function: SPI Bus delay 
** 输   入: INT8U value: 延时值,不超过255		    Input:	  INT8U value : delay value,do not beyond 255
** 输   出: 无										Output:	  NULL
*********************************************************************************************************************/
void SD_SPIDelay(INT8U value)
{
    INT8U i;

    for (i = 0; i < value; i++)
        SPI_SendByte(0xFF);						 	/* 发送0xFF clock out 0xFF */
}








⌨️ 快捷键说明

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