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

📄 sd_cmd.c

📁 Atmega64单片机程序(完整工程)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*--------------File Info-------------------------------------------------------
** 文   件   名:    SD_Cmd.c
** 最后修改日期:    2008.3.28
** 版        本:    V1.0
** 描        述:    sd 卡驱动软件包: SD卡物理层					
**------------------------------------------------------------------------------
** Created   by:    		
** Created date:			
*******************************************************************************/

#include "SYS_Config.h" 
#include "SD_Config.h" 
#include "SD_Hal.h" 
#include "SD_CRC.h" 
#include "SD_Cmd.h" 
#include "SD_Drive.h" 

/*******************************************************************************
** 函数名称: INT8U SD_SendCmd()						
** 功能描述: 向卡发送命令,并取得响应				 
** 输   入: INT8U cmd	    : 命令字				 
	         INT8U *param   : 命令参数,长度为4字节			  
	         INT8U resptype : 响应类型						
	         INT8U *resp    : 响应,长度为1-5字节			
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_SendCmd(INT8U cmd,INT8U *param,INT8U resptype,INT8U *resp)
{
    INT32S i,rlen ;
    INT8U tmp ;
    
    SPI_CS_Assert();
    
    SPI_SendByte((cmd&0x3F)|0x40);
    /* 发送命令头和命令字 send command header and word */
    
    for(i=3;i>=0;i--)
        SPI_SendByte(param[i]);
    /* 发送参数 send parameters */
    
    #if SD_CRC_EN 
        tmp=SD_GetCmdByte6((cmd&0x3F)|0x40,param);
        SPI_SendByte(tmp);
    #else 
        SPI_SendByte(0x95);
        /* CRC校验码,只用于第1个命令 CRC,only used for the first command */
    #endif 
    
    rlen=0 ;
    /* 根据不同的命令,得到不同的响应长度 */
    switch(resptype)
    {
        case R1 :
        case R1B:rlen=1 ;break ;
        case R2 :rlen=2 ;break ;
        case R3 :rlen=5 ;break ;
        default :
	            SPI_SendByte(0xFF);
	            SPI_CS_Deassert();
        return SD_ERR_CMD_RESPTYPE ; // 返回命令响应类型错误 
        break ;
    }
    
    i=0 ;
    /* 等待响应,响应的开始位为0 */
    do 
    {
        /* Wait for a response,a response is a start bit(zero) */
        tmp=SPI_RecByte();
        i++;
    }
    while(((tmp&0x80)!=0)&&(i<SD_CMD_TIMEOUT));
    
    if(i>=SD_CMD_TIMEOUT)
    {
        SPI_CS_Deassert();
        return SD_ERR_CMD_TIMEOUT ;
        /* 返回命令超时 return response timeout of command */
    }
    
    for(i=rlen-1;i>=0;i--)
    {
        resp[i]=tmp ;
        tmp=SPI_RecByte();
        /* 循环的最后发送8clock  at the last recycle,clock out 8 clock */
    }
    
    SPI_CS_Deassert();
    return SD_NO_ERR ;
    /* 返回执行成功 return perform sucessfully */
}

/*******************************************************************************
** 函数名称: void SD_PackParam()					
** 功能描述: 将32位的参数转为字节形式				
** 输   入: INT8U *parameter: 字节参数缓冲区		
	         INT32U value    : 32位参数		
** 输   出: 无								
*******************************************************************************/
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()				
** 功能描述: 块命令									
** 输   入: INT8U cmd	     : 命令字				
			 INT8U resptype  : 响应类型						 
			 INT32U parameter: 块操作参数			 		  
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_BlockCommand(INT8U cmd,INT8U resptype,INT32U parameter)
{
    INT8U 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 ;
}

/*************************************************
	
下面为SD卡SPI命令

/*******************************************************************************
** 函数名称: INT8U SD_ResetSD()						
** 功能描述: 复位SD卡								
** 输   入: 无										
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
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_ReadCSD()						
** 功能描述: 读SD卡的CSD寄存器						
** 输   入: INT8U csdlen  : 寄存器长度(固定为16)			  
	     INT8U *recbuf : 接收缓冲区					
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_ReadCSD(INT8U csdlen,INT8U *recbuf)
{
    INT8U param[4]={0,0,0,0},resp,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_ReadRegister(csdlen,recbuf));
}

/*******************************************************************************
** 函数名称: INT8U SD_ReadCID()						
** 功能描述: 读SD卡的CID寄存器						
** 输   入: INT8U cidlen  : 寄存器长度(固定为16)			  
	     INT8U *recbuf : 接收缓冲区			
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
#if SD_ReadCID_EN 
INT8U SD_ReadCID(INT8U cidlen,INT8U *recbuf)
{
    INT8U param[4]={0,0,0,0},resp,ret ;
    
    ret=SD_SendCmd(CMD10,param,CMD10_R,&resp);
    /* 读CID寄存器命令 command that read CID register */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    return(SD_ReadRegister(cidlen,recbuf));
}
#endif 

/*******************************************************************************
** 函数名称: INT8U SD_StopTransmission()			
** 功能描述: 停止数据传输							
** 输   入: 无								 		
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_StopTransmission(void)
{
    INT8U param[4]={0,0,0,0},resp ;
    
    return(SD_SendCmd(CMD12,param,CMD12_R,&resp));
    /* 结束数据传输命令失败 stop transmission command fail */
}

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


