网上给别人做网站,十堰网站推广,仿抖音网站开发,不是做有网站都叫jwth目录 1.认识时钟树#xff08;掌握#xff09;1.1什么是时钟#xff1f;1.2认识时钟树#xff08;F1#xff09;1.2.1STM32F103时钟树简图1.2.2STM32CubeMX时钟树#xff08;F103#xff09; 1.3认识时钟树#xff08;F4#xff09;1.3.1F407时钟树1.3.2F429时钟树1.3… 目录 1.认识时钟树掌握1.1什么是时钟1.2认识时钟树F11.2.1STM32F103时钟树简图1.2.2STM32CubeMX时钟树F103 1.3认识时钟树F41.3.1F407时钟树1.3.2F429时钟树1.3.3STM32F4时钟树简图1.3.4STM32CubeMX时钟树F4071.3.5STM32CubeMX时钟树F429 2配置系统时钟掌握2.1外设时钟使能和失能2.2sys_stm32_clock_init 函数F12.2.1HAL_RCC_OscConfig()函数F12.2.2 HAL_RCC_ClockConfig()函数F12.2.3实际配置步骤2.3.1.1.配置HSE_VALUE2.3.2调用SystemInit()函数可选2.3.2调用sys_stm32_clock_init()函数 2.4sys_stm32_clock_init 函数F4/F72.4.1 HAL_RCC_OscConfig()函数2.4.2HAL_RCC_ClockConfig()函数2.4.3Stm32_Clock_Init()函数 3总结了解 1.认识时钟树掌握
1.1什么是时钟 下图的clk是clock时钟的缩写下面的波形可以理解为脉冲信号或者方波。简单来说时钟是具有周期性的脉冲信号最常用的是占空比50%的方波。时钟是单片机的脉搏搞懂时钟走向及关系对单片机使用至关重要
1.2认识时钟树F1 下图是F1系列的时钟树从左侧竖线开始OSC_OUT与OSC_IN是外部高速晶振所连接的引脚OSC32_IN与OSC32_OUT是外部低速晶振所连接的引脚这两个是外部时钟源。STM32还有内部时钟源HSI与LSI。HSE经过PLLXTPRE选择器可以进行1分频或者2分频PLLSRC用于选择内部还是外部时钟经过PLL锁相环倍频得到PLLCLK选择器控制位SW选择SYSCLK的时钟来源。Cortex系统时钟是滴答定时器SysTick定时器时钟频率都为72MhzTIM1和TIM8位高级定时器。 STM32是向外部输出时钟通道MCO是引脚PA8复用得到此项功能时钟来源有四个。 四个时钟源的名字、作用如下字母的简写形式为 Hhigh Llow Sspeed Iinternal Eexternal 振荡器主要分为晶体、陶瓷、RC如果是晶体需要外接晶振陈本提高RC振荡器是芯片内部不需要额外成本但是从稳定、精确度方面来讲外部振荡器比较好。 NIM为不可屏蔽中断在休眠时将AHB总线时钟屏蔽唤醒时需要中断进行唤醒FCLK可以保证睡眠时仍可以产生中断保证芯片内部一部分功能正常使用
1.2.1STM32F103时钟树简图 STM32F103最大系统时钟为72MHzHSE与HSI想要得到72MHz需要经过PLL锁相环进行倍频进入PLL之前也需要进行分频HSI只有2分频HSE可以选择1分频或者2分频。HSI经过2分频为4MHz经过16倍频最大是64MHz即用内部高速时钟最大可达64MHz显然用内部是不满足的基本是不使用。F1系列最常用HSE为8MHz与HSI时钟一致一分频后为8MHz经过9倍频可以得到72MHz。 经过系统时钟来到HCLK也就是AHB总线AHB总线时钟用名字HCLK来表示从SYSCLK到HCLK需要进行分频分频系数不用关心具体的分频系数需要查看寄存器事实上该分频系数一般设置为1HCLK经过两个桥分为APB1和APB2总线分频系数份别为2和1AHB除了能分出APB1和APB2AHB总线上还会挂载外设并且内核时钟也是来自AHB。 低速有LSI与LSELSI可以作为IWDG独立看门狗、RTC实时时钟外设的时钟来源LSE只能作为RTC的时钟源。 时钟源振荡器、锁相环HAL_RCC_OscConfig()控制时钟源是否打开、锁相环PLL的倍频系数 系统时钟、总线HAL_RCC_ClockConfig()配置系统时钟的来源SYSCLK-HCLK-APB1/APB2的分频器。 使能外设时钟__HAL_RCC_PPP_CLK_ENABLE()__HAL_RCC_PPP_CLK_ENABLE()并不是函数是宏PPP代表任意外设例如GPIO、ADC等STM32为了低功耗将所有外设时钟默认是关闭的想要使用哪一个外设就要使能哪一个宏。 扩展外设时钟(RTC/ADC/USB)HAL_RCCEx_PeriphCLKConfig()Ex是拓展Extend的缩写不同系列该函数配置的外设不同。 1.2.2STM32CubeMX时钟树F103 1.3认识时钟树F4
1.3.1F407时钟树 下图是F407时钟树图与F429时钟树不同。图中VCOV是电压C是控制O是振荡器也就是压控振荡器。 时钟来源与F1类似频率有些不同。
1.3.2F429时钟树 1.3.3STM32F4时钟树简图 HSE与HSI都无法直接达到SYSCLK的最大时钟频率需要经过锁相环倍频在此之前需要进行M倍分频F1系列锁相环PLL只是倍频器而F4系列锁相环是先倍频后分频SYSCLK一般经过1分频到达HCLK也就是AHB总线在F4系列中AHB分为AHB1和AHB2甚至AHB3APB1与APB2是AHB1总线经过桥达到的。。LSE是专门为RTC提供的RTC对时钟的精准度要求较高优先选择LSE如果没有LSE则用LSI代替。 时钟源、PLLHAL_RCC_OscConfig()用于配置四个时钟源的开关以及RTC振荡器校准系数的设置。 系统时钟、总线HAL_RCC_ClockConfig()配置系统时钟的来源 使能外设时钟__HAL_RCC_PPP_CLK_ENABLE()PPP可以是任意外设例如GPIO 扩展外设时钟(PLLI2S/ I2S/ LTDC /RTC等)HAL_RCCEx_PeriphCLKConfig() 1.3.4STM32CubeMX时钟树F407 48MHz clocks(MHz)可以作为全速USB(FSUSB)的时钟来源。
1.3.5STM32CubeMX时钟树F429 USB相关例程的系统时钟配置为了让FSUSB全速运行但是系统会超频但是这些超频是允许的。
2配置系统时钟掌握 1.配置HSE_VALUE告诉HAL库外部晶振频率在stm32xxxx_hal_conf.h定义 2.调用SystemInit()函数可选在启动文件中调用 在system_stm32xxxx.c定义 3.选择时钟源配置PLL通过HAL_RCC_OscConfig()函数设置 4.选择系统时钟源配置总线分频器通过HAL_RCC_ClockConfig()函数设置 5.配置扩展外设时钟可选通过HAL_RCCEx_PeriphCLKConfig()函数设置正点原子只在H7系列中设置此项。 3 4 5 正点原子自定义函数 sys_stm32_clock_init() 2.1外设时钟使能和失能 我们要使用某个外设必需先使能该外设时钟 HAL库使能某个外设时钟的方法以使能GPIOA为例如 __HAL_RCC_GPIOA_CLK_ENABLE(); /* 使能 GPIOA 时钟 */HAL库禁止某个外设时钟的方法以使能GPIOA为例如
__HAL_RCC_GPIOA_CLK_DISABLE(); /* 禁止 GPIOA 时钟 */2.2sys_stm32_clock_init 函数F1
2.2.1HAL_RCC_OscConfig()函数F1 HAL_RCC_OscConfig()函数原型如下函数返回值为HAL_StatusTypeDef类型。
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct) 第一个参数OscillatorType是选择4个振荡器中的哪一个HSEState配置HSE打开还是关闭HSI是永远RC振荡器的会随着温度、电压变化而变化不稳定需要有一个校验值。
typedef struct
{ uint32_t OscillatorType; /* 选择需要配置的振荡器 */ uint32_t HSEState; /* HSE 状态 */ uint32_t HSEPredivValue; /* HSE 预分频值 */ uint32_t LSEState; /* LSE 状态 */ uint32_t HSIState; /* HSI状态 */ uint32_t HSICalibrationValue; /* HSI 校准值 */ uint32_t LSIState; /* LSI 状态 */ RCC_PLLInitTypeDef PLL; /* PLL 结构体 */
}RCC_OscInitTypeDef;RCC_PLLInitTypeDef锁相环结构体如下所示PLLState是配置打开锁相环还是关闭倍频系数为2~16倍频。
typedef struct
{ uint32_t PLLState; /* PLL 状态 */ uint32_t PLLSource; /* PLL 时钟源 */ uint32_t PLLMUL; /* PLL 倍频系数 */
}RCC_PLLInitTypeDef;2.2.2 HAL_RCC_ClockConfig()函数F1
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)HCLK是AHB总线时钟PCLK1是APB1总线上时钟PCLK2是APB2总线上时钟。
typedef struct
{ uint32_t ClockType; /* 要配置的时钟SYSCLK/HCLK/PCLK1/PCLK2 */ uint32_t SYSCLKSource; /* 系统时钟源 */ uint32_t AHBCLKDivider; /* AHB 时钟预分频系数 */ uint32_t APB1CLKDivider; /* APB1 时钟预分频系数 */ uint32_t APB2CLKDivider; /* APB2 时钟预分频系数 */
}RCC_ClkInitTypeDef;F1系统时钟为72MhzFLASH时钟来源来自72Mhz但是用72Mhz会超频最大时钟频率为24Mhz用72Mhz的时钟访问FLAH太快需要等待几个周期。
uint32_t FLatency #define FLASH_LATENCY_0 0x00000000U /* FLASH 0个等待周期 */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_0 /* FLASH 1个等待周期 */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_1 /* FLASH 2个等待周期 */实际设置FLASH_ACR寄存器LATENCY位域需要参考《 STM32F10xxx闪存编程参考手册.pdf 》3.1小节
2.2.3实际配置步骤
2.3.1.1.配置HSE_VALUE 在stm32f1xx_hal_conf.h中配置HSE_VALUE的值。
#if !defined (HSE_VALUE)
#if defined(USE_STM3210C_EVAL)
#define HSE_VALUE 25000000U /*! Value of the External oscillator in Hz */
#else
#define HSE_VALUE 8000000U /*! Value of the External oscillator in Hz */
#endif
#endif /* HSE_VALUE */2.3.2调用SystemInit()函数可选 如果不想调用SystemInit()函数可以用分号“;”注释掉。SystemInit()函数在system_stm32f1xx.c中被定义只配置了中断向量表所在的位置并没有配置时钟相关。
; Reset handler
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT __mainIMPORT SystemInitLDR R0, SystemInitBLX R0 LDR R0, __mainBX R0ENDP2.3.2调用sys_stm32_clock_init()函数 sys_stm32_clock_init()函数一般在main函数的前几行被调用主要由函数HAL_RCC_OscConfig和HAL_RCC_ClockConfig组成。选择要配置的时钟时可以用或“|”同时设置多个时钟结构体rcc_osc_init在定义时给到0如果其中结构体未被赋值则默认为0如果不定义可能为随机数赋值为0是为了避免不必要的麻烦。
void sys_stm32_clock_init(uint32_t plln)
{HAL_StatusTypeDef ret HAL_ERROR;RCC_OscInitTypeDef rcc_osc_init {0};RCC_ClkInitTypeDef rcc_clk_init {0};rcc_osc_init.OscillatorType RCC_OSCILLATORTYPE_HSE; /* 选择要配置HSE */rcc_osc_init.HSEState RCC_HSE_ON; /* 打开HSE */rcc_osc_init.HSEPredivValue RCC_HSE_PREDIV_DIV1; /* HSE预分频系数 */rcc_osc_init.PLL.PLLState RCC_PLL_ON; /* 打开PLL */rcc_osc_init.PLL.PLLSource RCC_PLLSOURCE_HSE; /* PLL时钟源选择HSE */rcc_osc_init.PLL.PLLMUL plln; /* PLL倍频系数 */ret HAL_RCC_OscConfig(rcc_osc_init); /* 初始化 */if (ret ! HAL_OK){while (1); /* 时钟初始化失败之后的程序将可能无法正常执行可以在这里加入自己的处理 */}/* 选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2*/rcc_clk_init.ClockType (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);rcc_clk_init.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK; /* 设置系统时钟来自PLL */rcc_clk_init.AHBCLKDivider RCC_SYSCLK_DIV1; /* AHB分频系数为1 */rcc_clk_init.APB1CLKDivider RCC_HCLK_DIV2; /* APB1分频系数为2 */rcc_clk_init.APB2CLKDivider RCC_HCLK_DIV1; /* APB2分频系数为1 */ret HAL_RCC_ClockConfig(rcc_clk_init, FLASH_LATENCY_2); /* 同时设置FLASH延时周期为2WS也就是3个CPU周期。 */if (ret ! HAL_OK){while (1); /* 时钟初始化失败之后的程序将可能无法正常执行可以在这里加入自己的处理 */}
}2.4sys_stm32_clock_init 函数F4/F7 STM32F4/F7系列的sys_stm32_clock_init 函数实现主要由HAL_RCC_OscConfig()函数和HAL_RCC_ClockConfig()函数实现。
2.4.1 HAL_RCC_OscConfig()函数 HAL_RCC_OscConfig()函数的返回值数据类型为HAL_StatusTypeDef 一般无需关心其返回值除非函数在调用过程中出现了问题。
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)OscillatorType是选择外部的哪个振荡器如果要配置多个振荡器则用竖线“|”隔开。
typedef struct
{ uint32_t OscillatorType; /* 选择需要配置的振荡器 */ uint32_t HSEState; /* HSE 状态 */ uint32_t LSEState; /* LSE 状态 */ uint32_t HSIState; /* HSI 状态 */ uint32_t HSICalibrationValue; /* HSI 校准微调值范围0x0~0x1F */ uint32_t LSIState; /* LSI 状态 */ RCC_PLLInitTypeDef PLL; /* PLL 结构体 */
}RCC_OscInitTypeDef;typedef struct
{ uint32_t PLLState; /* PLL 状态 */ uint32_t PLLSource; /* PLL 时钟源 */ uint32_t PLLM; /* PLL 分频系数 M */ uint32_t PLLN; /* PLL 倍频系数 N */ uint32_t PLLP; /* PLL 分频系数 P */ uint32_t PLLQ; /* PLL 分频系数 Q */
}RCC_PLLInitTypeDef; 2.4.2HAL_RCC_ClockConfig()函数
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)typedef struct
{ uint32_t ClockType; /* 要配置的时钟SYSCLK/HCLK/PCLK1/PCLK2 */ uint32_t SYSCLKSource; /* 系统时钟源 */ uint32_t AHBCLKDivider; /* AHB 时钟预分频系数 */ uint32_t APB1CLKDivider; /* APB1 时钟预分频系数 */ uint32_t APB2CLKDivider; /* APB2 时钟预分频系数 */
}RCC_ClkInitTypeDef;配置FLASH的等待周期由于F4/F7系列的系统时钟都比访问FLASH的时钟更快如果要有系统时钟访问FLASH则需要进行等待一共是有0~1516个选择。但是在有些芯片中可能是0~7那么需要查询FLASH_ACR寄存器LATENCY位域
uint32_t FLatency #define FLASH_LATENCY_0 FLASH_ACR_LATENCY_0WS /* FLASH 0个等待周期 */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_1WS /* FLASH 1个等待周期 */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_2WS /* FLASH 2个等待周期 */
...
#define FLASH_LATENCY_15 FLASH_ACR_LATENCY_15WS /* FLASH 15个等待周期 */ 2.4.3Stm32_Clock_Init()函数 下面为F429时钟配置函数__HAL_PWR_VOLTAGESCALING_CONFIG函数设置调压器输出电压来控制最大可达到的时钟。其中等待周期FLASH_LATENCY_5可以根据STM32F4xx中文参考手册中的表7 CPU 时钟 (HCLK) 频率对应的等待周期数来进行配置。
//时钟系统配置函数
//FvcoFs*(plln/pllm);
//SYSCLKFvco/pllpFs*(plln/(pllm*pllp));
//FusbFvco/pllqFs*(plln/(pllm*pllq));//Fvco:VCO频率
//SYSCLK:系统时钟频率
//Fusb:USB,SDIO,RNG等的时钟频率
//Fs:PLL输入时钟频率,可以是HSI,HSE等.
//plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
//pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
//pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
//pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.//外部晶振为25M的时候,推荐值:plln360,pllm25,pllp2,pllq8.
//得到:Fvco25*(360/25)360Mhz
// SYSCLK360/2180Mhz
// Fusb360/845Mhz
//返回值:0,成功;1,失败
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{HAL_StatusTypeDef ret HAL_OK;RCC_OscInitTypeDef RCC_OscInitStructure; RCC_ClkInitTypeDef RCC_ClkInitStructure;__HAL_RCC_PWR_CLK_ENABLE(); //使能PWR时钟//下面这个设置用来设置调压器输出电压级别以便在器件未以最大频率工作//时使性能与功耗实现平衡此功能只有STM32F42xx和STM32F43xx器件有__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//设置调压器输出电压级别1RCC_OscInitStructure.OscillatorTypeRCC_OSCILLATORTYPE_HSE; //时钟源为HSERCC_OscInitStructure.HSEStateRCC_HSE_ON; //打开HSERCC_OscInitStructure.PLL.PLLStateRCC_PLL_ON;//打开PLLRCC_OscInitStructure.PLL.PLLSourceRCC_PLLSOURCE_HSE;//PLL时钟源选择HSERCC_OscInitStructure.PLL.PLLMpllm; //主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.RCC_OscInitStructure.PLL.PLLNplln; //主PLL倍频系数(PLL倍频),取值范围:64~432. RCC_OscInitStructure.PLL.PLLPpllp; //系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)RCC_OscInitStructure.PLL.PLLQpllq; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.retHAL_RCC_OscConfig(RCC_OscInitStructure);//初始化if(ret!HAL_OK) while(1);retHAL_PWREx_EnableOverDrive(); //开启Over-Driver功能if(ret!HAL_OK) while(1);//选中PLL作为系统时钟源并且配置HCLK,PCLK1和PCLK2RCC_ClkInitStructure.ClockType(RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStructure.SYSCLKSourceRCC_SYSCLKSOURCE_PLLCLK;//设置系统时钟时钟源为PLLRCC_ClkInitStructure.AHBCLKDividerRCC_SYSCLK_DIV1;//AHB分频系数为1RCC_ClkInitStructure.APB1CLKDividerRCC_HCLK_DIV4; //APB1分频系数为4RCC_ClkInitStructure.APB2CLKDividerRCC_HCLK_DIV2; //APB2分频系数为2retHAL_RCC_ClockConfig(RCC_ClkInitStructure,FLASH_LATENCY_5);//同时设置FLASH延时周期为5WS也就是6个CPU周期。if(ret!HAL_OK) while(1);
}3总结了解