STM32F427 写入SD卡返回成功实际没写入

本文探讨了STM32F427在使用FATFS时遇到的SD卡写入问题,包括时钟配置、文件写入与读取测试代码及常见故障排除方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

芯片:STM32F427

芯片配置软件:STM32CubeMx 5.6.0

配置了FATFS

卡时钟(SDIO_CK ):每个时钟周期在命令和数据线上传输 1 位命令或数据。对于多媒体卡 V3.31 协议,时钟频率可以在 0MHz 至 20MHz 间变化;对于多媒体卡 V4.0/4.2 协议,时钟频率可以在 0MHz 至 48MHz 间变化;对于 SD 或 SD I/O 卡,时钟频率可以在 0MHz 至 25MHz间变化。
SDIO适配器时钟( SDIOCLK ):该时钟用于驱动 SDIO 适配器,其频率等于 AHB 总线频率( HCLK ),并用于产生 SDIO_CK 时钟。
AHB 总线接口时钟( HCLK/2 ):该时钟用于驱动 SDIO 的 AHB 总线接口,其频率为HCLK/2 。
前面提到,我们的SD 卡时钟( SDIO_CK ),根据卡的不同,可能有好几个区间,这就涉及到时钟频率的设置, SDIO_CK 与 SDIOCLK 的关系为:
SDIO_CK=SDIOCLK/(2+CLKDIV)
其中,SDIOCLK 为 HCLK ,一般是 72Mhz(F103系列),而 CLKDIV 则是分配系数,可以通过 SDIO
的 SDIO_CLKCR 寄存器进行设置(确保 SDIO_CK 不超过卡的最大操作频率)。
这里要提醒大家,在SD 卡刚刚初始化的时候,其时钟频率( SDIO_CK )是不能超过 400Khz的,
否则可能无法完成初始化。在初始化以后,就可以设置时钟频率到最大了(但不可超过 SD卡的最大操作时钟频率)。

按上面的公式配置了SD:

测试代码:

    // mount SD卡
    retSD = f_mount(&SDFatFS, SDPath, 1);
    if(retSD)
    {
        printf("mount error : %d \r\n",retSD);
        return -1;
    }
    else
    {
        printf("mount sucess!!! \r\n");
    }
int8_t SDWrite_test()
{
    static char testFileName[] = "test.txt";
    int32_t testVal = 123456;
    // 创建并写入文件
    FIL fl;
    retSD = f_open(&fl, testFileName, FA_CREATE_ALWAYS | FA_WRITE);
    if(FR_OK == retSD)
    {
        UINT bw = 0;
        if(FR_OK != f_write(&fl, (void*)&testVal , sizeof(int32_t ), &bw))
        {
            f_close(&fl);
            printf("f_write file(%s) error : %d\r\n", testFileName, retSD);
            return -1;
        }
        retSD = f_close(&fl);
        if(retSD)
        {
            printf("close(%s) error!!! %d\r\n", testFileName, retSD);
        }
        else
        {
            //printf("close(%s) sucess!!! \r\n", testFileName);
        }
        return 0;
    }
    else
    {
        printf("w open file(%s) error : %d\r\n", testFileName, retSD);
        return -1;
    }
}
// 读取文件测试
int8_t SDRead_test()
{
    static char testFileName[] = "test.txt";
    int32_t testVal = 0;
    FIL fl;
    // 打开文件
    retSD = f_open(&fl, testFileName, FA_READ);
    if(retSD)
    {
        printf("open file(%s) error : %d\r\n", testFileName, retSD);
        return -1;
    }
    else
    {
        //printf("open file(%s) sucess\r\n", testFileName);
    }
    if(f_size(&fl) != sizeof(int32_t))
    {
        f_close(&fl);
        printf("file(%s) len(%d) err\r\n", testFileName, (uint32_t)f_size(&fl));
        return -1;
    }
    uint32_t bytesread = 0;       // 读文件计数
    // 读取文件
    retSD = f_read(&fl, &testVal , sizeof(int32_t), (UINT*)&bytesread);
    if(retSD)
    {
        f_close(&fl);
        printf("read(%s) error!!! %d\r\n", testFileName, retSD);
        return -1;
    }
    else
    {
        //printf("read(%s) sucess!!! \r\n", testFileName);
    }
    // 关闭文件
    retSD = f_close(&fl);
    if(retSD)
    {
        printf("close(%s) error!!! %d\r\n", testFileName, retSD);
    }
    else
    {
        //printf("close(%s) sucess!!! \r\n", testFileName);
    }
    
    printf("testVal :%d \r\n", testVal);

    return 0;
}

写入SD卡返回了成功,但是当我执行SD卡读取代码时发现,文件不存在,读取失败了,取了SD卡放到电脑也发现文件没创建

如果写入文件后立刻读取失败则重写文件,一般写第二次就会成功,查看了SD卡的优先级,基本已经都是最高的

之后尝试调整SDIOCLK clock devide factor的值,基本上SD有问题都是这个问题,尝试了加大和减小这个值,发现设置为0-2都可以一次写入文件成功

按公式,如果设置SDIOCLK clock devide factor为0,SD卡的时钟频率就应该会超了才对,然而发现SD卡是能正常的,还是说是高速模式,没搞清楚


在使用STM32CubeMX 6.12.0和STM32F427ZGT6芯片时,发现SDIO中Mode选择为SD 4 bits Wide bus时,f_mount会返回错误3,对比以前的工程发现,同样的SD 4 bits Wide bus配置STM32F427VGT6芯片生成的工程代码不一样,改成hsd.Init.BusWide = SDIO_BUS_WIDE_1B;就能正常mount SD卡

所以使用STM32CubeMX配置SDIO为SDIO_BUS_WIDE_4B时,需要将MX_SDIO_SD_Init中的hsd.Init.BusWide = SDIO_BUS_WIDE_4B改为hsd.Init.BusWide = SDIO_BUS_WIDE_1B,否则f_mount会报错误3,可以在USER CODE BEGIN SDIO_Init 2区域内添加hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
    在使用STM32CubeMX配置SDIO为SDIO_BUS_WIDE_4B后,工程内部会自动调用HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B),如果配置为SDIO_BUS_WIDE_1B则不会
    所以应该需要使用SDIO_BUS_WIDE_1B初始化,然后再配置为SDIO_BUS_WIDE_4B

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值