硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4001|回复: 1
收起左侧

[HAL学习笔记] HAL库源文件stm32h7xx_hal_rcc.c学习笔记(2018-07-23 V1.0)

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106771
QQ
发表于 2018-7-23 15:56:45 | 显示全部楼层 |阅读模式
说明:
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的时钟:
  1. #define __HAL_RCC_GPIOA_CLK_ENABLE()   do { \
  2.                                         __IO uint32_t tmpreg; \
  3.                                         SET_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN);\
  4.                                         /* Delay after an RCC peripheral clock enabling */ \
  5.                                         tmpreg = READ_BIT(RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN);\
  6.                                         UNUSED(tmpreg); \
  7.                                        } 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,用于给部分外设提供时钟。
QQ截图20180723155520.png

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
QQ截图20180723155052.png

4、函数void HAL_RCC_DeInit(void)
     RCC复位函数
(1)复位以下时钟
- HSI 打开作为系统时钟
- HSE, PLL1, PLL2 和 PLL3 关闭
- AHB, APB 总线无分频
- CSS, MCO1 和 MCO2 关闭
- 所有中断关闭

(2)此函数不会修改以下时钟配置
- 外设时钟
- LSI, LSE 和 RTC 时钟。

  1. void HAL_RCC_DeInit(void)
  2. {
  3.   /* Set HSION bit */
  4.   SET_BIT(RCC->CR, RCC_CR_HSION);

  5.   /* Reset CFGR register */
  6.   CLEAR_REG(RCC->CFGR);

  7.   /* Reset CSION , CSIKERON, HSEON, HSI48ON, HSECSSON,HSIDIV, PLL1ON, PLL2ON, PLL3ON bits */
  8.   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  \
  9.   |RCC_CR_CSSHSEON | RCC_CR_PLL1ON | RCC_CR_PLL1ON | RCC_CR_PLL2ON | RCC_CR_PLL3ON);

  10.   /* Reset D1CFGR register */
  11.   CLEAR_REG(RCC->D1CFGR);

  12.   /* Reset D2CFGR register */
  13.   CLEAR_REG(RCC->D2CFGR);

  14.   /* Reset D3CFGR register */
  15.   CLEAR_REG(RCC->D3CFGR);

  16.   /* Reset PLLCKSELR register */
  17.   CLEAR_REG(RCC->PLLCKSELR);

  18.   /* Reset PLLCFGR register */
  19.   CLEAR_REG(RCC->PLLCFGR);

  20.   /* Reset PLL1DIVR register */
  21.   CLEAR_REG(RCC->PLL1DIVR);

  22.   /* Reset PLL1FRACR register */
  23.   CLEAR_REG(RCC->PLL1FRACR);

  24.   /* Reset PLL2DIVR register */
  25.   CLEAR_REG(RCC->PLL2DIVR);

  26.   /* Reset PLL2FRACR register */
  27.   CLEAR_REG(RCC->PLL2FRACR);

  28.   /* Reset PLL3DIVR register */
  29.   CLEAR_REG(RCC->PLL3DIVR);

  30.   /* Reset PLL3FRACR register */
  31.   CLEAR_REG(RCC->PLL3FRACR);

  32.   /* Reset HSEBYP bit */
  33.   CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);

  34.   /* Disable all interrupts */
  35.   CLEAR_REG(RCC->CICR);
  36. }
复制代码


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
QQ截图20180723163400.png


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]位的范围,防止超过允许的最大频率。
QQ截图20180723170830.png

7、函数void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)

配置MCO1和MCO2的输出以及选择的时钟源,通过下面的截图基本就可以说明此函数的作用
QQ截图20180723172649.png

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)

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106771
QQ
 楼主| 发表于 2018-7-23 15:59:32 | 显示全部楼层
占二楼,方便以后升级更新。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-6 01:15 , Processed in 0.296569 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表