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

📄 sd_cmd.c

📁 Atmega64单片机程序(完整工程)
💻 C
📖 第 1 页 / 共 2 页
字号:

/*******************************************************************************
** 函数名称: INT8U SD_EnableCRC()					
** 功能描述: 使能SD卡的CRC校验功能					
** 输   入: INT8U bEnable : 1:使能 0:禁止			
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
#if SD_CRC_EN 
INT8U SD_EnableCRC(INT8U bEnable)
{
    INT8U param[4],resp,ret ;
    
    if(bEnable==1)
        param[0]=1 ;/* 使能crc enable crc */
    else 
        param[1]=0 ;/* 禁止crc disalbe crc */
    
    ret=SD_SendCmd(CMD59,param,CMD59_R,&resp);
    /* "使能/禁止CRC"命令 enable/disable crc command */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;/* 响应错误 response is error */
    
    return SD_NO_ERR ; 
}
#endif 

/*******************************************************************************
** 函数名称: INT8U SD_Read_SD_Status()				    
** 功能描述: 读SD卡的 SD_Status 寄存器				     
** 输   入: INT8U sdslen: 寄存器长度(固定为64)	
	     INT8U *recbuf : 接收缓冲区				
** 输   出: 0:   正确    >0:   错误码		  			
*******************************************************************************/
#if SD_ReadSD_Status_EN 
INT8U SD_ReadSD_Status(INT8U sdslen,INT8U *recbuf)
{
    INT8U param[4]={0,0,0,0},resp[2],ret ;
    
    ret=SD_SendCmd(CMD55,param,CMD55_R,resp);
    /* 后续命令为一个应用命令 */
    if(ret!=SD_NO_ERR)
        return ret ;
    /* command that the followed commnad is a specific application */
    
    if(resp[0]!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    ret=SD_SendCmd(ACMD13,param,ACMD13_R,resp);
    /* 读 SD_Status 命令 */
    if(ret!=SD_NO_ERR)
        return ret ;
    /* command that read SD_Status register */
    
    if((resp[0]!=0)||(resp[1]!=0))
        return SD_ERR_CMD_RESP ;/* 响应错误 response is error */
    
    return(SD_ReadBlockData(sdslen,recbuf));
    /* 读出寄存器内容 read the content of the register */
}
#endif 

/*******************************************************************************
** 函数名称: INT8U SD_ReadSCR()							
** 功能描述: 读SD卡的 SCR 寄存器						
** 输   入: INT8U scrlen  		: 寄存器长度(固定为8) 	
	     INT8U *recbuf 		: 接收缓冲区					
** 输   出: 0:   正确    >0:   错误码		  			
*******************************************************************************/
#if SD_ReadSCR_EN 
INT8U SD_ReadSCR(INT8U scrlen,INT8U *recbuf)
{
    INT8U param[4]={0,0,0,0},resp,ret ;
    
    ret=SD_SendCmd(CMD55,param,CMD55_R,&resp);
    /* 后续命令为一个应用命令 */
    /* command that the followed commnad is a specific application */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    ret=SD_SendCmd(ACMD51,param,ACMD51_R,&resp);
    /* 发送读 SD_Status 命令*/
    /* command that read SD_Status register */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    return(SD_ReadBlockData(scrlen,recbuf));
    /* 读出寄存器内容 read the content of the register */
}
#endif 

/*******************************************************************************
** 函数名称: INT8U SD_GetNumWRBlcoks()				
** 功能描述: 得到正确写入的块数						
** 输   入: INT32U *blocknum: 返回的块数			
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
#if SD_WriteMultiBlock_EN 
INT8U SD_GetNumWRBlcoks(INT32U *blocknum)
{
    INT8U tmp[4]={0,0,0,0},resp,ret ;
    
    ret=SD_SendCmd(CMD55,tmp,CMD55_R,&resp);
    /* 后续命令为一个应用命令 */
    /* command that the followed commnad is a specific application */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    
    ret=SD_SendCmd(ACMD22,tmp,ACMD22_R,&resp);
    /* 读取正确写入的块数命令 */
    /* command that read the numbers of block written correctly */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    ret=SD_ReadBlockData(4,tmp);
    /* 读块数 read the numbvers of block */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    *blocknum=((INT32U)tmp[0]<<24)+((INT32U)tmp[1]<<16)+((INT32U)tmp[2]<<8)+tmp[3];
    /* 转换为32位 change to 32 bits */
    
    return SD_NO_ERR ;
    /* 返回执行成功 return perform sucessfully */
}
#endif 

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

