STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法

STM32实战项目经验:HAL_RCC_OscConfig中程序卡死问题解决办法


工程环境

  • STM32CUBEIDE
  • STM32F405VG

现象复现

项目中一个是IAP程序,另一个是APP程序,两个程序都是使用STM32CubeIDE生成,当程序跳转到APP中并且执行到函数SystemClock_Config中的时候,在初始化锁相环调用HAL_RCC_OscConfig函数的时候返回HAL_ERROR或者直接卡死在里面。

为什么在IAP中可以初始化通过,但是在APP中却通不过,查阅STM32F4xx参考手册发现这么一段话:
STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法_第1张图片

那么出现这个问题的原因也就清楚了,因为在IAP中已经初始化了PLL,在APP中再次初始化就不成功。

解决办法

我查找ST官方HAL固件库中对重复配置RCC时钟的时候,发现他是这么做的:

  1. 先将时钟源选择为内部时钟
  2. 初始化锁相环
  3. 将时钟源在切换回外部时钟源
  4. 禁用内部高速时钟(可选步骤,如果内部高速时钟不用的话,建议禁掉)

官方代码如下:
STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法_第2张图片

以下是我的示例代码:

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  // 先将时钟源选择为内部时钟
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

  // 初始化锁相环
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 168;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  // 锁相环已经初始化完毕了,将时钟源在切换回外部时钟源
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }

	// 禁用内部高速时钟
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
	RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
	if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	{
	  Error_Handler();
	}
}

通过以上操作后,问题成功解决!

解决F4系列这个问题之后,我又去看F1系列的参考手册,发现:
STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法_第3张图片
同样的也是需要在使能PLL之前完成时钟配置,不过在实际中发现,F1系列的IAP跳转到APP中并没有卡死在HAL_RCC_OscConfig函数中。

还有一个更快捷方便的办法,就是在IAP中不使用PLL,直接使用HSE或HSI的8M晶振作为系统时钟,如下图时钟的配置:
STM32实战项目:HAL_RCC_OscConfig中程序卡死问题解决办法_第4张图片


ends…

你可能感兴趣的:(单片机,RCC,STM32,时钟配置卡死,OscConfig)