sdcard.c
来自「ARM7 lpc2132+vs1003+sdcard 制作的 MP3 此程序在」· C语言 代码 · 共 1,442 行 · 第 1/5 页
C
1,442 行
while (((tmp & 0x80) != 0) && (i < SD_CMD_TIMEOUT));
if (i >= SD_CMD_TIMEOUT)
{
SPI1_CS_SET();
return SD_ERR_CMD_TIMEOUT; /* 返回命令超时 return response timeout of command */
}
for (i = rlen - 1; i >= 0; i--)
{
resp[i] = tmp;
tmp = SPI1_SrByte(0XFF); /* 循环的最后发送8clock at the last recycle,clock out 8 clock */
}
SPI1_CS_SET();
return (SD_NO_ERR); /* 返回执行成功 return perform sucessfully */
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadReg() Name: INT8U SD_ReadReg()
** 功能描述: 从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_ReadReg(INT32U len, INT8U *recbuf)
{
INT32U i = 0;
INT8U resp;
SPI1_CS_CLR();
do
{ /* 等待数据起始令牌 wait for data start token */
resp = SPI1_SrByte(0XFF);
i++;
}
while((resp == 0xFF) && (i < SD_READREG_TIMEOUT));
if (i >= SD_READREG_TIMEOUT)
{
SPI1_CS_SET();
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] = SPI1_SrByte(0XFF); /* 接收数据 receive data */
}
i = SPI1_SrByte(0XFF);
i = (i << 8) + SPI1_SrByte(0XFF); /* 读取16位CRC get 16-bit CRC */
#if SD_CRC_EN
if (i != SD_GetCRC16(recbuf, len))
{ /* CRC校验错误 CRC check is error */
SPI1_CS_SET();
SPI1_SrByte(0xFF);
return SD_ERR_DATA_CRC16; /* 返回RCR16错误 return error of CRC16 */
}
#endif
SPI1_SrByte(0xFF); /* 返回之前发送8个clock clock out 8 clk before return */
SPI1_CS_SET();
return (SD_NO_ERR);
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ReadCSD() Name: INT8U SD_ReadCSD()
** 功能描述: 读SD卡的CSD寄存器 Function: read CSD register of sd card
** 输 入 : INT8U csdlen : 寄存器长度(固定为16) INT8U csdlen : len of register (fixed,is 16)
INT8U *recbuf : 接收缓冲区 INT8U *recbuf : recbuffer
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
INT8U SD_ReadCSD(INT8U csdlen, INT8U *recbuf)
{
INT8U param[4] = {0,0,0,0};
INT8U resp;
INT8U 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_ReadReg(csdlen, recbuf));
}
/*******************************************************************************************************************
** 函数名称: INT8U SD_CalTimeout() Name: INT8U SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
** 输 入 : INT8U cardtype: 卡类型 Input: INT8U cardtype: card type
INT8U *csdbuf : CSD寄存器内容 INT8U *csdbuf : CSD register content
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*******************************************************************************************************************/
void SD_CalTimeout(INT8U *csdbuf)
{
INT32U tmp;
INT8U time_u,time_v,fator;
sds.timeout_read = READ_TIMEOUT_100MS; /* 默认读超时为100ms */
sds.timeout_write = WRITE_TIMEOUT_250MS; /* 默认写超时为250ms */
sds.timeout_erase = WRITE_TIMEOUT_250MS;
time_u = (csdbuf[TAAC_POS] & TAAC_MSK); /* 读超时时间单位 read timeout unit */
time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3; /* 读超时时间值 read timeout value */
fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2; /* 写超时时间因数 write timeout factor */
if(time_v == 0)
{
return;
}
if(fator >= 6)
{
return;
}
tmp = SPI1_CLOCK * time_value[time_v] / 10 / time_unit[time_u]; /* TACC * f (单位 unit: clock) */
tmp = tmp + csdbuf[NSAC_POS] * 100; /* TACC * f + NSAC * 100 (单位 unit: clock) */
/* 计算得到的超时值 the timeout value of being calculated */
sds.timeout_read = tmp;
sds.timeout_write = tmp * r2w_fator[fator]; /* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
sds.timeout_read = sds.timeout_read * 100 / 8; /* 实际值为计算值的100倍 */
sds.timeout_write = sds.timeout_write * 100 / 8;
if (sds.timeout_read > READ_TIMEOUT_100MS) /* 取计算值与默认值中的最小值 */
{
sds.timeout_read = READ_TIMEOUT_100MS;
}
if (sds.timeout_write > WRITE_TIMEOUT_250MS)
{
sds.timeout_write = WRITE_TIMEOUT_250MS;
}
sds.timeout_erase = sds.timeout_write;
}
/*******************************************************************************************************************
** 函数名称: INT8U SD_CalTimeout() Name: INT8U SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
** 输 入: INT8U *cardtype: 卡类型接收缓冲 Input: INT8U *cardtype: card type receive buff
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
当响应的Idle位为0时,SD卡就完全进入SPI1模式了。当然重复发送命令CMD1是有次数限制的,
最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
INT8U SD_ActiveInit(void)
{
INT8U param[4] = {0,0,0,0};
INT8U resp[5];
INT8U ret;
INT32U i = 0;
do
{ /* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */
ret = SD_SendCmd(CMD1, param, CMD1_R, resp);
if (ret != SD_NO_ERR)
{
return ret;
}
i++;
}
while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i < SD_IDLE_WAIT_MAX));
/* 如果响应R1的最低位Idle位为1,则继续循环 */
if (i >= SD_IDLE_WAIT_MAX)
{
return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误 time out,return error */
}
return (SD_NO_ERR);
}
/*******************************************************************************************************************
** 函数名称: INT16U SD_GetZLGSDVer() Name: INT16U SD_GetZLGSDVer()
** 功能描述: 得到SD的版本号 Function: get the version of ZLG/SD
** 输 入: 无 Input: NULL
** 输 出: 版本号 Output: Version
*******************************************************************************************************************/
INT16U SD_GetSDVer(void)
{
return 0x0100; /* 版本号为 1.00 */
}
/********************************************************************************************************************
** 函数名称: void SD_PackParam() Name: void SD_PackParam()
** 功能描述: 将32位的参数转为字节形式 Function: change 32bit parameter to bytes form
** 输 入: INT8U *parameter: 字节参数缓冲区 Input: INT8U *parameter: the buffer of bytes parameter
INT32U value : 32位参数 INT32U value : 32bit parameter
** 输 出: 无 Output: NULL
*********************************************************************************************************************/
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() Name: INT8U SD_BlockCommand()
** 功能描述: 块命令 Function: command about block operation
** 输 入: INT8U cmd : 命令字 Input: INT8U cmd : command byte
INT8U resptype : 响应类型 INT8U resptype : response type
INT32U parameter: 块操作参数 INT32U parameter: parameter of block operation
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
INT8U SD_BlockCommand(INT8U cmd, INT8U resptype, INT32U parameter)
{
INT8U param[4];
INT8U resp;
INT8U 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);
}
/********************************************************************************************************************
** 函数名称: INT8U SD_ResetSD() Name: INT8U SD_ResetSD()
** 功能描述: 复位SD卡 Function: reset sd card
** 输 入: 无 Input: NULL
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*********************************************************************************************************************/
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_GetCardInfo() Name: INT8U SD_GetCardInfo()
** 功能描述: 获得SD卡的信息 Function: get the information of SD card
** 输 入 : INT8U cardtype: 卡类型 Input: INT8U cardtype: card type
** 输 出 : 0: 正确 >0: 错误码 Output: 0: right >0: error code
*******************************************************************************************************************/
INT8U SD_GetCardInfo(void)
{
INT32U tmp;
INT8U csdbuf[16],ret;
ret = SD_ReadCSD(16,csdbuf); /* 读CSD寄存器 read CSD register */
if (ret != SD_NO_ERR)
{
return ret;
}
SD_CalTimeout(csdbuf); /* 计算超时时间值 calculate timeout value */
/* 计算块的最大长度 */ /* calculate the size of a sector */
sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK); /* (2 ^ READ_BL_LEN) */
/* 计算卡中块的个数 */ /* calculate the sector numbers of the SD Card */
sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
(csdbuf[C_SIZE_POS2] << 2) +
((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1; /* (C_SIZE + 1)*/
tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +
((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2; /* (C_SIZE_MULT + 2) */
/* 获得卡中块的数量 */ /* get the block numbers in card */
sds.block_num = sds.block_num * (1 << tmp); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
/* 计算扇区大小 *//*calculate the size of sector */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?