STM32F429第八篇之stm32f4xx_hal_rcc

前言

本文主要介绍STM32F429的HAL库中的RCC用法。本文主要参考资料:

  • Description of STM32F4 HAL and low-layer drivers

更新顺序:

  • 20201026——更新旁路电路使用注释,HSICalibrationValue的取值范围写错,已经更正。

综述

特性

复位之后,芯片的时钟源为HSI。Flash预取缓存,D缓存,I缓存和所有外设全部禁用。此时,只有内部SRAM,FLASH和JTAG还在工作。

  • 在高速总线和低速总线上都没有预分频,这些总线上映射的设备全都以HSI速度在运行。
  • 所有外设的时钟都关闭,除了SRAM和FLASH。
  • 所有GPIO为浮空输入状态,除了JTAG,其用于特定的debug功能。

一旦设备复位,用户软件必须做以下工作:

  • 配置时钟源来驱动系统时钟(SYSCLK)。
  • 配置系统时钟频率和Flash设定。
  • 配置AHB和APB的预分频。
  • 使能将要使用的GPIO。
  • 配置不是SYSCLK驱动的外设时钟源。

为了管理外设读写寄存器,应该考虑到:外设有效使能相比于RCC外设时钟使能有一个延时:

  • 延时取决于外设映射
  • 若外设映射在AHB总线上,延时为2个AHB时钟。
  • 若外设映射在APB总线上,延时为2个APB时钟。

解决方案:
对于AHB和APB外设中,虚拟读取外设已经插入到每一个 __HAL_RCC_PPP_CLK_ENABLE() 宏中。

初始化和反初始化函数

这个模块的函数实现以下功能:

  • 配置内部/外部振荡器:HSE,HSI,LSE,LSI,PLL,CSS,MCO
  • 系统总线时钟:SYSCLK,AHB,APB1,APB2

内部/外部时钟和PLL配置:

  1. 高速内部时钟(HSI),16MHz,工厂校正RC振荡器,可以直接使用或者间接用作系统时钟(SYSCLK)源。
  2. 低速内部时钟(LSI),32kHz,低功耗RC振荡器,可以用于IWDG或者RTC时钟源。
  3. 高速外部时钟(HSE),4-26MHz晶振,可以直接使用或者间接作用系统时钟(SYSCLK)源。另外还可以作为RTC时钟源。
  4. 低速外部时钟(LSE),32kHz晶振,可以用用作RTC时钟源。
  5. PLL,具有两路不同的输出时钟:
    1. 第一路用于产生高速的系统时钟。
    2. 第二路用于产生USB OTG FS,RNG,和SDIO。
  6. 时钟安全系统(CSS),一旦通过宏 __HAL_RCC_CSS_ENABLE() 使能CSS,若HSE时钟发生故障且HSE直接或者间接用作SYSCLK时钟源,则SYSCLK源则自动切回HSI且产生一个中断。这个中断与Cortex-M4 NMI (不可屏蔽中断)异常向量相连。
  7. 时钟输出1(MCO1),在PA8引脚上输出,输出的时钟可以一下时钟源分频:HSI,LSE,HSE,PLL。
  8. 时钟输出2(MCO2),在PC9引脚上输出,输出的时钟可以一下时钟源分频:HSE,PLL,SYSCLK,PLLI2S。

系统,AHB,APB总线时钟配置:

  • 可以作为SYSCLK时钟源的有:
    • HSI
    • HSE
    • PLL
  • AHB时钟(HCLK)从SYSCLK分频而来,可以用于驱动CPU,存储器和映射到AHB上的外设。
  • APB1(PCLK1)和APB2(PCLK2)时钟从AHB时钟分频而来,且用于驱动映射到该总线的外设。
  • 对于STM32F429来说,最高系统时钟频率为180MHz,PLCK2为90MHz,PLCK1为42MHz。

注意:

这部分对应的API有:

外设控制函数

这部分函数用于控制RCC时钟频率。

这部分包含以下API:

函数介绍

HAL_RCC_DeInit

函数原型

void HAL_RCC_DeInit(void)

复位RCC时钟到默认状态。

注意:

  • 默认状态如下所示:
    • HSI打开且用作系统时钟源。
    • HSE和PLL关闭
    • CSS,MCO1和MCO2关闭
    • 所有中断关闭
  • 这个函数并不修改以下配置
    • 外设时钟
    • LSI,LSE,和RTC时钟

HAL_RCC_OscConfig

函数原型

HAL_StatusTypeDef HAL_RCC_OscConfig (RCC_OscInitTypeDef * RCC_OscInitStruct)

