3

LPC4088 マイクロコントローラー用の SPI SD ドライバーに取り組んでいます。ただし、V2 カードまたは大容量カードを使用しているかどうかを検出するためにCMD8(の後に) を送信すると、奇妙な応答が返されます。CMD0正しい応答(0x01最上位ビットの場合0x1AA、下位12の場合)またはエラーを取得する代わりに0x00 00 00 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;
        }
    }
    //....
}

send_command コード:

    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;
    }

SPI プロトコルにエラーがないことを確認するために、ロジック アナライザーで入力と出力を検証しました。結果: CMD0の後にCMD8が続きます。正しいコマンドを送信しているようですが、それでもこの奇妙な応答が返されます。

セットアップに関する追加情報:

  • マイコンはLPC4088

  • マイクロコントローラはこの OEM ボードに接続されています

  • SDカードモジュールはOEMボードのシリアル拡張コネクタに接続

  • ロジックアナライザーをSDカードモジュールに接続

  • マイクロコントローラーと OEM ボードの両方の 2 つの異なるバージョンを使用して、それらのいずれかにハードウェア エラーがあることを除外しました。残念ながら、2 つ目の SD コントローラーはありません。

  • SanDisk Ultra SDHC 4GB Class 6 SD カードと Transcend SDHC 4GB Class 4 SD カードを使用しましたが、どちらもまったく同じ結果が得られました。

最後になりましたが、私は組み込みソフトウェアの経験がほとんどないため、小さなばかげたエラーに過ぎない可能性があります。

4

1 に答える 1

2

MISO ラインにノイズが発生していることが判明しました。コードは正しかったのですが、ノイズが原因で、マイクロコントローラは意図したものとは異なる結果を得ました。電子工学の専門家の助けを借りて、MISO とグランドの間にコンデンサをはんだ付けすることで、これをフィルタリングすることができました。

于 2014-01-26T14:22:41.967 に答える