打印

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

[复制链接]
10847|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 | 只看该作者
汇编程序给你参考一下啊

SD.rar

1.47 KB

使用特权

评论回复
5
tearsman520|  楼主 | 2011-5-4 11:25 | 只看该作者
谢谢ningling_21,我回去再试一下,可否通过站内信告知您的联系方式?

使用特权

评论回复
6
tearsman520|  楼主 | 2011-5-4 13:59 | 只看该作者
感谢楼上朋友kimfufree的提醒,我准备用示波器看一下完整的波形,作个对比……

使用特权

评论回复
7
古道热肠| | 2011-5-4 14:34 | 只看该作者
附件中有个完整的MP3播放程序,含SD卡驱动。SD卡初始化还是比较容易的,注意细读SD卡协议。

涛行MP3音乐播放器V10_外发.rar

148.06 KB

使用特权

评论回复
8
t.jm| | 2011-5-4 16:05 | 只看该作者
SD卡最容易忽视的问题就是同步的问题,尤其是硬件SPI时,模拟SPI还好些,
开始写了个读SD的驱动,如果被INT打断就出错,而关闭INT读大文件也不出错,
后来发现是同步的问题,因为硬件SPI可以工作在连续模式(前一个发送还没完成就可写第二个数据到
发送缓冲),极易造成无法同步,读到的数据可能是前一个的。
改写了等待响应函数后就好了,也不再怕中断被打断。
我用的是STM8,看到ST的官方SD历程发送命令还是很保守。

使用特权

评论回复
9
tearsman520|  楼主 | 2011-5-5 12:57 | 只看该作者
感谢楼上朋友们的热心帮助。
我需要说明的一点是:
上述同样的程序,我在其他平台上运行过,同样使用SPI硬件接口。
其他平台——例如M051和ATmega16,都能很好的运行初始化程序。
所以,唯一的可能就是我现在用的笙泉MA805-24的8位MCU的SPI接口时序与其他平台有不同。
至于不同在哪里,得借助于示波器。

使用特权

评论回复
10
tearsman520|  楼主 | 2011-5-5 13:05 | 只看该作者
9# t.jm

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

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

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

应该不会是硬件端口设置上的问题,因为发送CMD8的时候,已经读到了SD卡所支持的电平范围。

使用特权

评论回复
11
tearsman520|  楼主 | 2011-5-5 13:07 | 只看该作者
8# 古道热肠

谢谢古道热肠,之前其实我已经仔细阅读过SD协议,而且我不止在一个平台上实现了SD卡的读写。只是在这个平台上遇到了这样的问题,以前的平台移植从来没出现过发送ACMD41总是返回0x01的问题。郁闷了……

使用特权

评论回复
12
ee168| | 2013-2-17 11:08 | 只看该作者
我也遇到过,很难初始化,有时可以有时不可以,,有人说端口要接上拉电阻,但是我是5V-3V的,电阻串并联,不好作上拉,现在画板,怕又遇到这个问题

使用特权

评论回复
13
qchwu| | 2013-6-16 14:08 | 只看该作者
请问楼上的问题解决了吗?为什么有时可以,有时不可以。

使用特权

评论回复
14
sdwys| | 2013-6-19 17:44 | 只看该作者
现在在做SD卡的东西,先学习下。

使用特权

评论回复
15
jekey| | 2013-6-19 20:51 | 只看该作者
SD卡的标准上有复位的处理流程。看程序并没有完全遵守。

使用特权

评论回复
16
lz80650904| | 2013-6-20 17:27 | 只看该作者
MARK

使用特权

评论回复
17
apple| | 2013-6-20 19:15 | 只看该作者
SD卡对时序要求很严,我们用FPGA做4线读写没有成功,不稳定!

使用特权

评论回复
18
笑鸟007| | 2014-7-23 14:57 | 只看该作者
我在读sd卡,也初始化不成功。特来学习学习。

使用特权

评论回复
19
tt朝花夕拾| | 2017-7-26 15:52 | 只看该作者
tearsman520 发表于 2011-5-5 13:07
8# 古道热肠

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

楼主请问,ACMD41返回一直0x01的问题解决了么?
我也遇到了这个问题,可以请教下么?

使用特权

评论回复
20
changle11sdo5| | 2017-8-30 16:10 | 只看该作者
坏了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

22

帖子

0

粉丝