通过RCC_OscInitStruct中的参数初始化RCC 晶振的特定参数

注意:

  • 当PLL用作系统时钟的时候,不可以被禁用。
  • 该API不适用于将LSE Bypass转换成LSE On或者将LSE On 转化成LSE Bypass。用户需要首先将转换成LSE OFF,然后在去转换LSE Bypass或者LSE On。
  • 该API不适用于将HSE Bypass转换成HSE On或者将HSE On 转化成HSE Bypass。用户需要首先将转换成HSE OFF,然后在去转换HSE Bypass或者HSE On。

参数

返回值类型

例程

HAL_RCC_ClockConfig

函数原型

HAL_StatusTypeDef HAL_RCC_ClockConfig (RCC_ClkInitTypeDef * RCC_ClkInitStruct, uint32_t FLatency)

根据特定参数RCC_ClkInitStruct来初始化CPU,AHB,APB系统时钟。

注意:

  • CMSIS变量用来存储系统时钟频率,且通过本函数调用的HAL_RCC_GetHCLKFreq()函数来更新数据。
  • 硬件使能HSI用作系统时钟源有以下几种情况:
    • 复位
    • 从STOP或者STANDBY模式中恢复
    • 当CCS使能时,HSE用作系统时钟源的时候出现故障
  • 只有当目标时钟源准备好,才可切换时钟源。若目标时钟源没有准备好就发送切换指令,则实际切换会等到目标时钟源准备好才发生。
  • 根据设备电压,软件正确设置HPRE[3:0]以保证HCLK不超过允许的最大频率。

参数

  • RCC_ClkInitStruct:包含RCC外设配置信息的 RCC_ClkInitTypeDef指针。
  • FLatency:闪存延时,该参数由设备决定。

例程
该函数的使用例程可以参考博客<STM32F429第四篇之跑马灯程序详解>

HAL_RCC_MCOConfig

函数原型

void HAL_RCC_MCOConfig (uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)

选择MCO1或者MCO2的时钟源。

注意:

  • PA8/PC9应该配置成复用功能。

参数:

  • RCC_MCOx:选择配置的引脚。
  • RCC_MCOSource:指定输出的时钟源。
  • RCC_MCODiv:指定输出时钟的分频。

参数的具体定义在文档:stm32f4xx_hal_rcc.h中,具体源程序如下:

/** @defgroup RCC_MCO_Index MCO Index
  * @{
  */
#define RCC_MCO1                         ((uint32_t)0x00000000U)
#define RCC_MCO2                         ((uint32_t)0x00000001U)
/**
  * @}
  */

/** @defgroup RCC_MCO1_Clock_Source MCO1 Clock Source
  * @{
  */
#define RCC_MCO1SOURCE_HSI               ((uint32_t)0x00000000U)
#define RCC_MCO1SOURCE_LSE               RCC_CFGR_MCO1_0
#define RCC_MCO1SOURCE_HSE               RCC_CFGR_MCO1_1
#define RCC_MCO1SOURCE_PLLCLK            RCC_CFGR_MCO1
/**
  * @}
  */

/** @defgroup RCC_MCOx_Clock_Prescaler MCOx Clock Prescaler
  * @{
  */
#define RCC_MCODIV_1                    ((uint32_t)0x00000000U)
#define RCC_MCODIV_2                    RCC_CFGR_MCO1PRE_2
#define RCC_MCODIV_3                    ((uint32_t)RCC_CFGR_MCO1PRE_0 | RCC_CFGR_MCO1PRE_2)
#define RCC_MCODIV_4                    ((uint32_t)RCC_CFGR_MCO1PRE_1 | RCC_CFGR_MCO1PRE_2)
#define RCC_MCODIV_5                    RCC_CFGR_MCO1PRE
/**
  * @}
  */

下方参数定义在stm32f4xx_hal_rcc_ex.h中。

#define RCC_MCO2SOURCE_SYSCLK            ((uint32_t)0x00000000U)
#define RCC_MCO2SOURCE_PLLI2SCLK         RCC_CFGR_MCO2_0
#define RCC_MCO2SOURCE_HSE               RCC_CFGR_MCO2_1
#define RCC_MCO2SOURCE_PLLCLK            RCC_CFGR_MCO2

HAL_RCC_EnableCSS

函数原型

void HAL_RCC_EnableCSS (void )

使能时钟安全系统(CSS)。

注意:

  1. 若捕捉到HSE时钟故障,则晶振会自动进制且产生一个中断通知软件该故障,让MCU采取应急措施。

HAL_RCC_DisableCSS

函数原型

void HAL_RCC_DisableCSS(void)

禁用时钟安全系统(CSS)。

