固件库应用之使用HSE / HSI配置时钟

编程入门 行业动态 更新时间:2024-10-27 18:29:33

固件库应用之使用HSE / HSI配置<a href=https://www.elefans.com/category/jswz/34/1769919.html style=时钟"/>

固件库应用之使用HSE / HSI配置时钟

文章目录

    • 1.基础知识
    • 1.1 RCC是什么
    • 1.2 RCC框图分析
    • 2. SetSysClockTo72函数分析
    • 3. 编程步骤
    • 4. 使用的固件库函数
    • 4.1 RCC_HSEConfig函数
    • 4.2 RCC_WaitForHSEStartUp函数
    • 4.3 RCC_HCLKConfig函数
    • 4.4 RCC_PCLK2Config函数
    • 4.5 RCC_PCLK1Config 函数
    • 4.6 RCC_PLLConfig 函数
    • 4.7 RCC_PLLCmd 函数
    • 4.8 RCC_GetFlagStatus 函数
    • 4.9 RCC_SYSCLKConfig 函数
    • 4.10 RCC_GetSYSCLKSource 函数
    • 5. 整体代码解析

1.基础知识

1.1 RCC是什么

RCC : reset clock control 复位和时钟控制器。

1.2 RCC框图分析


以上分析会需要较大篇幅,故此处引用他人的回答(记得给他们点赞噢):RCC简介

2. SetSysClockTo72函数分析

SetSysClockTo72函数分析

3. 编程步骤

  1. 开启 HSE/HSI ,并等待 HSE/HSI 稳定
  2. 设置 AHB、APB2、APB1 的预分频因子
  3. 设置 PLL 的时钟来源,和 PLL 的倍频因子,设置各种频率主要就是在这里设置
  4. 开启 PLL,并等待 PLL 稳定
  5. 把 PLLCK 切换为系统时钟 SYSCLK
  6. 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟

此步骤与SetSysClockTo72函数执行步骤基本一致。

4. 使用的固件库函数

4.1 RCC_HSEConfig函数

配置 HSE

/*** @brief  Configures the External High Speed oscillator (HSE).简介:  配置 HSE* @note   HSE can not be stopped if it is used directly or through the PLL as system clock.注意:  如果直接或通过PLL作为系统时钟使用,HSE无法停止。* @param  RCC_HSE: specifies the new state of the HSE.参数1 :RCC_HSE: 指定HSE的新状态。*   This parameter can be one of the following values:此参数可以是以下值之一*     @arg RCC_HSE_OFF: HSE oscillator OFF*     @arg RCC_HSE_ON: HSE oscillator ON*     @arg RCC_HSE_Bypass: HSE oscillator bypassed with external clock通过外部时钟绕过HSE* @retval None*/
void RCC_HSEConfig(uint32_t RCC_HSE)
{/* Check the parameters *//* 检查参数是否有效 */assert_param(IS_RCC_HSE(RCC_HSE));/* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*//* 在配置HSE之前,重置HSEON和HSEBYP位 *//* 此处可参考时钟控制寄存器(RCC_CR) *//* Reset HSEON bit */RCC->CR &= CR_HSEON_Reset;/* Reset HSEBYP bit */RCC->CR &= CR_HSEBYP_Reset;/* Configure HSE (RCC_HSE_OFF is already covered by the code section above) */switch(RCC_HSE){case RCC_HSE_ON:/* Set HSEON bit */RCC->CR |= CR_HSEON_Set;break;case RCC_HSE_Bypass:/* Set HSEBYP and HSEON bits */RCC->CR |= CR_HSEBYP_Set | CR_HSEON_Set;break;default:break;}
}

4.2 RCC_WaitForHSEStartUp函数

等待HSE启动完毕

/*** @brief  Waits for HSE start-up.简介:  等待HSE启动完毕* @param  None* @retval An ErrorStatus enumuration value:返回以下两个值之一* - SUCCESS(启动成功): HSE oscillator is stable and ready to use* - ERROR  (启动失败): HSE oscillator not yet ready*/
ErrorStatus RCC_WaitForHSEStartUp(void)
{__IO uint32_t StartUpCounter = 0;ErrorStatus status = ERROR;FlagStatus HSEStatus = RESET;/* Wait till HSE is ready and if Time out is reached exit */do{HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);StartUpCounter++;  } while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET));if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET){status = SUCCESS;}else{status = ERROR;}  return (status);
}

4.3 RCC_HCLKConfig函数

配置AHB

