f_read 返回FR_OK ,但是读取的数据长度一直是0的现象:打开的是一个较小文件(不足1k)是能正确获取文件大小信息,打开一个较大文件(1.87MB)时返回FR_OK,文件大小信息是0
原因:SDIO时钟频率过低
我使用的是stm32f407vet6 通过sdio方式和SD卡通信
问题发现解决过程:
1、在问题出现前stm32使用的系统时钟频率是168mhz,为使产品符合低功耗要求降低频率至50mhz运行后出现问题,遂猜测和问题原因可能和系统时钟频率有关
2、通过逻辑分析仪检测SDIO 的CLK脚发现 在系统时钟为50MHZ时CLK脚频率为7mhz左右,168mhz 时CLK脚频率为24mhz左右。7mhz 时 f_open无法正确获取文件大小信息, 24mhz 时 f_open正确获取文件大小信息(强烈建议逻辑分析仪的采样频率要保证是被检测频率的10倍才能保证采样结果不失真!)
3、通过cube了解到stm32f407vet6的sdio 的工作频率范围为187khz-24mhz
工作频率计算方法为SDIO_CK = SDIOCLK / [CLKDIV + 2],其中CLKDIV(分频值)我的代码中已经设置为0
50MHZ时时钟配置如下,此时SDIOCLK为14.285mhz, SDIOCLK / [CLKDIV + 2]=7mhz,印证逻辑分析仪的采样结果,由cube时钟树图知上述公式中SDIOCLK的值取决于PLL中的Q值
系统时钟为50mhz时Q为2时超频,Q为3频率还是低
适当提高系统时钟频率为60mhz Q为3 ,f_open 打开文件后文件大小信息正确 增加的功耗在可承受范围, 完美解决问题。
系统时钟配置函数如下 配置时注意和cube中时钟树比对 以防出错!
/*******************************************************************************
函数功能 : 系统时钟设置
输 入 : PLL_OR_HSE-- 1-PLL 倍频 0--HSE 8MHZ
RCC_SYSCLK_Divx 系统时钟分频 注意对照CUBE里配置 时钟树末端不得出现小数
@arg RCC_SYSCLK_Div1: AHB clock = SYSCLK
@arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2
@arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4
@arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8
@arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16
@arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64
@arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128
@arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256
@arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512
输 出 : 无
使用方法 :
系统上电时、在功耗模式切换时调用 PLL_OR_HSE为1时使用PLL倍频 PLL_OR_HSE为0时不使用PLL 系统时钟为8MHZ
更改分频数时注意对照CUBE里配置 时钟树末端不得出现小数
STM32F407vet6--PCLK1最大42mhz 注意分频数
STM32F407vet6--PCLK2最大84mhz 注意分频数
*******************************************************************************/
void RCC_Configuration(uint8_t PLL_OR_HSE, uint32_t RCC_SYSCLK_Divx)
{
//----------使用外部RC晶振-----------
RCC_DeInit(); // 初始化为缺省值
RCC_HSEConfig(RCC_HSE_ON); // 使能外部的高速时钟
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET); // 等待外部高速时钟使能就绪
RCC_HCLKConfig(RCC_SYSCLK_Divx); // HCLK = SYSCLK/Divx
RCC_PCLK2Config(RCC_HCLK_Div1); // PCLK2 = HCLK /2 36Mhz STM32F407vet6--PCLK2最大84mhz 注意分频数
if (PLL_OR_HSE) // PLL
{
RCC_PCLK1Config(RCC_HCLK_Div2); // PCLK1 = HCLK/2 36Mhz STM32F407vet6--PCLK1最大42mhz 注意分频数
RCC_PLLConfig(RCC_PLLSource_HSE, 4, 60, 2, 3); // PLLCLK = 8MHZ * 7 =72MHZ
RCC_PLLCmd(ENABLE); // Enable PLLCLK
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}; // Wait till PLLCLK is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // Select PLL as system clock
while (RCC_GetSYSCLKSource() != 0x08)
; // Wait till PLL is used as system clock source
}
else
{
RCC_PCLK1Config(RCC_HCLK_Div1); // PCLK1 = HCLK/2 2Mhz
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET)
{
}; // Wait till PLLCLK is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); // Select PLL as system clock
while (RCC_GetSYSCLKSource() != 0x04)
; // Wait till PLL is used as system clock source
* be one of the following:
* - 0x00: HSI used as system clock
* - 0x04: HSE used as system clock
* - 0x08: PLL used as system clock
}
}
至于SDIO低频时FATFS不能正常工作,高频时正常工作真正原因,我猜测是由于SDIO通信速率低时需要正确读取文件信息的时间过长,超过了f_open函数执行的超时时间,f_open函数便退出并返回了文件大小信息为0字节。FATFS的超时机制如何实现我并没有再深入研究,有兴趣的道友可自行验证下~