2010-03-02 114 views
8

我看了一下堆栈溢出问题Initialization of a microSD card using an SPI interface并没有看到与我的问题相匹配的任何答案(即,我还没有试过的东西)。在SPI问题中初始化SD卡

我有一个类似的问题,我试图通过微控制器的SPI接口(特别是HC908)访问SD卡。我已经尝试遵循物理层简化规范v2.00中的流程图,并且似乎在创见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会响应非法命令?即使命令响应非法,卡CMD55等待有效的ACMD,CMD1是否失败?

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传输之间有任何流氓时钟周期。

+0

忘了提。在这些尝试初始化3张卡失败后,我将它们放入笔记本电脑的SD卡读卡器中,我仍然可以将它们作为标准SD卡(读取和写入)不带任何问题进行访问。 – Sembazuru 2010-03-02 19:27:46

+0

在“SanDisk ExtremeIII”的命令列表中发现了一个错误:发送CMD8 [0x40000001AA87] - 它应该是0x48,而不是0x40。 – 2014-04-19 15:06:55

回答

20

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

我实际上在我的'写入命令'例程的开始处发送了一个简单的循环,它发送0xFF,直到它得到0xFF作为响应,因此我不必去所有读取响应的不同地方当然我会额外发送0xFF。因为就SD卡而言(通常)在SPI模式下,如果没有时钟周期进入,时间依然存在。

有一件事我注意到并且还没有找到答案(但是到目前为止它没有伤害任何东西),在我读了CSR的16个字节之后,似乎还有另外2个字节的非零字节, 0xFF出来...这是一个CRC16?因为CSR有内置的CRC ...

+3

感谢您分享。 – 2010-03-04 23:22:37

+1

谢谢,你救我几个小时! – 2013-02-19 16:30:46

+1

同上,这是非常有用的,特别是发送0xFF,直到返回0xFF。我有一个Class 2 Transcend卡可以正常工作,但是当我切换到Class 4 Transcend卡时,我可以初始化但不能读取它。现在我能。谢谢。 – David 2013-04-05 22:12:02

3

如果您启用了CRC(与CMD59),那么是的,数据块将添加CRC16。

欲了解更多信息,请参阅“物理层简化规格版本2.00”,章节“总线传输保护”和“数据读取”。

+0

对不起,这么晚的回应......(忙于其他项目......)我想我没有在概念上将CSR视为“数据块”。我只是把它想成一个状态寄存器。 – Sembazuru 2011-03-17 16:31:18

1

这一点很重要:我已经受够了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是这样的...... ×69 0x40的0x10的0×00 0×00 0XCD ...或者如果它是一个SDSC卡... ×69 0×00 0×10 0×00 0×00 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 

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

+1

Sandisk SDCard规范说明如下: “在SPI模式下,与SD模式相反,ACMD41(或CMD1以及2.1mm-SD卡)没有操作数,并且不返回OCR寄存器的内容。 ,主机可以使用CMD58(仅在SPI模式下)读取OCR寄存器,此外,主机有责任避免访问不支持其电压范围的卡。“官方规范并没有反对这一点,并明确表示ACMD 41应该有一个标准容量卡的0x0参数。 – thenickdude 2015-10-21 23:15:31

+1

但是,在SD模式下,将需要该参数: “[...]主机发送所需的VDD电压窗口作为[SD_SEND_OP_COND(ACMD41)]命令的操作数无法执行数据传输的SD卡指定的范围必须放弃进一步的总线操作并进入非活动状态 通过省略命令中的电压范围,主机可以查询每张卡并确定是否在将超出范围的卡发送到无效状态“。 – thenickdude 2015-10-21 23:20:44