一、为什么时钟会这么复杂(相对于51单片机)
51单片机是十几年前使用的,功耗要求低
STM32多时钟:
外设很多,产生干扰,产生功耗大🙌
二、F4时钟树
图中的小梯形是代表选择
小方块
/P
之类,就是分频器,用来除以频率的PLL里面
xN
就是倍频器
2.1. STM325个时钟源: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用于生成高速的系统时钟(最高168MHz )
- 第二个输出PLLQ用于生成USB OTG FS的时钟( 48MHz ),随机数发生器的时钟和SDIO时钟。
- 专用PLL(PLLI2S)用于生成精确时钟,从而在12S接口实现高品质音频性能。
2.2 系统时钟SYSCLK可来源于三个时钟源:
①、HSI振荡器时钟
②、HSE振荡器时钟
③、PLL时钟
2.3 STM32F4时钟信号输出MCO1 ( PA8 )和MCO2(PC9) 。
MCO1:用户可以配置预分频器( 1~5 )向MCO1引脚PA8输出4个不同的时钟源:
- HIS
- LSE
- HSE
- PLL
MCO2:用户可以配置预分频器(1~5)向MCO2引脚PC9输出4个不同的时钟源:
- HSE
- PLL
- SYSCLK
- PLLI2S
MCO最大输出时钟不超过100MHz
4.任何一:个外设在使用之前,必须首先使能其相应的时钟。
三、RCC相关寄存器
typedef struct { __IO uint32_t CR; /*!< RCC clock control register, Address offset: 0x00 */ __IO uint32_t PLLCFGR; /*!< RCC PLL configuration register, Address offset: 0x04 */ __IO uint32_t CFGR; /*!< RCC clock configuration register, Address offset: 0x08 */ __IO uint32_t CIR; /*!< RCC clock interrupt register, Address offset: 0x0C */ __IO uint32_t AHB1RSTR; /*!< RCC AHB1 peripheral reset register, Address offset: 0x10 */ __IO uint32_t AHB2RSTR; /*!< RCC AHB2 peripheral reset register, Address offset: 0x14 */ __IO uint32_t AHB3RSTR; /*!< RCC AHB3 peripheral reset register, Address offset: 0x18 */ uint32_t RESERVED0; /*!< Reserved, 0x1C */ __IO uint32_t APB1RSTR; /*!< RCC APB1 peripheral reset register, Address offset: 0x20 */ __IO uint32_t APB2RSTR; /*!< RCC APB2 peripheral reset register, Address offset: 0x24 */ uint32_t RESERVED1[2]; /*!< Reserved, 0x28-0x2C */ __IO uint32_t AHB1ENR; /*!< RCC AHB1 peripheral clock register, Address offset: 0x30 */ __IO uint32_t AHB2ENR; /*!< RCC AHB2 peripheral clock register, Address offset: 0x34 */ __IO uint32_t AHB3ENR; /*!< RCC AHB3 peripheral clock register, Address offset: 0x38 */ uint32_t RESERVED2; /*!< Reserved, 0x3C */ __IO uint32_t APB1ENR; /*!< RCC APB1 peripheral clock enable register, Address offset: 0x40 */ __IO uint32_t APB2ENR; /*!< RCC APB2 peripheral clock enable register, Address offset: 0x44 */ uint32_t RESERVED3[2]; /*!< Reserved, 0x48-0x4C */ __IO uint32_t AHB1LPENR; /*!< RCC AHB1 peripheral clock enable in low power mode register, Address offset: 0x50 */ __IO uint32_t AHB2LPENR; /*!< RCC AHB2 peripheral clock enable in low power mode register, Address offset: 0x54 */ __IO uint32_t AHB3LPENR; /*!< RCC AHB3 peripheral clock enable in low power mode register, Address offset: 0x58 */ uint32_t RESERVED4; /*!< Reserved, 0x5C */ __IO uint32_t APB1LPENR; /*!< RCC APB1 peripheral clock enable in low power mode register, Address offset: 0x60 */ __IO uint32_t APB2LPENR; /*!< RCC APB2 peripheral clock enable in low power mode register, Address offset: 0x64 */ uint32_t RESERVED5[2]; /*!< Reserved, 0x68-0x6C */ __IO uint32_t BDCR; /*!< RCC Backup domain control register, Address offset: 0x70 */ __IO uint32_t CSR; /*!< RCC clock control & status register, Address offset: 0x74 */ uint32_t RESERVED6[2]; /*!< Reserved, 0x78-0x7C */ __IO uint32_t SSCGR; /*!< RCC spread spectrum clock generation register, Address offset: 0x80 */ __IO uint32_t PLLI2SCFGR; /*!< RCC PLLI2S configuration register, Address offset: 0x84 */ __IO uint32_t PLLSAICFGR; /*!< RCC PLLSAI configuration register, Address offset: 0x88 */ __IO uint32_t DCKCFGR; /*!< RCC Dedicated Clocks configuration register, Address offset: 0x8C */ } RCC_TypeDef;
RCC_CR:使能和就绪
RCC_PLLCFGR:配置PLL里面分频器和倍频器的数值
RCC_CFGR:分频系数和时钟源的选择
3个使能外设AHB1 AHB2 AHB3
APB1和APB2也是外设的时钟使能
四、RCC相关头文件和固件库源文件
stm32fexx_rcc.h
stm32fexx_rcc.c
4.1 时钟使能配置
就是在RCC_CR里面进行配置
4.2 时钟源和时钟相关配置
4.3 外设复位函数
4.4 状态参数获取参数
4.5 RCC中断相关函数
4.6 常用的5个函数(外设)
void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState); void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState); void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);