|
说明:
1、内部和外置时钟配置
2、各种总线时钟配置和获取
3、MCO1和MCO2配置。
==============================================================================
##### RCC规格特性 #####
==============================================================================
1、系统上电复位后,通过内部高速时钟HSI运行(主频64MHz),Flash工作在0等待周期,所有外设除了SRAM, Flash, JTAG 和 PWR,时钟都是关闭的。
这里特别注意SRAM,官方手册里面说的太笼统,这个SRAM到底是指的那个SRAM。关于这个问题,详情看此贴:链接
(1)、AHB和APB总线无分频,所有挂载这两类总线上的外设都是以HSI频率运行。
(2)、所有的GPIO都是模拟模式,除了JTAG相关的几个引脚。
2、系统上电复位后,用户需要完成以下工作
(1)、选择用于驱动系统时钟的时钟源。
(2)、配置系统时钟频率和Flash设置。
(3)、配置分频器。
(3)、使能外设时钟。
(4)、配置外设时钟源,部分外设的时钟可以不来自系统时钟,此时通过配置寄存器RCC_D1CCIPR,RCC_D2CCIP1R,RCC_D2CCIP2R 和 RCC_D3CCIPR 实现。
==============================================================================
##### RCC的局限性 #####
==============================================================================
1、使能了外设时钟后,不能立即操作对应的寄存器,要加延迟。
(1)、不同外设延迟不同。
a、如果是AHB的外设,使能了时钟后,需要等待2个AHB时钟周期才可以操作这个外设的寄存器。
b、如果是APB的外设,使能了时钟后,需要等待2个APB时钟周期才可以操作这个外设的寄存器。
当前HAL库的解决方案是在使能了外设时钟后,在搞一个读操作,算是当做延迟用。
比如下面使能GPIOA的时钟:
- #define __HAL_RCC_GPIOA_CLK_ENABLE() do { \
- __IO uint32_t tmpreg; \
- SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN);\
- /* Delay after an RCC peripheral clock enabling */ \
- tmpreg = READ_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN);\
- UNUSED(tmpreg); \
- } while(0)
复制代码
==============================================================================
##### 初始和复位初始化 #####
==============================================================================
1、本文件提供了配置内核和外设时钟(HSE, HSI, LSE,CSI, LSI,HSI48, PLL, CSS ,MCO)函数,
以及总线时钟(SYSCLK, AHB3, AHB1,AHB2,AHB4,APB3, APB1L, APB1H, APB2, APB4)。

