我的团队一直在研究一个包含基于标准库的 SD 卡的项目。最近我们决定迁移到 HAL 并开始了。
幸运的是,我们项目的所有部分都尽可能地更改为 HAL,它们运行良好,但我们不知道为什么 SD 卡不能正常运行。
我们没有更改外设的配置时钟,但我们必须将“SDMMC 控制器的时钟频率”在 HAL 中更改为 1.5MHz,而在 STDLibrary 中为 24MHz。因为,根本没用。
此外,我们的客户使用的 SD 卡类型范围很广,它们都还可以,但不是很好。我的意思FR_DISK_ERR
是,在工作期间返回很多,但我们的设备试图获取FR_OK
.
不幸的是,我们总是收到FR_DISK_ERR
一些 SD 卡,而它在我们的 STDLibrary 版本中一直有效。
此外,我们发现如果“f_mount”函数被调用一次,然后你取出 SD 卡并重新放入,它永远不会工作,直到你重置你的微控制器。
我的微控制器是STM32F427VI和SDIO配置如下:
hsd.Instance = SDIO;
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 14;
它适用于 4 位宽的总线。
此外,我的设备时钟为 96MHz,“APB2 外设时钟”为 48MHz。
编辑:
至于重新插入卡 - 当 f_openFR_DISK_ERR
返回时,我通过调用 f_mount 再次进行了初始化。我一直这样做,直到给予,但在这种情况下FR_OK
它从未返回。FR_OK
正如亲爱的 Jacek Ślimok 所说,我意识到 f_mount 第二次没有初始化 SDIO。
因为有一个标志不允许再次调用“SD_initialize”(SD_initialize 函数包括 BSP_SD_Init)。
这是diskio.c的代码:
DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat = RES_OK;
if(disk.is_initialized[pdrv] == 0)
{
disk.is_initialized[pdrv] = 1;
stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
}
return stat;
}
现在我在调用 f_mount 之前使用过,它现在可以正常工作了SD_PowerON
。SD_InitCard
这是一个错误,不是吗?
但其他问题仍然存在。它根本不适用于 24MHz 时钟,并且FR_DISK_ERR
仍然由一些 SD 卡返回。
编辑(2020/02/24):
最后,当我将我的 HAL 库更新到 STM32Cube_FW_F4_V1.24.2 时,它起作用了。但是 HAL 仍然不如标准外设好用。例如,我还不能将“ClockDiv”设置为“0”(24MHz)。它根本不起作用。现在我将“ClockDiv”设置为“1”(16MHz),这对我的项目来说还不够好,但我必须这样做。或者,如果您将 SDCard 拿走并在程序运行时再次插入,您将无法使用 f_mount 初始化 FATFS。它根本行不通。您必须自己重新初始化 SDIO Peripheral。不幸的是,现在我没有时间详细了解我的日程安排。也许在未来。