HAL时钟系统的再配置

STM32时钟系统:HSI到HSE的切换与错误处理
本文详细介绍了在STM32F401项目中,如何从HSI内部振荡器切换到HSE外部振荡器,并在HSE停止时通过看门狗恢复初始状态。过程中涉及STM32的时钟树结构,HSI到HSE的切换步骤,外部时钟频率检测以及错误处理机制。在HSE出现问题时,系统能通过错误处理函数进行软复位,重新启动。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

背景:我自己的项目,需要应用到STM32F401,启动时候需要从HSI RC内部振荡器工作,等外部HSE工作后,再切换到外部。有时候HSE会停止。这时候还能够回到初始状态作。


一、STM32时钟树

STM32F4的时钟系统如下图:
在这里插入图片描述

二、HSI切换到HSE

1.初始化

由于切换到HSE后,如果HSE停止,系统将不工作,所以需要增加看门狗来回倒初始状态。并且RCC->CR中的RCC_CR_HSERDY状态会出错,所以更需要看门狗来处理。
代码如下:

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM1_Init();
  MX_TIM3_Init();
  MX_IWDG_Init();
  /* USER CODE BEGIN 2 */
  printf("====================================================\r\n");
  printf("System Freq : %dMHz\r\n",HAL_RCC_GetHCLKFreq()/1000000);
  printf("====================================================\r\n");

  printf("Opening HSE......\r\n");  
  SET_BIT(RCC->CR, RCC_CR_HSEON);
  printf("Check HSE......\r\n");
  while(READ_BIT(RCC->CR, RCC_CR_HSERDY) == RESET)
  {
	HAL_Delay(50);
	HAL_IWDG_Refresh(&hiwdg);
  }
  printf("Check HSE is ready.\r\n");  


2.外部时钟频率检测

代码如下:

  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_5);
  printf("OPEN MCO DIV_5......\r\n");

打开MCO,5分频输出到TIM1做计数器。来计算当前的频率。


3.切换到HSE

切换HSE,如果直接 SystemClockHSE_Config()会出错。需要先HAL_RCC_DeInit();
代码如下:

  HAL_RCC_DeInit();
  SystemClockHSE_Config(); 

4.错误处理

当HSE停止的时候有一定的概率会出错。HSI的初始化也不成功。进入到Error_Handler();

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

Error_Handler的处理代码如下,否则就死在这里,因为看门狗这个时候还没有初始化。只能软复位重新再来。当HSE恢复的时候一切就正常了。在我的 应用中是如此的。对于错误的具体表现就是RCC_CR_HSERDY一直是Ready状态。即使没有打开HSE。并且也无法清除状态,复位也不能恢复,只有掉电或者HSE恢复才能清掉这个状态。

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {	  
	__disable_irq();
	__set_FAULTMASK(1);
	CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
	CLEAR_BIT(RCC->CR, RCC_CR_HSEON);
	MX_USART1_UART_Init();
	printf("No sclk signal input, pls reset local slave chip.......\r\n");
	printf("The system will restart\r\n");
	NVIC_SystemReset();	
  }
  /* USER CODE END Error_Handler_Debug */
}

总结

HSI和HSE切换,这样的应用比较少。所以记录一下,希望有所帮助。有问题可以留言讨论一下。

<think>好的,我现在需要帮助用户配置HAL系统的时钟频率到72MHz。首先,我应该回顾一下STM32时钟系统结构,特别是HAL库中的配置方法。根据引用[3],STM32F429的时钟配置涉及到多个时钟源,比如外部高速时钟(HSE)、内部高速时钟(HSI)、锁相环(PLL)等。用户的目标是达到72MHz的系统时钟,这通常需要通过PLL倍频实现。 首先,我需要确认用户使用的是哪款STM32型号,但假设是常见的STM32F1系列,因为72MHz是它们的典型主频。例如,STM32F103系列。在这种情况下,默认的外部时钟(HSE)通常是8MHz,如引用[1]提到的。通过PLL进行倍频,比如将8MHz乘以9得到72MHz。 接下来,配置步骤可能包括以下几步:启用HSE,配置PLL的倍频系数,选择PLL作为系统时钟源,并设置AHB、APB分频器。引用[1]中的代码示例可能涉及启用PLL并选择它为系统时钟源,但需要具体查看HAL库的函数。例如,在SystemInit函数中,可能会设置FLASH延迟,配置预取缓冲区,然后通过RCC_CFGR寄存器设置分频系数和PLL参数。 另外,引用[4]提到了系统嘀嗒时钟的配置HAL_SYSTICK_Config的参数计算,这关系到系统时钟的分频,确保SysTick中断的正确频率。这部分也需要正确配置,但主要关注系统时钟到72MHz的步骤。 用户的问题可能出现在分频设置上,比如HCLK如果设置为64MHz,可能是因为APB分频器设置错误,如引用[2]提到的疑问。因此,需要确保AHB分频器设置为1,APB1分频器设置为2,APB2分频器设置为1,这样APB1的时钟不会超过36MHz,而APB2则可以达到72MHz。 另外,HAL库中的时钟配置通常通过HAL_RCC_OscConfig和HAL_RCC_ClockConfig函数完成。需要正确设置PLL参数,比如PLLM、PLLN和PLLP等,具体数值根据不同的STM32系列有所不同。例如,在STM32F1中,PLL的倍频因子是HSE乘以9,所以需要设置PLLM为8MHz输入,PLLN为9倍频,然后选择PLL作为系统时钟源。 可能还需要注意FLASH的等待状态,因为更高的时钟频率需要调整FLASH的访问时间,如引用[3]中提到的SystemInit函数可能设置了预取缓冲区和等待状态。 最后,验证时钟配置是否正确,可以通过检查系统时钟变量SystemCoreClock的值,或者使用示波器测量相关时钟输出引脚。</think>在STM32HAL库中将系统时钟配置为72MHz需要以下步骤,以外部时钟HSE 8MHz为例: ### 步骤1:启用HSE时钟 通过RCC寄存器启用外部高速时钟: ```c RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; // 启用HSE ``` ### 步骤2:配置PLL参数 设置PLL的倍频系数为9倍频: $$ \text{PLL输出频率} = HSE \times 9 = 8\text{MHz} \times 9 = 72\text{MHz} $$ ```c RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 8; // HSE输入分频(8MHz/8=1MHz) RCC_OscInitStruct.PLL.PLLN = 72; // PLL倍频系数(1MHz×72=72MHz) RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; // 主PLL分频(仅部分型号需要) HAL_RCC_OscConfig(&RCC_OscInitStruct); // 应用PLL配置[^3] ``` ### 步骤3:配置系统时钟总线 设置AHB/APB分频器确保总线频率不超限: ```c RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 选择PLL为系统时钟源 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // HCLK=72MHz RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; // APB1=36MHz RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // APB2=72MHz HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2); // 设置FLASH等待周期[^1] ``` ### 验证配置 1. 检查`SystemCoreClock`变量是否更新为72MHz[^4]。 2. 通过调试器查看RCC寄存器的值,确认SYSCLK源为PLL且频率正确。 ### 注意事项 - 若HSE频率非8MHz,需调整`PLLM`和`PLLN`的值。 - APB1总线最大频率通常为36MHz(某些型号为42MHz),需遵守分频规则[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值