广州网站建设制作价格,徐州京都网架公司,建行网站用户名是什么,网站蓝色导航栏代码1.STM32时钟 STM32有5个时钟源#xff1a;HSI、HSE、LSI、LSE、PLL HSI是高速内部时钟#xff0c;RC振荡器#xff0c;频率为16MHz#xff0c;精度不高。可以直接作为系统时钟或者用作PLL时钟输入。 HSE是高速外部时钟#xff0c;可接石英/陶瓷谐振器#xff0c;或者接…1.STM32时钟 STM32有5个时钟源HSI、HSE、LSI、LSE、PLL HSI是高速内部时钟RC振荡器频率为16MHz精度不高。可以直接作为系统时钟或者用作PLL时钟输入。 HSE是高速外部时钟可接石英/陶瓷谐振器或者接外部时钟源频率范围为4MHz~26MHz。 LSI是低速内部时钟RC振荡器频率为32kHz提供低功耗时钟。主要供独立看门狗和自动唤醒单元使用。 LSE是低速外部时钟接频率为32.768kHz的石英晶体。RTC PLL为锁相环倍频输出。 STM32F4有三个PLL: 主PLL(PLL)由HSE或者HSI提供时钟信号并具有两个不同的输出时钟。
①第一个输出PLLP用于生成高速的系统时钟最高180MHz
②第二个输出PLLQ为48M时钟用于USB OTG FS时钟随机数发生器的时钟和SDIO时钟。 第一个专用PLL(PLLI2S)生成精确时钟在I2S和SAI1上实现高品质音频 N是用于PLLI2S vco的倍频系数其取值范围是192~432 R是I2S时钟的分频系数其取值范围是2~7 Q是SAI时钟分频系数其取值范围是2~15P没用到。 第二个专用PLL(PLLSAI)同样用于生成精确时钟用于SAI1输入时钟同时还为LCD_TFT接口提供精确时钟。 N是用于PLLSAI vco的倍频系数其取值范围是192~432 Q是SAI时钟分频系数其取值范围是2~15 R是LTDC时钟的分频系数其取值范围是2~7P没用到。 PLLCLKHSE*N/(M * P)可以通过改变N、M、P改变PLLCLK的频率 系统时钟SYSCLK可来源于三个时钟源
①、HSI振荡器时钟
②、HSE振荡器时钟
③、PLL时钟 任何外设在使用之前必须使能相应的时钟 STM32F4时钟信号输出MCO1PA8和MCO2(PC9,MCO1:用户可以配置预分频器1~ 5向MCO1引脚PA8输出4个不同的时钟源HIS、LSE、HSE、PLL。MCO2:用户可以配置预分频器1~ 5向MCO2引脚PC9输出4个不同的时钟源HSE、PLL、SYSCLK、PLLI2S 。MCO最大输出时钟不超过100MHz。 RCC时钟控制相关寄存器定义在stm32f429xx.h中。结构体 RCC_TypeDef;RCC时钟相关定义和函数在文件stm32f4xx_hal_rcc.h、stm32f4xx_hal_rcc.c 。
2.Stm32_Clock_Init
在CORE-startup_stm32f429xx.s文件中找到Reset_Handler这一部分代码作用是引导程序可以看到先执行SystemInit函数再执行main。
; Reset handler
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, SystemInitBLX R0LDR R0, __mainBX R0ENDP; Dummy Exception Handlers (infinite loops which can be modified)可以在USER-system_stm32f7xx.c文件中找到SystemInit函数。其中/* Set HSION bit */可以看出系统初始化之后默认使用HSI作为系统时钟来源因为不知道外部时钟是否准备好。
void SystemInit(void)
{/* FPU settings ------------------------------------------------------------*/#if (__FPU_PRESENT 1) (__FPU_USED 1)SCB-CPACR | ((3UL 10*2)|(3UL 11*2)); /* set CP10 and CP11 Full Access */#endif/* Reset the RCC clock configuration to the default reset state ------------*//* Set HSION bit */RCC-CR | (uint32_t)0x00000001;/* Reset CFGR register */RCC-CFGR 0x00000000;/* Reset HSEON, CSSON and PLLON bits */RCC-CR (uint32_t)0xFEF6FFFF;/* Reset PLLCFGR register */RCC-PLLCFGR 0x24003010;/* Reset HSEBYP bit */RCC-CR (uint32_t)0xFFFBFFFF;/* Disable all interrupts */RCC-CIR 0x00000000;/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAMSCB-VTOR RAMDTCM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#elseSCB-VTOR FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}时钟配置一般步骤
使能PWR时钟调用函数 _HAL_RCC_PWR_CLK_ENABLE()。设置调压器输出电压级别调用函数 _HAL_PWR_VOLTAGESCALING_CONFIG()。选择是否开启Over-Driver功能调用函数HAL_PWREx_EnableOverDrive()。配置时钟源相关参数调用函数HAL_RCC_OscConfig()。配置系统时钟源以及AHB,APB1和APB2的分频系数调用函数HAL_RCC_ClockConfig()。
在STSTEM-sys.c文件中找到Stm32_Clock_Init函数
//时钟设置函数
//FvcoFs*(plln/pllm);
//FsysFvco/pllpFs*(plln/(pllm*pllp));
//FusbFvco/pllqFs*(plln/(pllm*pllq));//Fvco:VCO频率
//Fsys:系统时钟频率
//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的时候,推荐值:plln432,pllm25,pllp2,pllq9.
//得到:Fvco25*(432/25)432Mhz
// Fsys432/2216Mhz
// Fusb432/948Mhz
//返回值: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时钟__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//设置调压器输出电压级别以便在器件未以最大频率工作RCC_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之前的分频)RCC_OscInitStructure.PLL.PLLNplln; //主PLL倍频系数(PLL倍频)RCC_OscInitStructure.PLL.PLLPpllp; //系统时钟的主PLL分频系数(PLL之后的分频)RCC_OscInitStructure.PLL.PLLQpllq; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)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_7);//同时设置FLASH延时周期为7WS也就是8个CPU周期。if(ret!HAL_OK) while(1);
}对于 __HAL_RCC_PWR_CLK_ENABLE();可以在stm32fxx_hal_rcc.h中找到
#define __HAL_RCC_PWR_CLK_ENABLE() do { \__IO uint32_t tmpreg; \SET_BIT(RCC-APB1ENR, RCC_APB1ENR_PWREN);\/* Delay after an RCC peripheral clock enabling */ \tmpreg READ_BIT(RCC-APB1ENR, RCC_APB1ENR_PWREN);\UNUSED(tmpreg); \} while(0) 因为后面设置调压器输出电压级别和选择是否开启Over-Driver功能要用到PWR时钟所以先使能PWR时钟。
对于以下两函数头文件都位于HALLIB-stm32f7xx_hal_rcc.h文件中
配置时钟源相关参数调用函数HAL_RCC_OscConfig()。配置系统时钟源以及AHB,APB1和APB2的分频系数调用函数HAL_RCC_ClockConfig()。
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency);HAL_RCC_OscConfig函数配置时钟源相关参数
选中RCC_OscInitTypeDef找到它的定义
首先根据TYPE判断操作的是哪个时钟源然后再对相应的时钟源配置。
typedef struct
{uint32_t OscillatorType; /*! The oscillators to be configured.This parameter can be a value of ref RCC_Oscillator_Type */uint32_t HSEState; /*! The new state of the HSE.This parameter can be a value of ref RCC_HSE_Config */uint32_t LSEState; /*! The new state of the LSE.This parameter can be a value of ref RCC_LSE_Config */uint32_t HSIState; /*! The new state of the HSI.This parameter can be a value of ref RCC_HSI_Config */uint32_t HSICalibrationValue; /*! The HSI calibration trimming value (default is RCC_HSICALIBRATION_DEFAULT).This parameter must be a number between Min_Data 0x00 and Max_Data 0x1F */uint32_t LSIState; /*! The new state of the LSI.This parameter can be a value of ref RCC_LSI_Config */RCC_PLLInitTypeDef PLL; /*! PLL structure parameters */ }RCC_OscInitTypeDef;其中的RCC_PLLInitTypeDef可以看到里面有对PLL时钟源等一系列配置。
typedef struct
{uint32_t PLLState; /*! The new state of the PLL.This parameter can be a value of ref RCC_PLL_Config */uint32_t PLLSource; /*! RCC_PLLSource: PLL entry clock source.This parameter must be a value of ref RCC_PLL_Clock_Source */ uint32_t PLLM; /*! PLLM: Division factor for PLL VCO input clock.This parameter must be a number between Min_Data 2 and Max_Data 63 */ uint32_t PLLN; /*! PLLN: Multiplication factor for PLL VCO output clock.This parameter must be a number between Min_Data 50 and Max_Data 432 */uint32_t PLLP; /*! PLLP: Division factor for main system clock (SYSCLK).This parameter must be a value of ref RCC_PLLP_Clock_Divider */uint32_t PLLQ; /*! PLLQ: Division factor for OTG FS, SDMMC and RNG clocks.This parameter must be a number between Min_Data 2 and Max_Data 15 */
#if defined (STM32F765xx) || defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx) || defined (STM32F779xx)uint32_t PLLR; /*! PLLR: Division factor for DSI clock.This parameter must be a number between Min_Data 2 and Max_Data 7 */
#endif /* STM32F767xx || STM32F769xx || STM32F777xx || STM32F779xx */ }RCC_PLLInitTypeDef; 调用HAL_RCC_OscConfig函数的方法如下首先设置一下RCC_OscInitTypeDef类型的结构体。 RCC_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之前的分频)RCC_OscInitStructure.PLL.PLLNplln; //主PLL倍频系数(PLL倍频)RCC_OscInitStructure.PLL.PLLPpllp; //系统时钟的主PLL分频系数(PLL之后的分频)RCC_OscInitStructure.PLL.PLLQpllq; //USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频)retHAL_RCC_OscConfig(RCC_OscInitStructure);//初始化如果要配置HSI可以找到RCC_OSCILLATORTYPE_HSE的定义然后发现如下代码块在RCC_OscInitStructure.OscillatorTypeRCC_OSCILLATORTYPE_HSE;代码中将RCC_OSCILLATORTYPE_HSE修改成RCC_OSCILLATORTYPE_HSI即可。
#define RCC_OSCILLATORTYPE_NONE ((uint32_t)0x00000000U)
#define RCC_OSCILLATORTYPE_HSE ((uint32_t)0x00000001U)
#define RCC_OSCILLATORTYPE_HSI ((uint32_t)0x00000002U)
#define RCC_OSCILLATORTYPE_LSE ((uint32_t)0x00000004U)
#define RCC_OSCILLATORTYPE_LSI ((uint32_t)0x00000008U)同样的方法可以配置其他的成员变量。
可以理解main函数的Stm32_Clock_Init可以找到Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz
然后找到Stm32_Clock_Init的定义void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
由于外部晶振是25M现在Stm32_Clock_Init第二个参数pllm是25因此外部晶振是25M经过/M后变成1。然后*n再/p最后得到216M 。 HAL_RCC_ClockConfig配置系统时钟源以及AHB,APB1和APB2的分频系数
然后再看一下HAL_RCC_ClockConfig函数HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
对于第一个参数RCC_ClkInitTypeDef 在HALLIB-stm32f7xx_hal_rcc.h文件中可找到
/*** brief RCC System, AHB and APB busses clock configuration structure definition */
typedef struct
{uint32_t ClockType; /*! The clock to be configured.This parameter can be a value of ref RCC_System_Clock_Type */uint32_t SYSCLKSource; /*! The clock source (SYSCLKS) used as system clock.This parameter can be a value of ref RCC_System_Clock_Source */uint32_t AHBCLKDivider; /*! The AHB clock (HCLK) divider. This clock is derived from the system clock (SYSCLK).This parameter can be a value of ref RCC_AHB_Clock_Source */uint32_t APB1CLKDivider; /*! The APB1 clock (PCLK1) divider. This clock is derived from the AHB clock (HCLK).This parameter can be a value of ref RCC_APB1_APB2_Clock_Source */uint32_t APB2CLKDivider; /*! The APB2 clock (PCLK2) divider. This clock is derived from the AHB clock (HCLK).This parameter can be a value of ref RCC_APB1_APB2_Clock_Source */}RCC_ClkInitTypeDef;对于第一个ClockType它可以选择哪些值也可以在HALLIB-stm32f7xx_hal_rcc.h文件找到
#define RCC_CLOCKTYPE_SYSCLK ((uint32_t)0x00000001U)
#define RCC_CLOCKTYPE_HCLK ((uint32_t)0x00000002U)
#define RCC_CLOCKTYPE_PCLK1 ((uint32_t)0x00000004U)
#define RCC_CLOCKTYPE_PCLK2 ((uint32_t)0x00000008U)对应于时钟系统可以配置SYSCLK、HCLK、PCLK SYSCLK、HCLK、PCLK都是占用不同的位而且HAL_RCC_ClockConfig里面是用if进行判断而不是ifelse所以可用或运算配置时钟。
//选中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_7);//同时设置FLASH延时周期为7WS也就是8个CPU周期。
配置调压器输出级别
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//设置调压器输出电压级别以便在器件未以最大频率工作。
首先找到__HAL_PWR_VOLTAGESCALING_CONFIG的定义可以发现是通过PWR-CR寄存器来配置的。 VOS[1:0] “0x01”时fHCLK 最大值为 144 MHz。 VOS[1:0] “0x10”时fHCLK 最大值为 168 MHz。激活过驱动模式可将其扩展到 180 MHz。 VOS[1:0] “0x11”时fHCLK 最大值为 180 MHz。激活过驱动模式可将其扩展到 216 MHz。
#define __HAL_PWR_VOLTAGESCALING_CONFIG(__REGULATOR__) do { \__IO uint32_t tmpreg; \MODIFY_REG(PWR-CR1, PWR_CR1_VOS, (__REGULATOR__)); \/* Delay after an RCC peripheral clock enabling */ \tmpreg READ_BIT(PWR-CR1, PWR_CR1_VOS); \UNUSED(tmpreg); \} while(0)对于__HAL_PWR_VOLTAGESCALING_CONFIG的参数可以找到
#define PWR_REGULATOR_VOLTAGE_SCALE1 PWR_CR1_VOS
#define PWR_REGULATOR_VOLTAGE_SCALE2 PWR_CR1_VOS_1
#define PWR_REGULATOR_VOLTAGE_SCALE3 PWR_CR1_VOS_0通过 retHAL_PWREx_EnableOverDrive(); //可以开启Over-Driver功能
配置FLASH等待周期
HAL_RCC_ClockConfig还有一个参数uint32_t FLatency可以找到
/** defgroup FLASH_Latency FLASH Latency* {*/
#define FLASH_LATENCY_0 FLASH_ACR_LATENCY_0WS /*! FLASH Zero Latency cycle */
#define FLASH_LATENCY_1 FLASH_ACR_LATENCY_1WS /*! FLASH One Latency cycle */
#define FLASH_LATENCY_2 FLASH_ACR_LATENCY_2WS /*! FLASH Two Latency cycles */
#define FLASH_LATENCY_3 FLASH_ACR_LATENCY_3WS /*! FLASH Three Latency cycles */
#define FLASH_LATENCY_4 FLASH_ACR_LATENCY_4WS /*! FLASH Four Latency cycles */
#define FLASH_LATENCY_5 FLASH_ACR_LATENCY_5WS /*! FLASH Five Latency cycles */
#define FLASH_LATENCY_6 FLASH_ACR_LATENCY_6WS /*! FLASH Six Latency cycles */
#define FLASH_LATENCY_7 FLASH_ACR_LATENCY_7WS /*! FLASH Seven Latency cycles */
#define FLASH_LATENCY_8 FLASH_ACR_LATENCY_8WS /*! FLASH Eight Latency cycles */
#define FLASH_LATENCY_9 FLASH_ACR_LATENCY_9WS /*! FLASH Nine Latency cycles */
#define FLASH_LATENCY_10 FLASH_ACR_LATENCY_10WS /*! FLASH Ten Latency cycles */
#define FLASH_LATENCY_11 FLASH_ACR_LATENCY_11WS /*! FLASH Eleven Latency cycles */
#define FLASH_LATENCY_12 FLASH_ACR_LATENCY_12WS /*! FLASH Twelve Latency cycles */
#define FLASH_LATENCY_13 FLASH_ACR_LATENCY_13WS /*! FLASH Thirteen Latency cycles */
#define FLASH_LATENCY_14 FLASH_ACR_LATENCY_14WS /*! FLASH Fourteen Latency cycles */
#define FLASH_LATENCY_15 FLASH_ACR_LATENCY_15WS /*! FLASH Fifteen Latency cycles */
/*** }*/CPU 时钟 (HCLK) 频率对应的等待周期数是通过一张表对应的 然后就可以写retHAL_RCC_ClockConfig(RCC_ClkInitStructure,FLASH_LATENCY_7);//同时设置FLASH延时周期为7WS也就是8个CPU周期。