在SPI问题中初始化SD卡

时间:2010-03-02 19:05:46

标签: embedded microcontroller initialization sd-card spi

我已经看过Stack Overflow问题 Initialization of a microSD card using an SPI interface ,但没有看到任何与我的问题相符的答案(也就是我尚未尝试过的事情)。

我有一个类似的问题,我试图通过微控制器的SPI接口(特别是HC908)访问SD卡。我已经尝试遵循物理层简化规范v2.00中的流程图,它似乎在Transcend 1 GB& amp; 2 GB和AE& C 1 GB卡。但是我在相机上使用过的旧卡上存在其他三张随机卡时出现问题。

我的代码全是HC908汇编程序。我确定了SPI时钟线,并且在初始化期间它运行大约350 kHz(HC908在我的低MCU时钟速度下提供的唯一速度倍增器,在100 - 400 kHz窗口内)。

以下是未完成初始化例程的三张卡的结果(所有这些卡都是连续完成而不更改任何代码或时序参数):

Canon 16Meg card (labeled as SD):
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (indicates idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
because illegal command branch to error routine
Send CMD13 [0x4D000000000D] (show status buffer) and Loop up to 8 times waiting for high bit on response to go low
R1= 0x05 (idle and illegal command)

非法命令标志是否卡住?我应该在CMD8之后做些什么来清除那面旗帜吗?

SanDisk UltraII 256Meg
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x48000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command set local flag to indicate v1 or MMC card
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send 0xFF 4 times to read OCR
OCR = 0xFFFFFFFF
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command)
Repeat the CMD1 50 times (my arbitrary number to wait until idle clears)
Every R1 response is 0x05 (idle and illegal command)

为什么OCR都是F?看起来不合适。另外,为什么ACMD41和CMD1会响应非法命令? CMD1失败是因为即使使用非法命令响应,CMD55之后卡正在等待有效的ACMD吗?

SanDisk ExtremeIII 2G:
Set card select high
Send 80 SPI clock cycles (done by writing 0xFF 10 times)
Set card select low
Send CMD0 [0x400000000095] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Send CMD8 [0x40000001AA87] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? My loop shows the responses for each iteration and I got 0xFF 0xFF 0xC1 0x7F... is the card getting out of sync?)
Send CMD58 [0x7A00000000FD] and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle and back in sync)
Send 0xFF 4 times to read OCR
OCR = 0x00FF80
Send CMD55 [0x770000000065] (1st part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x5F (??? loop responses are 0xFF 0xFF 0xF0 0x5F... again out of sync?)
Send CMD41 [0x6900000000E5] (2nd part of ACMD41) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x05 (idle and illegal command, but back in sync???)
Because illegal command, assume card is MMC
Send CMD1 [0x4100000000F9] (for MMC) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x01 (idle)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x7F (??? loop responses are 0xFF 0xFF 0xC1 0x7F... again out of sync?)
Repeat CMD1 and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x00 (out of idle)
Send CMD9 [0x4900000000AF] (get CSD) and Loop up to 8 times waiting for high bit on response to go low
R1 = 0x3F (??? loop responses are 0xFF 0xFF 0xC1 0x3F... again out of sync?)
Code craps out because Illegal command bit is high.

这张卡究竟出了什么问题?

有时它是同步的,有时则不同步。 (上面的模式可重复的。)我已经确定了这个模式,我没有看到MOSI / MISO传输之间经历任何流氓时钟周期。

3 个答案:

答案 0 :(得分:22)

好的......我发现了我的问题。对于遇到此问题的其他任何人,请务必记住在收到回复后发送额外的0xFF。这为卡提供了额外的8个时钟周期,以便为下一个命令做好准备。有些卡似乎不需要它(例如我正在使用的Transcends),但其他卡需要它。

我实际上在我的'write command'例程的开头放了一个简单的循环,发送0xFF直到它得到0xFF作为响应,所以我不必去所有不同的我阅读回复的地方,以确保我额外发送0xFF。因为只要SD卡(通常)涉及SPI模式,如果没有时钟周期进入,时间就会停止。

有一件事我注意到并且尚未找到答案(但到目前为止它没有伤害任何东西),在我读取CSR的16个字节后,似乎还有2个字节的非{ {1}}出来......那是CRC16吗?很奇怪,因为CSR内置了CRC ...

答案 1 :(得分:3)

如果启用了CRC(使用CMD59),则是,数据块将附加CRC16。

有关详细信息,请参阅“物理层简化规范版本2.00”,章节“总线传输保护”和“数据读取”。

答案 2 :(得分:2)

这很重要:我在SD / MMC卡上遇到了很多麻烦,直到我发现我必须 选择工作电压 。 您这样做,通过发送ACMD41并为您提供卡的 位设置电压 。 注意: 只能选择一个位 。 如果您没有选择电压或选择多个电压,它将保持在空闲状态下循环,并且永远不会退出某些SD卡。

即:如果ACMD41继续发送响应0x01,则表示您没有选择电压。 电压在ACMD41的32位参数位23 ... 8中。 对于3.2V ...... 3.3V,这是第20位,所以例如你可以:

acmdSDAppOpCond[2] = (1 << (20 & 7));           /* 3.2V .. 3.3V */

这是十六进制值0x10,所以你的ACMD41看起来像这样...... 0x69 0x40 0x10 0x00 0x00 0xCD ......或者如果它是SDSC卡...... 0x69 0x00 0x10 0x00 0x00 0x5F

这是最常见值的简短(不完整)表格:

Bit23: 3.5V..3.6V
Bit22: 3.4V..3.5V
Bit21: 3.3V..3.4V
Bit20: 3.2V..3.3V
Bit19: 3.1V..3.2V
Bit18: 3.0V..3.1V
Bit17: 2.9V..3.0V
Bit16: 2.8V..2.9V
Bit15: 2.7V..2.8V

NOT 必须在任何时间点将CS切换为高电平。你可以一直保持低水平。

相关问题