OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4113|回复: 3

STM32F4用SPI模式驱动SD卡的问题

[复制链接]

1

主题

3

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2020-11-30
在线时间
3 小时
发表于 2020-12-1 15:45:12 | 显示全部楼层 |阅读模式
1金钱
最近用STM32F4SPI模式读写SD卡时遇到了一些问题:
1.尝试了32G和8G的卡,完全无法驱动,CMD55+ACMD41返回1直到超时,换成CMD1结果也是一样返回1直到超时。换了一个500M的卡之后,能正常驱动,但是偶尔也会有CMD55+ACMD41返回1超时的现象发生。
2.用500M的SD卡测试时,主函数每5s读取一次我个人文件夹下的所有文件名,一开始运行正常,一段时间后就会出现CMD17收不到起始令牌0xfe的情况,导致f_opendir返回1(FR_DISK_ERR)。最后在某一次成功读取后,f_opendir持续返回5(FR_NO_PATH)。感觉应该是前一次CMD17的结果出现了问题。

程序是在正点原子mini板的基础上修改的,部分函数会在串口输出调试信息。硬件使用SPI1(PA5/PA6/PA7),PA8用做片选信号。STM32的对应管脚直接和SD卡座相连,没有外接上拉电阻只在程序里设置了GPIO_PuPd_UP.

串口输出的调试信息如下:
32G和8G卡初始化(用CMD1时的情况,CMD55+ACMD41也是一样)
[15:04:13.067] SD_SendCmd: Send CMD code is 0, R1_retval is 1!
[15:04:13.067] Init_SDCard: CMD0 R1 = 1
[15:04:13.067] SD_SendCmd: Send CMD code is 8, R1_retval is 1!
[15:04:13.067] SD_SendCmd: Send CMD code is 1, R1_retval is 1!
[15:04:13.067] SD_SendCmd: Send CMD code is 1, R1_retval is 1!
......
[15:04:13.615] Init_SDCard: ACMD41 R1 = 1
[15:04:13.615] SD_SendCmd: Send CMD code is 58, R1_retval is 1!

[15:04:13.615] Init_SDCard: R1 Error! Ret = 1

500M卡初始化
[15:01:11.310] SD_SendCmd: Send CMD code is 0, R1_retval is 1!
[15:01:11.310] Init_SDCard: CMD0 R1 = 1
[15:01:11.310] SD_SendCmd: Send CMD code is 8, R1_retval is 1!
[15:01:11.310] SD_SendCmd: Send CMD code is 1, R1_retval is 1!
[15:01:11.310] SD_SendCmd: Send CMD code is 1, R1_retval is 1!
......
[15:01:11.310] SD_SendCmd: Send CMD code is 1, R1_retval is 1!
[15:01:11.310] SD_SendCmd: Send CMD code is 1, R1_retval is 0!
[15:01:11.310] Init_SDCard: ACMD41 R1 = 0
[15:01:11.310] SD_SendCmd: Send CMD code is 58, R1_retval is 0!

[15:01:11.310] Init_SDCard: SD Type = 4
[15:01:11.310] SD_Read: Address of Block to read is 00000000
[15:01:11.310] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:01:11.310] SD_RecvData: Success!
[15:01:11.310] SD_Read: Address of Block to read is 00010800
[15:01:11.310] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:01:11.310] SD_RecvData: Success!

[15:01:11.310] FATFS_Init: Success! FS type = 2

500M卡正常读取数据
[15:02:58.935] SD_Read: Address of Block to read is 0004d800
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] SD_Read: Address of Block to read is 0004da00
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] SD_Read: Address of Block to read is 0004dc00
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] SD_Read: Address of Block to read is 0004de00
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] SD_Read: Address of Block to read is 0004e000
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] SD_Read: Address of Block to read is 0004e200
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] SD_Read: Address of Block to read is 0004e400
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] f_opendir:Retval = 0
[15:02:58.935] SD_Read: Address of Block to read is 0a051800
[15:02:58.935] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:02:58.935] SD_RecvData: Success!
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/687016
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/687057
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/687098
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/688454
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/688712
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/688753
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/688956
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/689159
[15:02:58.935] f_readdir:Retval = 0
[15:02:58.935] 0:ABC/690163
[15:02:58.935] f_readdir:Retval = 0

[15:02:58.935] f_closedir:Retval = 0

500M卡读取数据异常
[15:03:14.137] SD_Read: Address of Block to read is 0004d800
[15:03:14.137] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:03:14.137] SD_GetResponse: No response!
[15:03:14.323] SD_RecvData: Get Response Error!
[15:03:14.323] SD_Read: Recv error! Last retval = 1

[15:03:14.323] f_opendir:Retval = 1

最终出错
[15:03:19.315] SD_Read: Address of Block to read is 0004d800
[15:03:19.315] SD_SendCmd: Send CMD code is 17, R1_retval is 0!
[15:03:19.315] SD_RecvData: Success!
[15:03:19.315] f_opendir:Retval = 5
[15:03:19.315] f_opendir:Retval = 5
[15:03:24.291] f_opendir:Retval = 5
[15:03:29.268] f_opendir:Retval = 5

