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