打印

关于周立功的SD驱动源码中数据字节顺序颠倒问题,求解!

[复制链接]
2140|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hwk612167|  楼主 | 2013-1-6 14:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1、周立功的SD卡驱动,发送CMD,填充的4字节参数需要颠倒过来的,这点从计算CRC时可以看出,不知这样设计的道理是什么?
2、发送CMD接收应答时,将接收的数据也颠倒过来了,响应为1字节时没问题,响应为多字节时,如发送CMD58命令式,判断应答判断的是resp[0],这不就会产生bug吗?颠倒了应该判断resp[4]吧?

以下为周立功SD驱动发送CMD命令源码:
/********************************************************************************************************************
** 函数名称: INT8U SD_SendCmd()                                                Name:          INT8U SD_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
********************************************************************************************************************/
uint8 SD_SendCmd(uint8 cmd, uint8 *param, uint8 resptype, uint8 *resp)
{
        int32 i,rlen;                                                                         //所有SD卡命令都是6字节长
        uint8 tmp;

        SPI_CS_Assert();                                                             //片选SPI从机

    SPI_SendByte((cmd & 0x3F) | 0x40);                                 /* 发送命令头和命令字 send command header and word */
                                                                                                     //起始位为0(bit47),传输位为1(bit46)
    for (i = 0; i < 4; 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)                                                                 /* 根据不同的命令,得到不同的响应长度 */
    {                                                                                                 /* 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;
                      
                case R7:  rlen = 5;         break;
                 
            default:  SPI_SendByte(0xFF);       
                            SPI_CS_Deassert();                                                 
                      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 = 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 */
}

相关帖子

沙发
hwk612167|  楼主 | 2013-1-6 14:56 | 只看该作者
难道是我哪里理解有问题?现在直接用他的驱动,发送CMD58也能通过,是因为resp[0]刚好也是0x00。
而且我实际测试,发现这样确实是有问题。他判断的是resp[0],把resp[1]~[4]当做是OCR,与手册数据是不符的。

使用特权

评论回复
板凳
hwk612167|  楼主 | 2013-1-6 19:23 | 只看该作者
木有人用过么

使用特权

评论回复
地板
emailli| | 2013-1-6 21:46 | 只看该作者
大小端的问题

楼主仔细看一下大端小端

使用特权

评论回复
5
hwk612167|  楼主 | 2013-1-7 10:10 | 只看该作者
emailli 发表于 2013-1-6 21:46
大小端的问题

楼主仔细看一下大端小端

void SD_PackParam(uint8 *parameter, uint32 value)
{
    parameter[0] = (uint8)(value >> 24);
    parameter[1] = (uint8)(value >> 16);
    parameter[2] = (uint8)(value >> 8);
    parameter[3] = (uint8)(value);
}

请问这个子函数,有大小端要求么?

使用特权

评论回复
6
emailli| | 2013-1-7 17:24 | 只看该作者
大小端存储问题和你的函数没有关系。

和你使用的 平台有关

你要看一下你的协议、或者硬件平台 采用的是大端模式还是小端模式

然后才可以写你的代码

使用特权

评论回复
7
hwk612167|  楼主 | 2013-1-13 14:55 | 只看该作者
emailli 发表于 2013-1-7 17:24
大小端存储问题和你的函数没有关系。

和你使用的 平台有关

有点关系吧?
u16_var = 0x1234;
u8_var = (INT16U)u16_var;
u8_var = ?跟大小端没有关系?

使用特权

评论回复
8
emailli| | 2013-1-15 20:38 | 只看该作者
我的意思是,你要先搞清楚你的 编译器或者是你的目标芯片是大端存储还是小端存储。

这样你再来写代码才有意义

否则,你写出来的代码有什么用呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:前进 前进 前进

20

主题

511

帖子

3

粉丝