Embedded SD over SPI在CMD8上返回无效响应

Embedded SD over SPI在CMD8上返回无效响应,embedded,driver,sd-card,lpc,Embedded,Driver,Sd Card,Lpc,我正在为LPC4088微控制器开发一个SPI SD驱动程序。但是,当我发送CMD8(在CMD0之后)以检测我是否正在使用V2或高容量卡时,我会收到一个奇怪的响应。我没有得到正确的响应(0x01用于最高位,0x1AA用于较低的12位)或错误,而是得到了0x00 02 1F,这对我来说毫无意义 我用于初始化的代码: bool initialize () { //0. Initialize SPI SPI::init(); //1. Set clock to 400kHz

我正在为LPC4088微控制器开发一个SPI SD驱动程序。但是,当我发送
CMD8
(在
CMD0
之后)以检测我是否正在使用V2或高容量卡时,我会收到一个奇怪的响应。我没有得到正确的响应(
0x01
用于最高位,
0x1AA
用于较低的12位)或错误,而是得到了
0x00 02 1F
,这对我来说毫无意义

我用于初始化的代码:

bool initialize () {
    //0. Initialize SPI
    SPI::init();

    //1. Set clock to 400kHz
    SPI::set_clock(400000);


    //2. Assert CS signal (=0)
    assert_cs();

    // 3. Delay at least 74 clocks
    delay8(10);
    // 4. Deassert CS signal
    deassert_cs();

    // 5. Delay at least 16 clocks
    delay8(2);

    uint8_t argument[4];
    reset_argument(argument);

    // 6. Send CMD0 (reset, go to idle)
    if (!send_command(CMD::GO_IDLE_STATE, CMD_RESPONSE_SIZE::GO_IDLE_STATE, response, argument)) {
        return false;
    }

    // 7. Send CMD8
    bool version2;
    reset_argument(argument);
    pack_argument(argument, 0x1AA);

    if (!send_command(CMD::SEND_IF_COND, CMD_RESPONSE_SIZE::SEND_IF_COND, response, argument)) { 
        return false; 
    }
    if ((response[0] & 0xFE) == 0x04) {
        //unknown command. This means we have version1
        version2 = false;
    } else if (response[0] & 0xFE) {
        //other error, let's bail
         return false;
    } else {
        //Response, we're version2
        version2 = true;
        if (response[4] != 0xAA) {
            return false;
        }
    }
    //....
}
发送命令代码:

    bool send_command(CMD::value cmd, uint8_t response_size, uint8_t *response, uint8_t *argument) {

        assert_cs();
        Crc7_SD crc;
        crc += cmd | 0x40;
        crc += argument[3] & 0xFF;
        crc += argument[2] & 0xFF;
        crc += argument[1] & 0xFF;
        crc += argument[0] & 0xFF;

        SPI::send(cmd | 0x40);
        SPI::send(argument[3] & 0xFF);
        SPI::send(argument[2] & 0xFF);
        SPI::send(argument[1] & 0xFF);
        SPI::send(argument[0] & 0xFF);
        SPI::send((crc << 1) | 1);

        volatile uint8_t data;
        {
            unsigned int timeout = SD_CMD_TIMEOUT;
            do {
                data = SPI::receive();
                --timeout;
            } while(timeout && (data & 0x80));
            if (timeout == 0) {
                deassert_cs();
                return false;
            }
        }

        for (int i = 0; i < response_size; i++) {
            //First byte is already read above
            if (response) {
                response[i] = data;
            }
            data = SPI::receive();

        }

        deassert_cs();

        return true;
    }
bool send_命令(CMD::value CMD,uint8_t response_size,uint8_t*response,uint8_t*参数){
断言_cs();
Crc7_SD crc;
crc+=cmd | 0x40;
crc+=参数[3]&0xFF;
crc+=参数[2]&0xFF;
crc+=参数[1]&0xFF;
crc+=参数[0]&0xFF;
SPI::send(cmd | 0x40);
SPI::send(参数[3]&0xFF);
SPI::send(参数[2]&0xFF);
SPI::send(参数[1]&0xFF);
SPI::send(参数[0]&0xFF);

SPI::发送((crc结果是MISO线路上有一些噪声。代码是正确的,但由于噪声,微控制器得到了不同的结果。在一些电子人员的帮助下,我能够通过在MISO和接地之间焊接电容器来过滤这些噪声。

你的论点顺序对我来说似乎很奇怪。你发送first
参数[3]
,我首先假设
参数[0]
。但这取决于
pack_参数()
函数,并且
crc
crc+=cmd | 0x40
中使用之前未初始化。CMD0的发送crc字符应为0x95,CMD8的发送crc字符应为0x87(从我的工作源代码读取)@jeb-参数以正确的顺序发送,正如您在逻辑分析仪的输出中所看到的那样。此外,crc已正确初始化。
0x95
0x87
与相应的命令一起发送。很高兴您解决了问题,但加载带有CAP的数据行似乎有点不寻常。您可能有一些严重的布局问题问题-如果电线很长,可能需要端接电阻器。您可能还需要检查电源是否被充分旁路。这目前仅用于开发设置。我们的定制PCB尚未完成,但我确实需要为其开发软件(我只做软件).所以这只是我的开发设置的一个脏补丁,真正的设置当然会设计得更好(由比我更了解pcb设计的人设计)。你有数据线上的上拉和时钟线上的下拉吗?-如果没有,试着看看它是否可以替换电容器(因为电容器听起来不对)。还有一个细节:也许您还需要检查响应[3]==1和响应[1..2]==0,以确保您不会拿回碎片。据我所知,您应该验证整个响应。