先说明一下我使用的硬件平台。主控MCU是51架构的MA805-24(笙泉的8位MCU)。
硬件上SPI接口4线连接SD卡。
MCU供电为5V,SD卡供电3.3V,从MCU到SD卡的MOSI,SCK,SS均已经电阻分压。初始化代码如下:
DSTATUS disk_initialize (void)
{
UINT n, cmd, ty, ocr[4];
WORD tmr;
init_spi(); /* Initialize USI */
for (tmr = 200; tmr; tmr--) rcv_spi(); /* Dummy clocks */
SELECT();
for (tmr = 2000; tmr; tmr--) rcv_spi(); /* Dummy clocks */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
printf("Enter Idle Mode!\n");
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2 */
printf("Card Type is SDv2!\n");
for (n = 0; n < 4; n++) {
ocr[n] = rcv_spi(); /* Get trailing return value of R7 resp */
//printf("ocr[%d] = %x\n",n,ocr[n]);
}
printf("ocr0 = %2x\n",ocr[0]);
printf("ocr1 = %2x\n",ocr[1]);
printf("ocr2 = %2x\n",ocr[2]);
printf("ocr3 = %2x\n",ocr[3]);
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
printf("The card can work at 2.7~3.6V!\n");
for (tmr = 25000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ; /* Wait for leaving idle state (ACMD41 with HCS bit) */
printf("tmr value = %d!\n",tmr);
// while(send_cmd(ACMD41, 0) != 0);
// tmr = 1;
if (tmr && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
printf("Now checking CCS!\n");
for (n = 0; n < 4; n++) ocr[n] = rcv_spi();
// printf("ocr0 = %2x\n",ocr[0]);
// printf("ocr1 = %2x\n",ocr[1]);
// printf("ocr2 = %2x\n",ocr[2]);
// printf("ocr3 = %2x\n",ocr[3]);
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
}
}
}
else { /* SDv1 or MMC */
if (send_cmd(ACMD41, 0) <= 1) {
printf("Card Type is SDv1!\n");
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
printf("Card Type is MMC!\n");
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ; /* Wait for leaving idle state */
if (!tmr || send_cmd(CMD16, 512) != 0) { /* Set R/W block length to 512 */
printf("ACMD41 Command failed!\n");
ty = 0;
}
}
}
else
printf("Enter Idle mode failed!\n");
CardType = ty;
printf("CardType value is %d\n",ty);
fast_spi();
release_spi();
return ty ? 0 : STA_NOINIT;
}
static
BYTE send_cmd (
BYTE cmd, /* Command byte */
DWORD arg /* Argument */
)
{
UINT n, res;
BYTE id;
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
id = 1;
cmd &= 0x7F;
res = send_cmd(CMD55, 0);
// printf("Now sending CMD55 to send ACMD41, res = %2x!\n",res);
if (res > 1) return res;
}
/* Select the card and wait for ready */
DESELECT();
rcv_spi();
SELECT();
rcv_spi();
// #asm("nop")
/* Send command packet */
xmit_spi(cmd); /* Start + Command index */
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xmit_spi((BYTE)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
xmit_spi(n);
/* Receive command response */
n = 2000; /* Wait for a valid response in timeout of 10 attempts */
do {
res = rcv_spi();
} while ((res & 0x80) && --n);
// if(id == 1) id = 0, printf("ACMD41 res is %4x\n",res);
return res; /* Return with the response value */
}
程序DEBUG的结果是:
Device Initialize Finished!
Enter Idle Mode!
Card Type is SDv2!
ocr0 = 0
ocr1 = 0
ocr2 = 1
ocr3 = aa
The card can work at 2.7~3.6V!
tmr value = 0!
CardType value is 0
FatFs Load Failed!
发送ACMD41收到的响应死活为0x01,实在是想不通,同样的软件我在M051和AVR平台上都移植过,没有任何问题。 |