[15:03:34.244] f_opendir:Retval = 5

最佳答案

查看完整内容[请看2#楼]

终于解决了这个问题!我是用一个FT232串口转USB模块打印调试信息的,然后我就直接把这个模块的电源接到了板子上当作供电电源了。结果测试了一下只有2.6V!切换成直流电源3.3V后SD卡可以正常初始化了,读写目前也正常。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2020-11-30
在线时间
3 小时
 楼主| 发表于 2020-12-1 15:45:13 | 显示全部楼层
终于解决了这个问题!我是用一个FT232串口转USB模块打印调试信息的,然后我就直接把这个模块的电源接到了板子上当作供电电源了。结果测试了一下只有2.6V!切换成直流电源3.3V后SD卡可以正常初始化了,读写目前也正常。
回复

使用道具 举报

1

主题

3

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2020-11-30
在线时间
3 小时
 楼主| 发表于 2020-12-1 17:31:59 | 显示全部楼层
SD卡初始化函数如下:

//初始化SD卡
u8 Init_SDCard(void)
{
        u8 r1;      // 存放SD卡的返回值
        u16 retry;  // 用来进行超时计数
        u8 buf[4];
        u16 i;
       

        Init_SPI();
        SD_SPI_SpeedLow();        //设置到低速模式       

  delay_ms(1000);   //SPI总线初始化延时一会再初始化SD卡

        for(i=0; i<10; i++)SD_WriteByte(0XFF); //发送最少74个脉冲
        retry=200;
        do
        {
                r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
        }
        while((r1!=0X01) && retry--);
        UART_DebugPrintf(0,0,"Init_SDCard: CMD0 R1 = %d\n",r1);
        Flag.SDCard=0;//默认无卡
        if(r1==0X01)
        {
                if(SD_SendCmd(CMD8,0x1AA,0x87)==1)//SD V2.0
                {
                        for(i=0; i<4; i++)buf[i] = SD_ReadByte();        //Get trailing return value of R7 resp
                        if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
                        {
                                retry=2000;
                                do
                                {
//                                        SD_SendCmd(CMD55,0,0X01);        //发送CMD55
//                                        r1=SD_SendCmd(CMD41,0x40000000,0X01);//发送CMD41
                                        r1=SD_SendCmd(CMD1,0x40000000,0X01);//发送CMD1
                                }
                                while(r1&&retry--);
                                UART_DebugPrintf(0,0,"Init_SDCard: ACMD41 R1 = %d\n",r1);
                                if(retry&&SD_SendCmd(CMD58,0,0X01)==0)//鉴别SD2.0卡版本开始
                                {
                                        for(i=0; i<4; i++)buf[i] = SD_ReadByte(); //得到OCR值
                                        if(buf[0]&0x40)Flag.SDCard=SD_TYPE_V2HC;    //检查CCS
                                        else Flag.SDCard=SD_TYPE_V2;
                                }
                        }
                }
                else //SD V1.x/ MMC        V3
                {
//                        SD_SendCmd(CMD55,0,0X01);                //发送CMD55
//                        r1=SD_SendCmd(CMD41,0,0X01);        //发送CMD41
                        r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
                        if(r1<=1)
                        {
                                Flag.SDCard=SD_TYPE_V1;
                                retry=2000;
                                do //等待退出IDLE模式
                                {
//                                        SD_SendCmd(CMD55,0,0X01);        //发送CMD55
//                                        r1=SD_SendCmd(CMD41,0,0X01);//发送CMD41
                                        r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
                                }
                                while(r1&&retry--);
                                UART_DebugPrintf(0,0,"Init_SDCard: ACMD41 R1 = %d\n",r1);
                        }
                        else
                        {
                                Flag.SDCard=SD_TYPE_MMC;//MMC V3
                                retry=2000;
                                do //等待退出IDLE模式
                                {
                                        r1=SD_SendCmd(CMD1,0,0X01);//发送CMD1
                                }
                                while(r1&&retry--);
                                UART_DebugPrintf(0,0,"Init_SDCard: ACMD41 R1 = %d\n",r1);
                        }
                        if(retry==0||SD_SendCmd(CMD16,512,0X01)!=0)Flag.SDCard=SD_TYPE_ERR;//错误的卡
                }
        }
        SD_DisSelect();//取消片选
        SD_SPI_SpeedHigh();//SPI配置为高速模式
       
        if (Flag.SDCard)
                return UART_DebugPrintf(0,0,"Init_SDCard: SD Type = %d\n",Flag.SDCard);
        else if(r1)
                return UART_DebugPrintf(r1,0,"Init_SDCard: R1 Error! Ret = %d\n",r1);
        return UART_DebugPrintf(0xaa,0,"Init_SDCard: Unknown Error");//其他错误
}
回复

使用道具 举报

21

主题

2205

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5141
金钱
5141
注册时间
2014-8-26
在线时间
1317 小时
发表于 2020-12-1 18:40:36 | 显示全部楼层
帮顶。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-14 13:52

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表