首页 > 其他分享 >STM32使用cubemx生成代码的系统时钟频率配置

STM32使用cubemx生成代码的系统时钟频率配置

时间:2023-12-25 22:14:55浏览次数:32  
标签:PLL cubemx HSE 函数 STM32 频率 时钟 RCC

STM32使用cubemx生成代码的系统时钟频率配置

当使用cubemx软件自动生成hal库代码时,我们在可视化界面配置的系统时钟频率会通过SystemClock_Config()函数进行配置。如下图所示:

img1

下面则是cubemx中可视化界面配置时钟频率的页面。
使用了外部高速时钟HSE当做时钟源,随后对外部高速时钟进行了1分频;然后进入PLL:选择HSE为PLL时钟源,配置PLL Mul为x9,将系统频率选择为PLLCLK输入,然后得到SYSCLK。SYSCLK通过AHB Prescaler(1分频)得到HCLK时钟,通过APB1 Prescaler(2分频)得到PCLK1时钟,通过APB2 Prescaler(1分频)得到PCLK2时钟。

img2

其实与SystemClock_Config()函数中的配置是一模一样的:

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;   //对外部高速时钟进行1分频
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;              
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;      //选择HSE为PLL时钟源
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;              //配置PLL Mul为x9
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;             //系统频率选择PLLCLK输入
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;                    //AHB   1分频
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;                     //APB1  2分频
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;                     //APB2  1分频

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

系统频率配置过程

首先,STM32上电或复位后,通过汇编代码可以看出来:程序首先会进入SystemInit()函数中做一些初始化的工作,然后再进入main函数中执行。如下图所示:

img3

但是hal库中的SystemInit()函数并没有做配置时钟相关的操作。所以时钟配置只有在main函数中的SystemClock_Config()函数进行。
img4

那么,在STM32上电后到执行SystemClock_Config()函数之前,STM32的运行时钟频率是多少呢?

以STM32F1系列为例,在system_stm32f1xx.c文件中,有具体注释说明,如下图:
img5

  1. 该文件提供了两个函数和一个全局变量
  • SystemInit():初始化系统时钟。
  • SystemCoreClockUpdate():更新SystemCoreClock全局变量。
  • SystemCoreClock:表示系统运行频率。
  1. 当设备(单片机)复位之后,HSI(内部高速时钟,在f1系列为8MHz)会作为系统的时钟源。在"startup_stm32f1xx_xx.s"文件中会在进入main函数之前调用SystemInit()函数去配置系统时钟(显然没有进行配置)。
  2. HSE晶振的默认值设置为了8MHz(根据产品不同,也会设置成25MHz),定义为了HSE_VALUE宏。如果HSE直接或者通过PLL作为了系统时钟源,而且你使用了不同频率的外部晶振,那就必须修改HSE_VALUE的值为当前所用的时钟频率。

所以说,在程序还没执行到SystemClock_Config()函数之前,单片机都是使用内部高速时钟源HSI来作为系统时钟频率的,该HSI的频率会根据单片机的类型不同而有所不同。在执行了SystemClock_Config()函数之后,系统时钟频率便会设置为我们在cubemx中设置的频率。

SystemCoreClock变量

当前系统时钟频率的值保存在了SystemCoreClock全局变量中。可以通过该变量来得到当前系统的运行频率。

system_stm32f1xx.c文件中,定义了SystemCoreClock变量,如下图。但是初始值给了一个16000000。这个初始值其实并不是一开始的系统运行频率。用户可以通过几种方式来更新该变量的值,更新之后才代表真正的系统运行频率。
img6

更新SystemCoreClock变量的三种方法:

  1. 调用SystemCoreClockUpdate()函数。
  2. 调用HAL_RCC_GetHCLKFreq()函数。
  3. 调用HAL_RCC_ClockConfig()函数。

总结

  1. system_stm32xx.c文件中,定义了HSI_VALUEHSE_VALUE两个宏,分别表示该单片机的内部高速时钟频率外部高速时钟频率,两个值一定要与实际的相对应。
  2. 当单片机复位之后,HSI(内部高速时钟,在f1系列为8MHz)会作为系统的时钟源。直到执行了SystemClock_Config()函数,系统时钟频率便会设置为在cubemx中设置的频率。
  3. SystemCoreClock全局变量表示当前系统时钟频率,并不是实时的,需要更新。
  4. SystemCoreClock全局变量会用于配置滴答定时器(SysTick timer)和其他参数。