HAL_RCC_GetSysClockFreq

函数原型

uint32_t HAL_RCC_GetSysClockFreq (void )

返回系统时钟(SYSCLK)频率。

注意:

  • 该函数计算系统频率并非芯片的真实系统频率。它是根据预定义值以及所选的时钟源:
    • 若系统时钟源为HSI,函数返回值是基于HSI_VALUE(),该常数预定义在stm32f4xx_hal_conf.h文件,默认值为16MHz,但是真实参数会随着电压和温度变化。
    • 若系统时钟源为HSE,函数返回值是基于HSE_VALUE(),该常数预定义在stm32f4xx_hal_conf.h文件,默认25MHz,用户必须保证该值与实际使用晶振频率一致,否则该函数将计算出错。
    • 若系统时钟源为PLL,函数返回值是基于HSE_VALUE(**)或者HSI_VALUE(*)和PLL配置参数。
  • 当HSE晶体频率不是整数值时,该函数返回值不正确。
  • 该函数可以用于计算外设通信的脉宽或者计算其他的参数。
  • 每当系统时钟改变时,则需要重新调用该函数更新系统时钟值。否则,基于该函数配置将会出错。

HAL_RCC_GetHCLKFreq

函数原型

uint32_t HAL_RCC_GetHCLKFreq (void )

返回HCLK频率。

注意:

  • 每当HCLK频率变化时,该函数需要被调用以更新HCLK值。否则,基于该函数的配置将会出错。
  • 调用该函数时,用以存储系统时钟的CMSIS变量将会被更新。

HAL_RCC_GetPCLK1Freq

函数原型

uint32_t HAL_RCC_GetPCLK1Freq (void )

返回PCLK1的频率。

注意:

  • 每当PCLK1频率变化时,该函数需要被调用以更新HCLK值。否则,基于该函数的配置将会出错。

HAL_RCC_GetPCLK2Freq

函数原型

uint32_t HAL_RCC_GetPCLK2Freq (void )

返回PCLK2的频率

注意:

  • 每当PCLK2频率变化时,该函数需要被调用以更新HCLK值。否则,基于该函数的配置将会出错。

HAL_RCC_GetOscConfig

函数原型

void HAL_RCC_GetOscConfig (RCC_OscInitTypeDef * RCC_OscInitStruct)

根据 RCC配置寄存器获取RCC_OscInitStruct对应的参数。

参数

HAL_RCC_GetClockConfig

函数原型

void HAL_RCC_GetClockConfig (RCC_ClkInitTypeDef * RCC_ClkInitStruct, uint32_t * pFLatency)

根据内部RCC寄存器设置,配置RCC_ClkInitStruct的对应参数。

参数

  • RCC_ClkInitStruct:包含RCC外设配置信息的 RCC_ClkInitTypeDef指针。
  • FLatency:闪存延时,该参数由设备决定。

HAL_RCC_NMI_IRQHandler

函数原型

void HAL_RCC_NMI_IRQHandler (void )

该函数处理RCC CSS中断请求。

注意:

  • 该函数应该在NUM_Handler()处调用。

HAL_RCC_CSSCallback

函数原型

void HAL_RCC_CSSCallback (void )

RCC时钟安全系统中断回调。

结构体

HAL_StatusTypeDef

这个枚举类型定义了HAL的状态。

/** 
  * @brief  HAL Status structures definition  
  */  
typedef enum 
{
  HAL_OK       = 0x00U,
  HAL_ERROR    = 0x01U,
  HAL_BUSY     = 0x02U,
  HAL_TIMEOUT  = 0x03U
} HAL_StatusTypeDef;

RCC_OscInitTypeDef

/**
  * @brief  RCC Internal/External Oscillator (HSE, HSI, LSE and LSI) configuration structure definition  
  */
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;

OscillatorType(振荡器类型)

/** @defgroup RCC_Oscillator_Type Oscillator Type
  * @{
  */
#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)
/**
  * @}
  */

HSEState(HSE状态)

/** @defgroup RCC_HSE_Config HSE Config
  * @{
  */
#define RCC_HSE_OFF                      ((uint8_t)0x00U)
#define RCC_HSE_ON                       ((uint8_t)0x01U)
#define RCC_HSE_BYPASS                   ((uint8_t)0x05U)//当使用有源晶振的时候,选择旁路模式。
/**
  * @}
  */

LSEState(LSE状态)

/** @defgroup RCC_LSE_Config LSE Config
  * @{
  */
#define RCC_LSE_OFF                      ((uint8_t)0x00U)
#define RCC_LSE_ON                       ((uint8_t)0x01U)
#define RCC_LSE_BYPASS                   ((uint8_t)0x05U)
/**
  * @}
  */

