HAL库使用的外部晶振频率是多少?

发布于:2024-07-30 ⋅ 阅读:(148) ⋅ 点赞:(0)

HAL库默认使用内部RC,因为它不想让编程人员接触和硬件有关的东西,因此HAL库没有使用外部晶振,但提供了相关配置函数。使用外部晶振是由后期设计工程模板的的人自己写了一个SystemClock_Config()来实现的。看到SystemClock_Config()没有带“HAL_”前缀,你就明白了,它不是来自HAL库。PY32F003F18P和STM32F334R8的HALL库,就是如此,其它CPU不知道是否是如此,为了体现HAL库的优势,HAL库不会自己否定自己,因此,它不会去写这种函数,好比写议论文一样,为了支持自己的观点,啥都不要了。举例说明如下:

1、PY32F003F18P的官方模板是这么切换时钟的,如下:

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

  /* 振荡器配置 */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

/* 选择RCC振荡器为HSE */
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;  /* 开启HSI */
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV4;  /* 4分频 */
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_8MHz;

/* 配置HSI输出时钟为8MHz */
  RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* 开启HSE */
  RCC_OscInitStruct.HSEFreq = RCC_HSE_16_24MHz;  /* HSE晶振工作频率16M~32M */
  RCC_OscInitStruct.LSIState = RCC_LSI_OFF;  /* 准备关闭LSI */

  /* 配置振荡器 */
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /* 时钟源配置 */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; /* 选择配置时钟 HCLK,SYSCLK,PCLK1 */
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;

/* 准备选择HSE作为系统时钟 */
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;     /* AHB时钟 1分频 */
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;      /* APB时钟 1分频 */
  /* 配置时钟源 */
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}


void Error_Handler(void)
{
  /* 无限循环 */
  while (1)
  {
  }
}

HALL库提供的部分函数如下:

HAL_RCC_OscConfig()

HAL_RCC_ClockConfig()

下面的是工程模板提供的:

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE              ((uint32_t)24000000) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */

2、STM32F334R8的官方模板是这么切换时钟的,如下:

//函数功能:系统时钟使用HSE+PLL
void SystemClock_Config_HSE(void)
{
   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the CPU, AHB and APB busses clocks 
  */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;//RCC_OSCILLATORTYPE_HSE=0x00000001U
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;//RCC_HSE_ON=0x00010000
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;

//设置RCC->CFGR寄存器的PLLXTPRE=0,HSE分频器设置为1
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;//RCC_HSI_ON=0x00000001
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

//设置RCC->CFGR寄存器的SW=2,设置PLL作为系统时钟
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    //设置RCC->CFGR寄存器的PLLSRC=1,PLL使用HSE作为输入时钟源
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
    //设置RCC->CFGR寄存器的PLLMUL[3:0]=0100B,即PLL乘法因子为6
    //由于PLL乘法因子为6,外部晶振频率为12MHz,因此当AHB分频器为1时,系统时钟就是72MHz

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {//设置PLL时钟进入工作状态
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks 
  */

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

//使用PLL作为系统时钟源
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;//AHB分频器设置为1
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;

//APB1分频器设置为2,则PCLK1=36MHz,TIM2CLK,TIM3CLK,TIM6CLK,TIM7CLK为72MHz
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

//APB2分频器设置为1,则PCLK2=72MHz,TIM1CLK,TIM15CLK,TIM16CLK,TIM17CLK为72MHz

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {//根据RCC_ClkInitStruct结构变量初始化系统时钟
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_HRTIM1|RCC_PERIPHCLK_USART1;
  PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
  PeriphClkInit.Hrtim1ClockSelection = RCC_HRTIM1CLK_PLLCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }

    SystemCoreClockUpdate();//根据系统时钟开关状态更新SystemCoreClock的值
}
void Error_Handler(void)
{
    while(1);
}

HALL库提供的部分函数如下:

HAL_RCC_OscConfig()
HAL_RCC_ClockConfig()
HAL_RCCEx_PeriphCLKConfig()

下面是工程模板的:

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE    ((uint32_t)12000000)

/*!< Value of the External oscillator in Hz */
    //外部晶振12000000Hz

#endif /* HSE_VALUE */

SystemCoreClockUpdate()

总结:

从上面可以看出:

PY32F003F18P的官方模板是24MHz;

STM32F334R8的官方模板是12MHz;

3、HAL是通用的吗?

HAL库无法做到互相替换,但函数名是一样的,实现的功能大体是一个意思。每个HAL库都要去了解,不是说一通百通,但大体上,是那个意思。

为什么HAL不写全,而让工程模板去实现,是因为各个厂家的CPU是不同的,为了体现兼容性强的特点,它没法去写。。所以,当有人问HALL库使用外部晶振的频率是多少,我很无语,因为这是和工程模板有关的。标准库和CPU有关,所以就不会存在这种问题

如果没有工程模板,自己实现,太难了。千万不要举一反三,CPU变了,HAL库没法保证外部晶振的频率是一样的。


网站公告

今日签到

点亮在社区的每一天
去签到