📄 sd_cmd.c
字号:
/*--------------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 + -