标签:PLL,cubemx,HSE,函数,STM32,频率,时钟,RCC
From: https://www.cnblogs.com/haostudio/p/17927068.html

相关文章

  • STM32 IIC温湿度传感器(STH45)实验
    SHT45简介.精度ΔRH=±1.0%RH,ΔT=±0.1°C•VDD=1.08V…3.6V•平均电流:0.4μA,空闲电流:80nA•I2CFM、CRC校验和、乘法。I2C地址。•专利保护选项[1]、PTFE膜和可拆卸保护盖•工作范围:0…100%相对湿度,−40…125摄氏度•在冷凝环境中功能齐全•......
  • STM32采集传感器数据通过冒泡排序取稳定值
    STM32采集传感器数据通过冒泡排序取稳定值一、前言在物联网、单片机开发中,经常需要采集各种传感器的数据。比如:温度、湿度、MQ2、MQ3、MQ4等等传感器数据。这些数据采集过程中可能有波动,偶尔不稳定,为了得到稳定的值,我们可以对数据多次采集,进行排序,去掉最大......
  • 【DIY】自制STM32_Arduino
    【DIY】自制STM32_Arduino电路板前言为了在STM32上使用SimpleFOC,使用SimpleFOC的Arduino驱动板,就有了制作STM32_Arduino电路板的想法。使用STM32F103C8T6作为主控,使用立创EDA专业版软件进行电路板设计。功能需求:电路板外形上与Arduino外形相同。使用STM32的定时器TIM输出引......
  • 利用iso镜像制作并使用本地yum源 & 时钟同步
    一、利用iso镜像制作并使用本地yum源步骤一:1、查看操作系统发行版信息:cat/etc/redhat-release2、查看操作系统版本信息cat/proc/version3、查看操作系统内核等信息:uname-a步骤二:获取步骤一中对应系统版本的iso镜像步骤三:系统内执行df-h命令,查看文件系统的磁盘空间占用情况,确认......
  • STM32MP157驱动开发——USB设备驱动
    一、简介  由于USB协议太过庞大和复杂,所以本节只对STM32MP157自带的USB驱动进行使能和测试。详细的USB接口和协议的介绍,可以参考原子哥的资料《USB2.0协议中文版.pdf》和《USB3.0协议中文版.pdf》。  USB全称为UniversalSerialBus,翻译过来就是通用串行总线,用......
  • STM32中滴答定时器的使用并进行ms和us级延时
    STM32中滴答定时器的使用并进行ms和us级延时滴答定时器(Systick)滴答定时器Systick是stm32内核中的一个系统定时器,是属于内核的外设。滴答定时器是一个24位的倒计数定时器,当计数到0时,会从LOAD寄存器中自动重装载定时初值,开始新一轮计数。在core_cm3.h和core_cm4.h头文件中都会......
  • 阅读STM32-hal库代码得到的几点C代码编程规范
    阅读STM32-hal库代码得到的几点C代码编程规范规范一:头文件使用#ifndef_XXX_H#define_XXX_H#ifdef__cplusplusextern"C"{#endif//头文件内容#ifdef__cplusplus}#endif#endif在C++编译环境中,会定义__cplusplus宏,如果在C++代码中需要使用C语言的函数和变......
  • stm32之名缩写词
    缩写名称缩写名称NVIC嵌套向量中断控制器CANCAN通信SysTick系统滴答定时器USBUSB通信RCC复位和时钟控制RTC实时时钟GPIO通用IO口CRCCRC校验AFIO复用IO口PWR电源控制EXTI外部中断BKP备份寄存器TIM定时器IWDG独立看门狗ADC模......
  • STM32 窗口看门狗(WWDG)实验
    ......
  • STM32智能小车 0基础教学
    (文章目录)前言最近发现很多小伙伴都想自己制作一辆属于自己的智能小车,从今天开始我准备从选材料开始教大家如何制作一辆智能小车。一、必备器材选择及其作用1.主控制器STM32首先最重要的就是选择主控制器,因为我们需要通过STM32来控制各个模块协调工作。这里我们选择STM32RC......