/*** @brief  Configures the AHB clock (HCLK).简介:  配置 AHB 时钟* @param  RCC_SYSCLK: defines the AHB clock divider. This clock is derived from *   the system clock (SYSCLK).参数:  RCC_SYSCLK:定义AHB时钟分频器。该时钟源于系统时钟(SYSCLK)。*   This parameter can be one of the following values:*     @arg RCC_SYSCLK_Div1: AHB clock = SYSCLK*     @arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2*     @arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4*     @arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8*     @arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16*     @arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64*     @arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128*     @arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256*     @arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512* @retval None*/
void RCC_HCLKConfig(uint32_t RCC_SYSCLK)
{uint32_t tmpreg = 0;/* Check the parameters */assert_param(IS_RCC_HCLK(RCC_SYSCLK));tmpreg = RCC->CFGR;/* Clear HPRE[3:0] bits */tmpreg &= CFGR_HPRE_Reset_Mask;/* Set HPRE[3:0] bits according to RCC_SYSCLK value */tmpreg |= RCC_SYSCLK;/* Store the new value */RCC->CFGR = tmpreg;
}

4.4 RCC_PCLK2Config函数

配置APB2

/*** @brief  Configures the High Speed APB clock (PCLK2).* @param  RCC_HCLK: defines the APB2 clock divider. This clock is derived from *   the AHB clock (HCLK).*   This parameter can be one of the following values:*     @arg RCC_HCLK_Div1: APB2 clock = HCLK*     @arg RCC_HCLK_Div2: APB2 clock = HCLK/2*     @arg RCC_HCLK_Div4: APB2 clock = HCLK/4*     @arg RCC_HCLK_Div8: APB2 clock = HCLK/8*     @arg RCC_HCLK_Div16: APB2 clock = HCLK/16* @retval None*/
void RCC_PCLK2Config(uint32_t RCC_HCLK)
{uint32_t tmpreg = 0;/* Check the parameters */assert_param(IS_RCC_PCLK(RCC_HCLK));tmpreg = RCC->CFGR;/* Clear PPRE2[2:0] bits */tmpreg &= CFGR_PPRE2_Reset_Mask;/* Set PPRE2[2:0] bits according to RCC_HCLK value */tmpreg |= RCC_HCLK << 3;/* Store the new value */RCC->CFGR = tmpreg;
}

4.5 RCC_PCLK1Config 函数

配置APB1

/*** @brief  Configures the Low Speed APB clock (PCLK1).* @param  RCC_HCLK: defines the APB1 clock divider. This clock is derived from *   the AHB clock (HCLK).*   This parameter can be one of the following values:*     @arg RCC_HCLK_Div1: APB1 clock = HCLK*     @arg RCC_HCLK_Div2: APB1 clock = HCLK/2*     @arg RCC_HCLK_Div4: APB1 clock = HCLK/4*     @arg RCC_HCLK_Div8: APB1 clock = HCLK/8*     @arg RCC_HCLK_Div16: APB1 clock = HCLK/16* @retval None*/
void RCC_PCLK1Config(uint32_t RCC_HCLK)
{uint32_t tmpreg = 0;/* Check the parameters */assert_param(IS_RCC_PCLK(RCC_HCLK));tmpreg = RCC->CFGR;/* Clear PPRE1[2:0] bits */tmpreg &= CFGR_PPRE1_Reset_Mask;/* Set PPRE1[2:0] bits according to RCC_HCLK value */tmpreg |= RCC_HCLK;/* Store the new value */RCC->CFGR = tmpreg;
}

4.6 RCC_PLLConfig 函数

配置PLL时钟源和乘法因子。

/*** @brief  Configures the PLL clock source and multiplication factor.简介:  配置PLL时钟源和乘法因子。* @note   This function must be used only when the PLL is disabled.注意:  只有当PLL失能时,才能使用此功能。* @param  RCC_PLLSource: specifies the PLL entry clock source.参数1: RCC_PLLSource: 指定PLL输入时钟源。*   For @b STM32_Connectivity_line_devices or @b STM32_Value_line_devices, *   this parameter can be one of the following values:*     @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 selected as PLL clock entry(PLL = HSI / 2)*     @arg RCC_PLLSource_PREDIV1: PREDIV1 clock selected as PLL clock entry(PLL = HSI / 1)*   For @b other_STM32_devices, this parameter can be one of the following values:*     @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 selected as PLL clock entry (PLL = HSI / 2)*     @arg RCC_PLLSource_HSE_Div1: HSE oscillator clock selected as PLL clock entry(PLL = HSE / 1)*     @arg RCC_PLLSource_HSE_Div2: HSE oscillator clock divided by 2 selected as PLL clock entry(PLL = HSE / 2)* @param  RCC_PLLMul: specifies the PLL multiplication factor.参数2: RCC_PLLMul: 指定PLL乘法因子。*   For @b STM32_Connectivity_line_devices, this parameter can be RCC_PLLMul_x where x:{[4,9], 6_5}形参可以为:RCC_PLLMul_x , x:{[4,9], 6_5}*   For @b other_STM32_devices, this parameter can be RCC_PLLMul_x where x:[2,16]  形参可以为:RCC_PLLMul_x , x:[2,16]* @retval None*/
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul)
{uint32_t tmpreg = 0;/* Check the parameters */assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource));assert_param(IS_RCC_PLL_MUL(RCC_PLLMul));tmpreg = RCC->CFGR;/* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */tmpreg &= CFGR_PLL_Mask;/* Set the PLL configuration bits */tmpreg |= RCC_PLLSource | RCC_PLLMul;/* Store the new value */RCC->CFGR = tmpreg;
}