/*******************************************************************************
** 函数名称: INT8U Sd_SetBlockLen()					
** 功能描述: 设置一个块的长度						
** 输   入: INT32U length	: 块的长度值			
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_SetBlockLen(INT32U length)
{
    INT8U param[4],resp,ret ;
    
    SD_PackParam(param,length);
    /* 将参数转化为字节形式 change the parameter to bytes form */
    
    ret=SD_SendCmd(CMD16,param,CMD16_R,&resp);
    if(ret!=SD_NO_ERR)
        return ret ;
    /* 设置块的长度为length失败 set the length of block to length fail */
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    return SD_NO_ERR ; /* 返回执行成功 return perform sucessfully */
}

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

/*******************************************************************************
** 函数名称: INT8U SD_ReadMultipleBlock()			
** 功能描述: 读多块命令								
** 输   入: INT32U blockaddr: 块地址				
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_ReadMultipleBlock(INT32U blockaddr)
{
    return(SD_BlockCommand(CMD18,CMD18_R,blockaddr));
    /* 读多块命令 command that read multiple block */
}

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

/*******************************************************************************
** 函数名称: INT8U SD_WriteMultipleBlock()			
** 功能描述: 写多块命令								
** 输   入: INT32U blockaddr: 块地址				
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_WriteMultipleBlock(INT32U blockaddr)
{
    return(SD_BlockCommand(CMD25,CMD25_R,blockaddr));
    /* 写多块命令 command that write multiple block */
}

/*******************************************************************************
** 函数名称: INT8U SD_ProgramCSD()						
** 功能描述: 写CSD寄存器								
** 输   入: INT8U *buff   		 : CSD寄存器内容		
			 INT8U len	  		 : CSD寄存器长度	
** 输   出: 0:   正确    >0:   错误码		  			
*******************************************************************************/
#if SD_ProgramCSD_EN 
INT8U SD_ProgramCSD(INT8U len,INT8U*buff)
{
    INT8U param[4]={0,0,0,0},resp,ret ;
    
    if(len!=16)
        return SD_ERR_USER_PARAM ;
    
    ret=SD_SendCmd(CMD27,param,CMD27_R,&resp);
    /* 发送写CSD寄存器命令 send command that write CSD */
    if(ret!=SD_NO_ERR)
        return ret ;
    
    if(resp!=0)
        return SD_ERR_CMD_RESP ;
    
    buff[15]=(SD_GetCRC7(buff,15)<<1)+0x01 ;
    /* 计算CSD中的crc 位域 calculate crc field in CSD */
    
    return(SD_WriteBlockData(0,16,buff));
}
#endif 

#if SD_EraseBlock_EN 
/*******************************************************************************
** 函数名称: INT8U SD_EraseStartBlock()				
** 功能描述: 设置块擦除起始地址						
** 输   入: INT32U startblock: 块地址				
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_EraseStartBlock(INT32U startblock)
{
    return(SD_BlockCommand(CMD32,CMD32_R,startblock));
    /* 发送擦除起始块地址 send the start block address of erasing operation */
}

/*******************************************************************************
** 函数名称: INT8U SD_EraseEndBlock()				
** 功能描述: 设置块擦除终止地址						
** 输   入: INT32U endblock: 块地址				
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_EraseEndBlock(INT32U endblock)
{
    return(SD_BlockCommand(CMD33,CMD33_R,endblock));
    /* 发送擦除终止块地址 send the end block address of erasing operation */
}

/*******************************************************************************
** 函数名称: INT8U SD_EraseSelectedBlock()			
** 功能描述: 擦除已选中的块							
** 输   入: 无										
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_EraseSelectedBlock(void)
{
    INT8U param[4],resp,tmp ;
    
    SD_PackParam(param,0);
    
    tmp=SD_SendCmd(CMD38,param,CMD38_R,&resp);
    /* 擦除所选择的块  erase blocks selected */
    if(tmp!=SD_NO_ERR)
        return tmp ;
    
    /* 等待擦除完成 wait for finishing erasing */
    if(SD_WaitBusy(SD_WAIT_ERASE)!=SD_NO_ERR)
        return SD_ERR_TIMEOUT_ERASE ;
    else 
        return SD_NO_ERR ;
}
#endif 

/******************************************************************************
** 函数名称: INT8U SD_ReadOCR()						
** 功能描述: 读操作条件寄存器OCR					
** 输   入: INT8U ocrlen  : 寄存器长度(固定为4)	
	         INT8U *recbuf : 接收缓冲区			
** 输   出: 0:   正确    >0:   错误码		  		
*******************************************************************************/
INT8U SD_ReadOCR(INT8U ocrlen,INT8U *recbuf)
{
    INT8U param[4]={0,0,0,0},resp[5],tmp ;
    
	ocrlen=ocrlen;
    tmp=SD_SendCmd(CMD58,param,CMD58_R,resp);
    /* 读 OCR 寄存器命令 */
    /* read OCR register command */
    if(tmp!=SD_NO_ERR)
        return tmp ;
    
    if(resp[0]!=0)
        return SD_ERR_CMD_RESP ;
    /* 响应错误 response is error */
    
    for(tmp=0;tmp<4;tmp++)
        recbuf[tmp]=resp[tmp+1];/* 复制OCR寄存器内容到接收缓冲区 */
	
    return SD_NO_ERR ;
}

⌨️ 快捷键说明

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