打印
[其他ST产品]

初始化SD卡

[复制链接]
770|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
FightingBoy|  楼主 | 2016-12-15 16:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 FightingBoy 于 2016-12-15 18:48 编辑

static uint8_t SD_WriteCmd(uint8_t cmd, uint32_t dat, uint8_t crc)
{         
        uint8_t r1 = 0;
        uint16_t i = 0;

        /* 复位SD卡,取消上次片选 */
        SD_CS_SET;
        SPI2_WriteReadData(0xFF);         //额外提供8个时钟

        SD_CS_CLR;
        while(SPI2_WriteReadData(0xFF) != 0xFF) //等待卡是否准备好
        {
                i++;
                if(i > 100)
                {
                        return 0xFF;                         //等待失败返回
                }
        }

        /* 发送数据 */
        SPI2_WriteReadData(cmd | 0x40);

        SPI2_WriteReadData(dat >> 24);     //发送Dat的最高8位
        SPI2_WriteReadData(dat >> 16);
        SPI2_WriteReadData(dat >> 8);
        SPI2_WriteReadData(dat & 0x00FF);

        SPI2_WriteReadData(crc);
        if(cmd == SD_CMD12)//如果是停止数据传输命令,额外多发一个时钟
        {
                SPI2_WriteReadData(0xFF);
        }

        i = 0;
        do
        {
                r1 = SPI2_WriteReadData(0xFF);        
                i++;
                if(i > 100)
                {
                        return 0xFF;
                }
        }
        while((r1 & 0x80) != 0);   //发送成功的最高位是0,如果返回的数最高位不是0,说明没有收到应答信息

        return r1;
}

/****************************************************************************
* Function Name  : SD_Init
* Description    : 初始化SD卡.
* Input          : None
* Output         : None
* Return         : 0xFF:初始化失败
*                         * 0:初始化成功
****************************************************************************/

int8_t SD_Init(void)
{
        uint8_t r1, buf[4];
        uint16_t i = 0;

        SD_GPIO_Config();
        
        /* 将SD卡通信模式转换为SPI模式,上电默认是用DAT0作数据线 */
        /* 接到CMD0时,CS信号有效,SPI模式启动 */
        for(i=0; i<0x0F; i++)//初始时,先发送至少74个时钟,这个是必须的。
        {
                SPI2_WriteReadData(0xFF);         //发送8*16个
        }

        //当读取到0x01的时候表示初始化成功
        i = 0;
        while(SD_WriteCmd(SD_CMD0, 0, 0x95) != 0x01)
        {
                i++;
                if(i > 100)
                {
                        return 0xFF;        //初始化失败返回0
                }
        }
               
        /* 发送CMD8,检测是否SD V2.0 */
        i = 0;
        do
        {
                i++;
                if(i > 100)        //若是发送超过次数跳出循环管
                {
                        break;
                }
                r1 = SD_WriteCmd(SD_CMD8, 0x01AA, 0x87);
        }
        while(r1 != 0x01); //发送CMD8
        
        if(r1 == 0x01)     //如果CMD8有回应说明是SD V2.0协议
        {
                /* 读取CMD8的返回值,检测是否支持电压 */
                /* 读取CMD8的返回值,检测是否支持电压 */
                for(i=0; i<4; i++)
                {
                        buf = SPI2_WriteReadData(0xFF);
                }
               
                /* 卡电压不支持电压,返回错误 */
                if((buf[2] != 0x01) || (buf[3] != 0xAA))
                {
                        return 0xFF;
                }
               
                /* 初始化SD卡 */
                i = 0;
                do
                {
                        i++;
                        if(i > 100)
                        {
                                return 0xFF;   //返回失败
                        }

                        SD_WriteCmd(SD_CMD55, 0, 0x01);
                        r1 = SD_WriteCmd(SD_CMD41, 0x40000000, 0x01);
                }
                while(r1 != 0);

                /* 检测是SDHC卡还是SD卡 */
                i = 0;
                while(SD_WriteCmd(SD_CMD58, 0, 0x01) != 0)
                {
                        i++;
                        if(i > 100)
                        {
                                SD_TYPE = SD_TYPE_ERR;
                                break;
                        }               
                }

                /* 读取OCR */
                for(i=0; i<4; i++)
                {
                        buf = SPI2_WriteReadData(0xFF);
                }

                if(buf[0] & 0x40)
                {
                        SD_TYPE = SD_TYPE_V2HC;
                }
                else
                {
                        SD_TYPE = SD_TYPE_V2;
                }        
        }
                        
        else //否则就是SD V1.0或者MMC V3
        {
                SD_WriteCmd(SD_CMD55, 0x00, 0x01);
                r1 = SD_WriteCmd(SD_CMD41, 0x00, 0x01);

                if(r1 <= 1)           //对CMD41有回应说明是SD V1.0
                {
                        SD_TYPE = SD_TYPE_V1;         //是V1.0卡
                        i = 0;
                        do
                        {
                                if(i > 100)
                                {
                                        return 0xFF;
                                }

                                SD_WriteCmd(SD_CMD55, 0x00, 0x01);
                                r1 = SD_WriteCmd(SD_CMD41, 0x00, 0x01);        
                        }
                        while(r1 != 0);        
                }

                else                  //没有回应说明是MMC V3
                {
                        SD_TYPE = SD_TYPE_MMC;         //卡类型是MMC卡
                        i = 0;
                        while(SD_WriteCmd(SD_CMD1, 0, 0x01) != 0)
                        {
                                i++;
                                if(i > 100)
                                {
                                        return 0xFF;
                                }
                        }        
                }
        }               

        SD_CS_SET;                   //取消片选
        SPI2_WriteReadData(0xFF);
//        SPI2_SetSpeed(SPI_BaudRatePrescaler_2);

        return 0;

关于我标注出来的那些红字的返回值的判断,为什么判断返回值是那些值。我看过SD卡应答,可是还是不太懂....求懂SD卡的大神教教我啊。。。

沙发
wahahaheihei| | 2016-12-15 17:01 | 只看该作者
返回值就是为了判断是否执行完了这个,如果返回值通过while判断完成后,就执行对应的后面的代码。

使用特权

评论回复
板凳
FightingBoy|  楼主 | 2016-12-15 18:35 | 只看该作者
本帖最后由 FightingBoy 于 2016-12-15 18:43 编辑
wahahaheihei 发表于 2016-12-15 17:01
返回值就是为了判断是否执行完了这个,如果返回值通过while判断完成后,就执行对应的后面的代码。 ...

我想说的那个返回值的的具体值,这个是SD卡的发送命令和初始化的函数。比如第一个那个判断返回值是否是0XFF。如果是0xFF就调出来接着执行下一个。 SD卡中没有0XFF这个命令,在通过SPI不停的发送0xff,如果卡准备好就返回的是0xff,然后执行下边语句。可是为什么发送返回的也是oxff就说明卡准备好了。还有后边的那几句红色的,为什么判断返回值是0x01或者0(这个应该跟SD的应答机制有关,我看了关于SD卡应答,没看出来为什么)。

使用特权

评论回复
地板
huangcunxiake| | 2016-12-15 21:00 | 只看该作者
你想看具体的返回值,编译后可以定位到那个函数原型看看啊。

使用特权

评论回复
5
huangcunxiake| | 2016-12-15 21:01 | 只看该作者
0xFF应该是测试卡的位置是否被清空,通常在内存的表示上,全写1代表的是清空,也就是NULL了,这时候才能写数据,写数据的过程实际上是写0的BIT的过程。

使用特权

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

本版积分规则

6

主题

18

帖子

1

粉丝