4.7 RCC_PLLCmd 函数

使能或失能PLL

/*** @brief  Enables or disables the PLL.简介:  使能或失能PLL* @note   The PLL can not be disabled if it is used as system clock.* @param  NewState: new state of the PLL. This parameter can be: ENABLE or DISABLE.* @retval None*/
void RCC_PLLCmd(FunctionalState NewState)
{/* Check the parameters */assert_param(IS_FUNCTIONAL_STATE(NewState));*(__IO uint32_t *) CR_PLLON_BB = (uint32_t)NewState;
}

4.8 RCC_GetFlagStatus 函数

检查是否设置了指定的RCC标志

/*** @brief  Checks whether the specified RCC flag is set or not.简介:  检查是否设置了指定的RCC标志。* @param  RCC_FLAG: specifies the flag to check.* 参数:  RCC_FLAG: 指定要检查的标志。  *   For @b STM32_Connectivity_line_devices, this parameter can be one of the*   following values: 如下参数示例:*     @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready*     @arg RCC_FLAG_HSERDY: HSE oscillator clock ready*     @arg RCC_FLAG_PLLRDY: PLL clock ready*     @arg RCC_FLAG_PLL2RDY: PLL2 clock ready      *     @arg RCC_FLAG_PLL3RDY: PLL3 clock ready                           *     @arg RCC_FLAG_LSERDY: LSE oscillator clock ready*     @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready*     @arg RCC_FLAG_PINRST: Pin reset*     @arg RCC_FLAG_PORRST: POR/PDR reset*     @arg RCC_FLAG_SFTRST: Software reset*     @arg RCC_FLAG_IWDGRST: Independent Watchdog reset*     @arg RCC_FLAG_WWDGRST: Window Watchdog reset*     @arg RCC_FLAG_LPWRRST: Low Power reset* *   For @b other_STM32_devices, this parameter can be one of the following values:        *     @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready*     @arg RCC_FLAG_HSERDY: HSE oscillator clock ready*     @arg RCC_FLAG_PLLRDY: PLL clock ready*     @arg RCC_FLAG_LSERDY: LSE oscillator clock ready*     @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready*     @arg RCC_FLAG_PINRST: Pin reset*     @arg RCC_FLAG_PORRST: POR/PDR reset*     @arg RCC_FLAG_SFTRST: Software reset*     @arg RCC_FLAG_IWDGRST: Independent Watchdog reset*     @arg RCC_FLAG_WWDGRST: Window Watchdog reset*     @arg RCC_FLAG_LPWRRST: Low Power reset*   * @retval The new state of RCC_FLAG (SET or RESET).返回值: RCC_FLAG的新状态( SET or RESET )*/
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)
{uint32_t tmp = 0;uint32_t statusreg = 0;FlagStatus bitstatus = RESET;/* Check the parameters */assert_param(IS_RCC_FLAG(RCC_FLAG));/* Get the RCC register index */tmp = RCC_FLAG >> 5;if (tmp == 1)               /* The flag to check is in CR register */{statusreg = RCC->CR;}else if (tmp == 2)          /* The flag to check is in BDCR register */{statusreg = RCC->BDCR;}else                       /* The flag to check is in CSR register */{statusreg = RCC->CSR;}/* Get the flag position */tmp = RCC_FLAG & FLAG_Mask;if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET){bitstatus = SET;}else{bitstatus = RESET;}/* Return the flag status */return bitstatus;
}

4.9 RCC_SYSCLKConfig 函数

配置系统时钟