HSIState(HSI状态)

/** @defgroup RCC_HSI_Config HSI Config
  * @{
  */
#define RCC_HSI_OFF                      ((uint8_t)0x00U)
#define RCC_HSI_ON                       ((uint8_t)0x01U)

#define RCC_HSICALIBRATION_DEFAULT       ((uint32_t)0x10U)         /* Default HSI calibration trimming value */
/**
  * @}
  */

HSICalibrationValue(HSI校正微调值)
该值的默认值为RCC_HSICALIBRATION_DEFAULT。该参数取值范围为:0x00~0x1F。

LSIState(LSI状态)

/** @defgroup RCC_LSI_Config LSI Config
  * @{
  */
#define RCC_LSI_OFF                      ((uint8_t)0x00U)
#define RCC_LSI_ON                       ((uint8_t)0x01U)
/**
  * @}
  */

PLL(PLL初始化)

/**
  * @brief  RCC PLL configuration structure definition
  */
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 = 0 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 
                            except for STM32F411xE devices where the Min_Data = 192 */

  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, SDIO and RNG clocks.
                            This parameter must be a number between Min_Data = 4 and Max_Data = 15    */ 
}RCC_PLLInitTypeDef;

此定义见于<stm32f4xx_hal_rcc_ex.h>。

其中,PLLState 定义如下:

/** @defgroup RCC_PLL_Config PLL Config
  * @{
  */
#define RCC_PLL_NONE                      ((uint8_t)0x00U)
#define RCC_PLL_OFF                       ((uint8_t)0x01U)
#define RCC_PLL_ON                        ((uint8_t)0x02U)
/**
  * @}
  */

PLLSource 定义如下

/** @defgroup RCC_PLL_Clock_Source PLL Clock Source
  * @{
  */
#define RCC_PLLSOURCE_HSI                RCC_PLLCFGR_PLLSRC_HSI
#define RCC_PLLSOURCE_HSE                RCC_PLLCFGR_PLLSRC_HSE
/**
  * @}
  */

RCC_ClkInitTypeDef

/**
  * @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(时钟类型)

/** @defgroup RCC_System_Clock_Type System Clock Type
  * @{
  */
#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)
/**
  * @}
  */

SYSCLKSource(系统时钟源)

/** @defgroup RCC_System_Clock_Source System Clock Source 
  * @{
  */
#define RCC_SYSCLKSOURCE_HSI             RCC_CFGR_SW_HSI
#define RCC_SYSCLKSOURCE_HSE             RCC_CFGR_SW_HSE
#define RCC_SYSCLKSOURCE_PLLCLK          RCC_CFGR_SW_PLL
#define RCC_SYSCLKSOURCE_PLLRCLK         ((uint32_t)(RCC_CFGR_SW_0 | RCC_CFGR_SW_1))
/**
  * @}
  */

AHBCLKDivider(AHB时钟预分频)

/** @defgroup RCC_AHB_Clock_Source AHB Clock Source
  * @{
  */
#define RCC_SYSCLK_DIV1                  RCC_CFGR_HPRE_DIV1
#define RCC_SYSCLK_DIV2                  RCC_CFGR_HPRE_DIV2
#define RCC_SYSCLK_DIV4                  RCC_CFGR_HPRE_DIV4
#define RCC_SYSCLK_DIV8                  RCC_CFGR_HPRE_DIV8
#define RCC_SYSCLK_DIV16                 RCC_CFGR_HPRE_DIV16
#define RCC_SYSCLK_DIV64                 RCC_CFGR_HPRE_DIV64
#define RCC_SYSCLK_DIV128                RCC_CFGR_HPRE_DIV128
#define RCC_SYSCLK_DIV256                RCC_CFGR_HPRE_DIV256
#define RCC_SYSCLK_DIV512                RCC_CFGR_HPRE_DIV512
/**
  * @}
  */ 

APBCLKDivider(APB1和APB2时钟预分频)

/** @defgroup RCC_APB1_APB2_Clock_Source APB1/APB2 Clock Source
  * @{
  */
#define RCC_HCLK_DIV1                    RCC_CFGR_PPRE1_DIV1
#define RCC_HCLK_DIV2                    RCC_CFGR_PPRE1_DIV2
#define RCC_HCLK_DIV4                    RCC_CFGR_PPRE1_DIV4
#define RCC_HCLK_DIV8                    RCC_CFGR_PPRE1_DIV8
#define RCC_HCLK_DIV16                   RCC_CFGR_PPRE1_DIV16
/**
  * @}
  */ 
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值