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

📄 sdspihal.c

📁 周立功开发板smartArm2300的sd示例程序。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**                               Guangzhou ZLG-MCU Development Co.,LTD.
**                                      graduate school
**                                 http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name:			sdhal.c
** Last modified Date:	2007-5-20
** Last Version:		V2.0
** Descriptions:		SD/MMC卡读写模块: 硬件抽象层 ---- SD总线硬件相关的操作函数
**
**
**------------------------------------------------------------------------------------------------------
** Created by:			Ming Yuan Zheng
** Created date:		2005-1-6
** Version:				V1.0
** Descriptions:		The original version
**
**------------------------------------------------------------------------------------------------------
** Modified by:			
** Modified date:		
** Version:				
** Descriptions:		
**
**------------------------------------------------------------------------------------------------------
** Modified by: 
** Modified date:
** Version:	
** Descriptions: 
**
********************************************************************************************************/


#include "sdconfig.h"

#if (!SDBUS_MODE_EN)

/********************************************************************************************************************
** 函数名称: INT8U SdHal_SendCmd()					Name:	  INT8U SdHal_SendCmd()
** 功能描述: 向卡发送命令,并取得响应				Function: send command to the card,and get a response
** 输   入: INT8U cmd	    : 命令字				Input:	  INT8U cmd	    : command byte	
			 INT8U *param	: 命令参数,长度为4字节			  INT8U *param	: command parameter,length is 4 bytes  
			 INT8U resptype : 响应类型						  INT8U resptype: response type
			 INT8U *resp	: 响应,长度为1-5字节			  INT8U *resp	: response,length is 1-5 bytes
** 输   出: 0:   正确    >0:   错误码		  		Output:	  0:  right		>0:  error code
********************************************************************************************************************/
INT8U SdHal_SendCmd(sd_struct *sds, INT8U cmd, INT8U *param, INT8U resptype, INT8U *resp)
{
	INT32 i,rlen;
	INT8U tmp;
    
	SdHal_SPI_CSAssert(sds);
   
    SdHal_SPISendByte(sds, (cmd & 0x3F) | 0x40);	 /* 发送命令头和命令字 send command header and word */
    
    for (i = 3; i >= 0; i--)
        SdHal_SPISendByte(sds, param[i]);			 /* 发送参数 send parameters */

#if SD_CRC_EN
	tmp = SD_GetCmdByte6((cmd & 0x3F) | 0x40, param);
	SdHal_SPISendByte(sds, tmp);
#else
    SdHal_SPISendByte(sds, 0x95);					 /* CRC校验码,只用于第1个命令 CRC,only used for the first command */
#endif 
    
    rlen = 0;
    switch (resptype)								 /* 根据不同的命令,得到不同的响应长度 */
    {												 /* according various command,get the various response length */
  		case R1:
   	 	case R1B: rlen = 1;  break;
       		 
    	case R2:  rlen = 2;	 break;
       		 
   		case R3:  rlen = 5;	 break;
       		 
    	default:  SdHal_SPISendByte(sds, 0xFF);	
      		      SdHal_SPI_CSDeassert(sds);						 
        	      return SD_ERR_CMD_RESPTYPE;		 /* 返回命令响应类型错误 return error of command response type */
    		      break;
    }
    
    i = 0;				
    do 												 /* 等待响应,响应的开始位为0 */
    {												 /* Wait for a response,a response is a start bit(zero) */ 
        tmp = SdHal_SPIRecByte(sds);
        i++;
    }while (((tmp & 0x80) != 0) && (i < SD_CMD_TIMEOUT));
    
    if (i >= SD_CMD_TIMEOUT)
    {												 
        SdHal_SPI_CSDeassert(sds);
        return SD_ERR_CMD_TIMEOUT;					 /* 返回命令超时 return response timeout of command */
    }
    
    for (i = rlen - 1; i >= 0; i--)
    {
        resp[i] = tmp;
        tmp = SdHal_SPIRecByte(sds);				 /* 循环的最后发送8clock  at the last recycle,clock out 8 clock */
    }
      
    SdHal_SPI_CSDeassert(sds);
    return SD_NO_ERR;								 /* 返回执行成功 return perform sucessfully */
}


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

/********************************************************************************************************************
** 函数名称: 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 SdHal_ReadRegister(sd_struct *sds, INT32U len, INT8U *recbuf)
{	
	INT32U i = 0;
	INT8U resp;

    SdHal_SPI_CSAssert(sds);
    do{    											/* 等待数据起始令牌 wait for data start token */
        resp = SdHal_SPIRecByte(sds);
    	i++;
    }while((resp == 0xFF) && (i < SD_READREG_TIMEOUT));    
    
    if (i >= SD_READREG_TIMEOUT)
    {
    	SdHal_SPI_CSDeassert(sds);
    	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] = SdHal_SPIRecByte(sds);			/* 接收数据 receive data */
   		
    i = SdHal_SPIRecByte(sds);								
    i = (i << 8) + SdHal_SPIRecByte(sds);   		/* 读取16位CRC get 16-bit CRC */	