2、内部和外部时钟。
(1)HSI (high-speed internal),高速内部RC振荡器,可以直接或者通过PLL倍频后做系统时钟源。缺点是精度差些,即使经过校准。
(2)CSI (Low-power internal oscillator),低功耗内部RC振荡器,作用同HSI,不过主要用于低功耗。
(3)LSI (low-speed internal),低速内部时钟,主要用于独立看门狗和RTC的时钟源。
(4)HSE (high-speed external),高速外部晶振,可接4 - 48MHz的晶振,可以直接或者通过PLL倍频后做系统时钟源,也可以做RTC的是时钟源。
(5)LSE (low-speed external),低速外部晶振,接32786晶振用于RTC。
(6)CSS (Clock security system),时钟安全系统,一旦使能后,如果HSE启动失败(不管是直接作为系统时钟源还是通过PLL输出后做系统时钟源),系统时钟将切换到HSI。
如果使能了中断的话,将进入不可屏蔽中断NMI。
(7)MCO1 (micro controller clock output),可以在PA8引脚输出HSI, LSE, HSE, PLL1(PLL1_Q)或HSI48 时钟。
(8)MCO2 (micro controller clock output),可以在PC9引脚输出HSE, PLL2(PLL2_P), SYSCLK, LSI, CSI或PLL1(PLL1_P) 时钟。
(9)PLL锁相环,时钟输入来自HSI , HSE 或者CSI
a、主锁相环PLL1,用于给CPU和部分外设提供时钟。
b、专用锁相环PLL2和PLL3,用于给部分外设提供时钟。
3、System, AHB 和 APB总线时钟配置
(1)系统总线时钟源可以来自CSI,HSI,HSE 或 PLL。
(2)AHB总线时钟是通过系统时钟分频产生的,用于给AXI,AHB1,2,3,4和APB1,2,3,4九个总线上的外设提供时钟。另外用户可以通过函数HAL_RCC_GetSysClockFreq获取系统时钟。
(3)所有外设时钟都可以通过系统时钟获取,并且部分外设还支持多个时钟源,比如下面串口1,6
4、函数void HAL_RCC_DeInit(void)
RCC复位函数
(1)复位以下时钟
- HSI 打开作为系统时钟
- HSE, PLL1, PLL2 和 PLL3 关闭
- AHB, APB 总线无分频
- CSS, MCO1 和 MCO2 关闭
- 所有中断关闭
(2)此函数不会修改以下时钟配置
- 外设时钟
- LSI, LSE 和 RTC 时钟。
- void HAL_RCC_DeInit(void)
- {
- /* Set HSION bit */
- SET_BIT(RCC->CR, RCC_CR_HSION);
- /* Reset CFGR register */
- CLEAR_REG(RCC->CFGR);
- /* Reset CSION , CSIKERON, HSEON, HSI48ON, HSECSSON,HSIDIV, PLL1ON, PLL2ON, PLL3ON bits */
- CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_HSIKERON| RCC_CR_HSIDIV| RCC_CR_HSIDIVF| RCC_CR_CSION | RCC_CR_CSIKERON | RCC_CR_HSI48ON \
- |RCC_CR_CSSHSEON | RCC_CR_PLL1ON | RCC_CR_PLL1ON | RCC_CR_PLL2ON | RCC_CR_PLL3ON);
- /* Reset D1CFGR register */
- CLEAR_REG(RCC->D1CFGR);
- /* Reset D2CFGR register */
- CLEAR_REG(RCC->D2CFGR);
- /* Reset D3CFGR register */
- CLEAR_REG(RCC->D3CFGR);
- /* Reset PLLCKSELR register */
- CLEAR_REG(RCC->PLLCKSELR);
- /* Reset PLLCFGR register */
- CLEAR_REG(RCC->PLLCFGR);
- /* Reset PLL1DIVR register */
- CLEAR_REG(RCC->PLL1DIVR);
- /* Reset PLL1FRACR register */
- CLEAR_REG(RCC->PLL1FRACR);
- /* Reset PLL2DIVR register */
- CLEAR_REG(RCC->PLL2DIVR);
- /* Reset PLL2FRACR register */
- CLEAR_REG(RCC->PLL2FRACR);
- /* Reset PLL3DIVR register */
- CLEAR_REG(RCC->PLL3DIVR);
- /* Reset PLL3FRACR register */
- CLEAR_REG(RCC->PLL3FRACR);
- /* Reset HSEBYP bit */
- CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
- /* Disable all interrupts */
- CLEAR_REG(RCC->CICR);
- }
复制代码
5、函数__weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
根据函数形参初始化RCC振荡器
(1)用作系统时钟时,PLL不会被禁用。
(2)LSE Bypass 切换到 LSE On 或者 LSE On切换到 LSE Bypass不支持,用需要先关闭LSE,然后才可以切换到LSE Bypass 或者LSE On
(3)HSE Bypass 切换到 HSE On 或者 LSE On切换到 LSE Bypass不支持,用需要先关闭HSE,然后才可以切换到HSE Bypass 或者HSE On
6、函数HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
根据函数形参初始化CPU, AHB 和 APB
(1)此函数会更新全局变量SystemCoreClock的主频值,并且会再次调用函数HAL_InitTick更新系统滴答时钟,这点要特别注意。
(2)系统上电复位或者从停机、待机模式唤醒后,使用的是HSI作为系统时钟。以防使用HSE直接或者通过PLL输出后做系统时钟时失败(如果使能了CSS)
(3)目标时钟就绪后才可以从当前的时钟源往这个目标时钟源切换,如果目标时钟源没有就绪,就会等待直到时钟源就绪才可以切换。
(4)根据设备的供电范围,必须正确设置D1CPRE[3:0]位的范围,防止超过允许的最大频率。
7、函数void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
配置MCO1和MCO2的输出以及选择的时钟源,通过下面的截图基本就可以说明此函数的作用
8、剩下的函数比较简单
void HAL_RCC_EnableCSS(void)
uint32_t HAL_RCC_GetSysClockFreq(void)
uint32_t HAL_RCC_GetHCLKFreq(void)
uint32_t HAL_RCC_GetPCLK1Freq(void)
uint32_t HAL_RCC_GetPCLK2Freq(void)
void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency)
|
|