SD卡死活无法完成初始化,在线求助

[复制链接]
12142|19
 楼主| tearsman520 发表于 2011-4-30 17:03 | 显示全部楼层 |阅读模式
先说明一下我使用的硬件平台。主控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平台上都移植过,没有任何问题。
 楼主| tearsman520 发表于 2011-5-2 01:53 | 显示全部楼层
自己顶一下……
 楼主| tearsman520 发表于 2011-5-3 01:29 | 显示全部楼层
再来顶……还没解决……
ningling_21 发表于 2011-5-3 07:41 | 显示全部楼层
汇编程序给你参考一下啊

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| tearsman520 发表于 2011-5-4 11:25 | 显示全部楼层
谢谢ningling_21,我回去再试一下,可否通过站内信告知您的联系方式?
 楼主| tearsman520 发表于 2011-5-4 13:59 | 显示全部楼层
感谢楼上朋友kimfufree的提醒,我准备用示波器看一下完整的波形,作个对比……
古道热肠 发表于 2011-5-4 14:34 | 显示全部楼层
附件中有个完整的MP3播放程序,含SD卡驱动。SD卡初始化还是比较容易的,注意细读SD卡协议。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
t.jm 发表于 2011-5-4 16:05 | 显示全部楼层
SD卡最容易忽视的问题就是同步的问题,尤其是硬件SPI时,模拟SPI还好些,
开始写了个读SD的驱动,如果被INT打断就出错,而关闭INT读大文件也不出错,
后来发现是同步的问题,因为硬件SPI可以工作在连续模式(前一个发送还没完成就可写第二个数据到
发送缓冲),极易造成无法同步,读到的数据可能是前一个的。
改写了等待响应函数后就好了,也不再怕中断被打断。
我用的是STM8,看到ST的官方SD历程发送命令还是很保守。
 楼主| tearsman520 发表于 2011-5-5 12:57 | 显示全部楼层
感谢楼上朋友们的热心帮助。
我需要说明的一点是:
上述同样的程序,我在其他平台上运行过,同样使用SPI硬件接口。
其他平台——例如M051和ATmega16,都能很好的运行初始化程序。
所以,唯一的可能就是我现在用的笙泉MA805-24的8位MCU的SPI接口时序与其他平台有不同。
至于不同在哪里,得借助于示波器。
 楼主| tearsman520 发表于 2011-5-5 13:05 | 显示全部楼层
9# t.jm

我已经关闭了其他所有中断,设置在初始化完成后打开中断,还是不奏效。
不知兄弟你的等待响应函数是什么样的呢?

另外,根据MA805-24的参数手册,我对SPI硬件接口的GPIO均设置为推挽输出模式。
MOSI, MISO, SCK均为推挽输出,SS引脚使用了其他的PIN脚。

因为MA805-24的GPIO设置在推挽模式下才能通过内部上拉读取端口电平值。

应该不会是硬件端口设置上的问题,因为发送CMD8的时候,已经读到了SD卡所支持的电平范围。
 楼主| tearsman520 发表于 2011-5-5 13:07 | 显示全部楼层
8# 古道热肠

谢谢古道热肠,之前其实我已经仔细阅读过SD协议,而且我不止在一个平台上实现了SD卡的读写。只是在这个平台上遇到了这样的问题,以前的平台移植从来没出现过发送ACMD41总是返回0x01的问题。郁闷了……
ee168 发表于 2013-2-17 11:08 | 显示全部楼层
我也遇到过,很难初始化,有时可以有时不可以,,有人说端口要接上拉电阻,但是我是5V-3V的,电阻串并联,不好作上拉,现在画板,怕又遇到这个问题
qchwu 发表于 2013-6-16 14:08 | 显示全部楼层
请问楼上的问题解决了吗?为什么有时可以,有时不可以。
sdwys 发表于 2013-6-19 17:44 | 显示全部楼层
现在在做SD卡的东西,先学习下。
jekey 发表于 2013-6-19 20:51 | 显示全部楼层
SD卡的标准上有复位的处理流程。看程序并没有完全遵守。
lz80650904 发表于 2013-6-20 17:27 | 显示全部楼层
apple 发表于 2013-6-20 19:15 | 显示全部楼层
SD卡对时序要求很严,我们用FPGA做4线读写没有成功,不稳定!
笑鸟007 发表于 2014-7-23 14:57 | 显示全部楼层
我在读sd卡,也初始化不成功。特来学习学习。
tt朝花夕拾 发表于 2017-7-26 15:52 | 显示全部楼层
tearsman520 发表于 2011-5-5 13:07
8# 古道热肠

谢谢古道热肠,之前其实我已经仔细阅读过SD协议,而且我不止在一个平台上实现了SD卡的读写 ...

楼主请问,ACMD41返回一直0x01的问题解决了么?
我也遇到了这个问题,可以请教下么?
changle11sdo5 发表于 2017-8-30 16:10 来自手机 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

22

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部