/*** @brief  Configures the system clock (SYSCLK).简介:  配置系统时钟 (SYSCLK) 。* @param  RCC_SYSCLKSource: specifies the clock source used as system clock.参数:  RCC_SYSCLKSource: 指定用作系统时钟的时钟源。*   This parameter can be one of the following values:(参数示例如下:)*     @arg 	RCC_SYSCLKSource_HSI			:   HSI selected as system clock*     @arg 	RCC_SYSCLKSource_HSE			:   HSE selected as system clock*     @arg 	RCC_SYSCLKSource_PLLCLK		: 	PLL selected as system clock* @retval None( 无返回值 )*/
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)
{uint32_t tmpreg = 0;/* Check the parameters */assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource));tmpreg = RCC->CFGR;/* Clear SW[1:0] bits */tmpreg &= CFGR_SW_Mask;/* Set SW[1:0] bits according to RCC_SYSCLKSource value */tmpreg |= RCC_SYSCLKSource;/* Store the new value */RCC->CFGR = tmpreg;
}

4.10 RCC_GetSYSCLKSource 函数

查看系统时钟的时钟源

/*** @brief  Returns the clock source used as system clock.简介:  返回用作系统时钟的时钟源。* @param  None( 无参数 )* @retval The clock source used as system clock. 返回用作系统时钟的时钟源* The returned value can be one of the following:( 返回值示例如下:)*     - 0x00: HSI used as system clock*     - 0x04: HSE used as system clock*     - 0x08: PLL used as system clock*/
uint8_t RCC_GetSYSCLKSource(void)
{return ((uint8_t)(RCC->CFGR & CFGR_SWS_Mask));
}

5. 整体代码解析


#define IS_RCC_HSE(HSE) (((HSE) == RCC_HSE_OFF) || ((HSE) == RCC_HSE_ON) || \((HSE) == RCC_HSE_Bypass))/* CR register bit mask */
#define CR_HSEBYP_Reset           ((uint32_t)0xFFFBFFFF)
#define CR_HSEBYP_Set             ((uint32_t)0x00040000)
#define CR_HSEON_Reset            ((uint32_t)0xFFFEFFFF)
#define CR_HSEON_Set              ((uint32_t)0x00010000)
#define CR_HSITRIM_Mask           ((uint32_t)0xFFFFFF07)#define  RCC_CR_HSERDY                       ((uint32_t)0x00020000)        /*!< External High Speed clock ready flag *//* 标志HSE启动完成 */
#define HSE_STARTUP_TIMEOUT   ((uint16_t)0x0500) /*!< Time out for HSE start up *//* HSE启动暂停 */void HSE_SetSysClock(uint32_t pllmul){ __IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0; 45 // 把 RCC 外设初始化成复位状态RCC_DeInit();//使能 HSE,开启外部晶振,野火 STM32F103 系列开发板用的是 8MRCC_HSEConfig(RCC_HSE_ON);// 等待 HSE 启动稳定HSEStartUpStatus = RCC_WaitForHSEStartUp();// 只有 HSE 稳定之后则继续往下执行if (HSEStartUpStatus == SUCCESS) {//-----------------------------------------------------------------//// 这两句是操作 FLASH 闪存用到的,如果不操作 FLASH,这两个注释掉也没影响// 使能 FLASH 预存取缓冲区FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);// SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2// 设置成 2 的时候,SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
// 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
// 0:0 < SYSCLK <= 24M
// 1:24< SYSCLK <= 48M
// 2:48< SYSCLK <= 72M
FLASH_SetLatency(FLASH_Latency_2);
//-----------------------------------------------------------------//// AHB 预分频因子设置为 1 分频,HCLK = SYSCLK
RCC_HCLKConfig(RCC_SYSCLK_Div1);// APB2 预分频因子设置为 1 分频,PCLK2 = HCLK
RCC_PCLK2Config(RCC_HCLK_Div1);// APB1 预分频因子设置为 1 分频,PCLK1 = HCLK/2
RCC_PCLK1Config(RCC_HCLK_Div2);//-----------------设置各种频率主要就是在这里设置-------------------//
// 设置 PLL 时钟来源为 HSE,设置 PLL 倍频因子
// PLLCLK = 8MHz * pllmul
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
//-------------------------------------------------------------//// 开启 PLL
RCC_PLLCmd(ENABLE);// 等待 PLL 稳定
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) { }// 当 PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
while (RCC_GetSYSCLKSource() != 0x08) { }} else {
// 如果 HSE 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
// 当 HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,
// HSI 是内部的高速时钟,8MHZ
while (1) { }}
}

更多推荐

固件库应用之使用HSE / HSI配置时钟

本文发布于:2024-03-05 14:39:43,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1712571.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:时钟   固件   HSE   HSI

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!