/*******************************************************************************
** 函数名称: INT8U SD_ReadRegister()				
** 功能描述: 从SD卡读取数据							
** 输   入: INT32U len	  : 长度					
	     INT8U  *recbuf: 接收缓冲区					 	 
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
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,*/
    
    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_CS_Deassert();
        SPI_SendByte(0xFF);
        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()			 
** 功能描述: 从SD卡中读取数据块					
** 输   入: INT32U len    : 长度				
	     INT8U *recbuf : 接收缓冲区					 
** 输   出: 0:   正确    >0:   错误码		  	
*******************************************************************************/
INT8U SD_ReadBlockData(INT32U len,INT8U *recbuf)
{
    INT8U tmp ;
    INT32U i=0 ;
    
    SPI_CS_Assert();
    do 
    {
        /* 等待接收数据开始令牌0xFE   */
        tmp=SPI_RecByte();
        i++;
    }
    while((tmp==0xFF)&&(i<sds.timeout_read));
    
    if(i>=sds.timeout_read)
    {
        SPI_CS_Deassert();
        return SD_ERR_TIMEOUT_READ ;
        /* 返回读超时错误码  return error timeout error code of reading */
    }
    
    /* 块读开始令牌错误 read start block token is error */
    if(tmp!=SD_TOK_READ_STARTBLOCK)
    {
        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))
    {
        /* CRC校验错误 CRC check is error */
        SPI_SendByte(0xFF);
        SPI_CS_Deassert();
        return SD_ERR_DATA_CRC16 ;
        /* 返回CRC16错误  return error of CRC16 */
    }
    #endif 
    
    SPI_SendByte(0xFF);
    SPI_CS_Deassert();
    
    return SD_NO_ERR ;
    /* 返回函数执行成功 return function perform sucessfully */
}

/*******************************************************************************
** 函数名称: INT8U SD_WriteBlockData()				
** 功能描述: 向sd卡写数据块							
** 输   入: INT8U bmulti  : 是否为多块操作1:是0:否 Input:	 
	     INT32U len    : 长度						  	
	     INT8U *sendbuf: 发送缓冲区					 	
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
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()				
** 功能描述: 发送多块写停止令牌						
** 输   入: 无									   
** 输   出: 无										
*******************************************************************************/
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()						
** 功能描述: 查询SD卡是否处于忙状态					
** 输   入: INT32U waittype: 超时类型				
** 输   出: 0: 未超时  >0: 错误码					
*******************************************************************************/
INT8U SD_WaitBusy(INT8U waittype)
{
    INT32U timeout,i=0 ;
    INT8U tmp ;
    
    if(waittype==SD_WAIT_WRITE)
        timeout=sds.timeout_write ;
    else 
        timeout=sds.timeout_erase ;
    
    SPI_CS_Assert();
    do 
    {
        /* 等待忙结束 wait for being busy end */
        tmp=SPI_RecByte();
        i++;
    }
    while((tmp!=0xFF)&&(i<timeout));
    /* 忙时收到的值为0xFF always receive 0xFF when card is busy */
    SPI_CS_Deassert();
    /* 有错 */
    
    if(i<timeout)
        return SD_NO_ERR ;
    /* 返回0,表示没超时 return 0 indicate that operation is not time out */
    else 
        return SD_ERR_TIMEOUT_WAIT ;
    /* 返回错误码,表示超时 return error code indicate that operation is time out */
}

/*******************************************************************************
** 函数名称: void SD_SPIDelay()						
** 功能描述: SPI总线延时							
** 输   入: INT8U value: 延时值,不超过255		 
** 输   出: 无										
*******************************************************************************/
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 + -