OpenEdv-开源电子网

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

STM32F3 SPI通信驱动TF卡问题

[复制链接]

5

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
122
金钱
122
注册时间
2022-1-1
在线时间
35 小时
发表于 2025-2-22 15:28:39 | 显示全部楼层 |阅读模式
2金钱
现在做一个小项目,主控芯片为STM32F3系列,存储方式采用SD卡存储,通信方式SPI(F3系列没有SDIO),由于板子空间有限,采用TF卡的卡槽,用的卡是立创买的4GB TF卡,现在初始化可以通过,但是我的数据量级别大概是2GB,用正点原子MINI开发板的SPI驱动SD卡程序,用u8 sd_write_disk(u8 *pbuf, u32 saddr, u32 cnt)函数多扇区写,但是一直会卡在 if ( (t & 0x1F) != 0x05)   {   return SD_ERROR;  }这里面导致多扇区写不能成功,所以打算固定cnt = 1,每次调用这个函数,让其一个扇区一个扇区的写,但是测试过程中,每写一个扇区还得加几ms的延时才能勉强算成功写入,而且再同样方式调用读函数u8 sd_read_disk(u8 *pbuf, u32 saddr, u32 cnt),也读不出来,请问大神们这大概是哪方面的问题啊,卡还是程序呢?
下面附官方程序:
u8 sd_write_disk(u8 *pbuf, u32 saddr, u32 cnt)
{
    u8 retry = 20; /* 发送ACMD经常失败, 多尝试几次 */
    u8 res;
    long long lsaddr = saddr;

    if (sd_type != SD_TYPE_V2HC)
    {
        lsaddr <<= 9;   /* 转换为字节地址 */
    }

    if (cnt == 1)
    {
        res = sd_send_cmd(CMD24, lsaddr);   /* 读命令 */

        if (res == 0)   /* 指令发送成功 */
        {
            res = sd_send_block(pbuf, 0xFE);/* 写512个字节 */
        }
    }
    else
    {
        if (sd_type != SD_TYPE_MMC)
        {
            do
            {
                sd_send_cmd(ACMD23, cnt);   /* 发送 ACMD23 指令 */
            }while(res && retry--);
        }

        res = sd_send_cmd(CMD25, lsaddr);   /* 连续读命令 */

        if (res == 0)
        {
            do
            {
                res = sd_send_block(pbuf, 0xFC);    /* 写入一个block, 512个字节 */
                pbuf += 512;
            } while (--cnt && res == 0);

            res = sd_send_block(0, 0xFD);   /* 写入一个block, 512个字节 */
        }
    }

    sd_deselect();/* 取消片选 */
    return res;
}
u8 sd_send_block(u8 *buf, u8 cmd)
{
    u16 t;

    if (sd_wait_ready())            /* 等待ready */
    {
        return SD_ERROR;
    }

    sd_spi_read_write_byte(cmd);    /* 发送 CMD */

    if (cmd != 0XFD)                /* 不是结束指令 */
    {
        for (t = 0; t < 512; t++)
        {
            sd_spi_read_write_byte(buf[t]); /* 发送数据 */
        }

        sd_spi_read_write_byte(0xFF);       /* 忽略crc */
        sd_spi_read_write_byte(0xFF);

        t = sd_spi_read_write_byte(0xFF);   /* 接收响应 */

        if ((t & 0x1F) != 0x05)             /* 数据包没有被接收 */
        {
            return SD_ERROR;
        }
    }

    return SD_OK;   /* 写入成功 */
}

u8 sd_read_disk(u8 *pbuf, u32 saddr, u32 cnt)
{
    u8 res;
    long long lsaddr = saddr;

    if (sd_type != SD_TYPE_V2HC)
    {
        lsaddr <<= 9;   /* 转换为字节地址 */
    }

    if (cnt == 1)
    {
        res = sd_send_cmd(CMD17, lsaddr);       /* 读命令 */

        if (res == 0)   /* 指令发送成功 */
        {
            res = sd_receive_data(pbuf, 512);   /* 接收512个字节 */
        }
    }
    else
    {
        res = sd_send_cmd(CMD18, lsaddr);       /* 连续读命令 */

        do
        {
            res = sd_receive_data(pbuf, 512);   /* 接收512个字节 */
            pbuf += 512;
        } while (--cnt && res == 0);

        sd_send_cmd(CMD12, 0);  /* 发送停止命令 */
    }

    sd_deselect();  /* 取消片选 */
    return res;
}

u8 sd_receive_data(u8 *buf, u16 len)
{
    if (sd_get_response(0xFE))   /* 等待SD卡发回数据起始令牌0xFE */
    {
        return SD_ERROR;
    }

    while (len--)   /* 开始接收数据 */
    {
        *buf = sd_spi_read_write_byte(0xFF);
        buf++;
    }

    /* 下面是2个伪CRC(dummy CRC) */
    sd_spi_read_write_byte(0xFF);
    sd_spi_read_write_byte(0xFF);

    return SD_OK;   /* 读取成功 */
}



下面是我的测试代码:
    while(1)
    {

                if(USART1_RX_STA&0x8000)
                {                       
                        if(USART1_RX_BUF[0]==0xAA&&USART1_RX_BUF[1]==0x01)
                        {
                                LED1_ON;
                                //写入0xFF
                                for(a=0; a<512; a++)
                                {
                                        writeBuffer[a] = 0xFF;
                                }
                                for(b=0;b<1000;b++)
                                {
                                        if(sd_write_disk(writeBuffer,b,1) == 0)//如果等于0,证明写完
                                        {
                                                LED3_ON;
                                                RS485_TX_HI;
                                                USART_SendData(USART1,0xFF);
                                                while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);       
                                                RS485_TX_LO;
                                        }
                                        delay_ms(10);                                       
                                }
                                //写入数据
                                for(a=0; a<512; a++)
                                {
                                        writeBuffer[a] = a;
                                }
                                for(b=0;b<1000;b++)
                                {
                                        if(sd_write_disk(writeBuffer,b,1) == 0)//如果等于0,证明写完
                                        {
                                                LED3_ON;
                                                RS485_TX_HI;
                                                USART_SendData(USART1,0x22);
                                                while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);       
                                                RS485_TX_LO;
                                        }
                                        delay_ms(10);                                       
                                }
                               
                                LED1_OFF;
                                LED3_OFF;                                                                                               
                        }
                        if(USART1_RX_BUF[0]==0xAA&&USART1_RX_BUF[1]==0x02)
                        {                                                               
                                LED2_ON;
                                for(a=0;a<1000;a++)
                                {
                                        if(sd_read_disk(readBuffer, a, 1) == 0)
                                        {
                                                RS485_TX_HI;
                                                for(b=0;b<512;b++)
                                                {
                                                        USART_SendData(USART1,readBuffer[b]);
                                                        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);                 
                                                }
                                                RS485_TX_LO;
                                        }
                                        delay_ms(10);                                       
                                }
                                LED2_OFF;                                                                                                                                                       
                        }                                                                                                                       
                        USART1_RX_STA=0;
                }       
        }






正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

137

帖子

0

精华

高级会员

Rank: 4

积分
547
金钱
547
注册时间
2018-11-2
在线时间
113 小时
发表于 2025-2-28 14:23:06 | 显示全部楼层
2G的数据量,你存了些啥
回复

使用道具 举报

5

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
122
金钱
122
注册时间
2022-1-1
在线时间
35 小时
 楼主| 发表于 2025-3-6 19:59:48 | 显示全部楼层
qinlu123 发表于 2025-2-28 14:23
2G的数据量,你存了些啥

传感器数据,传感器快30个了
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-4-6 13:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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