#if SD_CRC_EN 
   	if (i != SD_GetCRC16(recbuf, len))
   	{												/* CRC校验错误 CRC check is error */
   		SdHal_SPISendByte(sds, 0xFF);
   		SdHal_SPI_CSDeassert(sds);		
  		return SD_ERR_DATA_CRC16;					/* 返回RCR16错误  return error of CRC16 */				
  	}    
#endif   
  
    SdHal_SPISendByte(sds, 0xFF);					/* 返回之前发送8个clock  clock out 8 clk before return */
    SdHal_SPI_CSDeassert(sds);	
    	
	return SD_NO_ERR;
}	


#define  SD_UCOSII_SMALLWAIT  256

/*******************************************************************************************************************
** 函数名称: 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 SdHal_ReadBlockData(sd_struct *sds, 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  
    
    SdHal_SPI_CSAssert(sds);    
    do
    { 											    	/* 等待接收数据开始令牌0xFE  wait for receiving data start token 0xFE */
        tmp = SdHal_SPIRecByte(sds);
        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 = SdHal_SPIRecByte(sds);
       	 	i++;
   		}while((tmp == 0xFF) && (i < timeout));
	}
#endif

	if (i >= timeout)
	{
		SdHal_SPI_CSDeassert(sds);
       	return SD_ERR_TIMEOUT_READ;						/* 返回读超时错误码  return error timeout error code of reading */
	}
	
	if (tmp != SD_TOK_READ_STARTBLOCK)					/* 块读开始令牌错误 read start block token is error */
	{
		SdHal_SPISendByte(sds, 0xFF);
		SdHal_SPI_CSDeassert(sds);
		return SD_ERR_DATA_START_TOK;
	}
	
	for (i = 0; i < len; i++)
   		recbuf[i] = SdHal_SPIRecByte(sds);				/* 接收数据 receive data */
   		
    i = SdHal_SPIRecByte(sds);							
    i = (i << 8) + SdHal_SPIRecByte(sds);    			/* 读取16位CRC get 16-bit CRC */	

#if SD_CRC_EN 
   	if (i != SD_GetCRC16(recbuf, len))
   	{	
   		SdHal_SPISendByte(sds, 0xFF); 					/* CRC校验错误 CRC check is error */
   		SdHal_SPI_CSDeassert(sds);		
  		return SD_ERR_DATA_CRC16;						/* 返回RCR16错误  return error of CRC16 */				
  	}    
#endif   

	SdHal_SPISendByte(sds, 0xFF); 
	SdHal_SPI_CSDeassert(sds);

  	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 SdHal_WriteBlockData(sd_struct *sds, INT8U bmulti, INT32U len, INT8U *sendbuf)
{
	INT16U i;
	INT8U tmp;

	SdHal_SPI_CSAssert(sds);
		
    SdHal_SPISendByte(sds, 0xFF);							/* 开始发送数据之前发送8个clock clock out 8 clk before start */
    
    if (bmulti == 1)
        SdHal_SPISendByte(sds, SD_TOK_WRITE_STARTBLOCK_M);	/* 写多块开始令牌 start token of write multi blocks */
	else
		SdHal_SPISendByte(sds, SD_TOK_WRITE_STARTBLOCK);	/* 写单块开始令牌 start token of write single block */

	for (i = 0; i < len; i++)
        SdHal_SPISendByte(sds, sendbuf[i]);					/* 发送数据 send data */

#if SD_CRC_EN	
	i = SD_GetCRC16(sendbuf,len);							/* 计算CRC16 calculate CRC16 */
#endif

	SdHal_SPISendByte(sds, (i >> 8) & 0xFF);
	SdHal_SPISendByte(sds, i & 0xFF); 						/* 发送CRC16校验码 send CRC16 check code */
			    
	tmp = SdHal_SPIRecByte(sds);
  	if ((tmp & SD_RESP_DATA_MSK) != SD_RESP_DATA_ACCETPTED)	
  	{		
   		SdHal_SPISendByte(sds, 0xFF);						/* 返回之前发送8个clock  clock out 8 clk before return */
   		SdHal_SPI_CSDeassert(sds);
   		return SD_ERR_DATA_RESP;							/* 数据响应错误 data response error */
    }
        
    SdHal_SPI_CSDeassert(sds);
     		
    if (SdHal_WaitBusy(sds, SD_WAIT_WRITE) != SD_NO_ERR)			

⌨️ 快捷键说明

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