STM32-(26):RCC内部结构与原理分析

上一篇:STM32-(25):PWM实验 下一篇:STM32-(27):RTC实时时钟

RCC(Reset Clock Controller)复位与时钟控制器

这个在STM32中起到一个举足轻重的作用,所有的外设都由时钟来控制。通过控制时钟的开关、速度来控制外设的开关、运行速度来控制整体功耗。特别是对手持式设备、利用电池供电的设备都对功耗要求比较高。

一、时钟系统与内部结构

在这里插入图片描述
四个驱动单元
Cortex-M3内核ICode(地址)总线(I-bus).DCode(数据)总线(D-bus).和系统总线(S-bus)
GP-DMA(通用DMA)

三个被动单元
内部SRAM
内部闪存存储器
AHB到APB的桥(AHB2APBx),它连接所有的APB设备,APB2的时钟比APB1快。

在这里插入图片描述
简析: 首先,输入 OSC_OUT/OSC_IN,这是一路晶振,OSC32_IN/OSC32_OUT,第二路晶振,我们先看上面这一路,上面这一路是外部时钟(HSE OSC),外部时钟进来,也可先除以2(二分频)进来,进来之后又是一个选择开关,这个选择开关还有一路,HSI RC(内部时钟RC振荡器),内部时钟也可以直接进入后方,可以看到内部时钟是8Mhz,不管是内部时钟还是外部时钟,往后进入 PLL (锁相环),锁相环起一个倍频器的作用,输出一个倍频之后的 PLLCLK,又遇到一个选择开关,这个选择开关还有一路输入 ,HSE OSC(外部晶振)直接过来的,所以一共有三个时钟,可以通过设置选择某一路过来,过来之后得到一个SYSCLK(系统时钟),系统时钟往后可以为 AHB总线提供时钟源,AHB Prescaler 是一个预分频器,再往后分三路,第一路跑到 CPU 内核(内核用,72Mhz);第二路走到 APB1,提供给 APB1 控制的这些外设(最高36Mhz),如果这里还要用到通用定时器,这里还有一个 Multiplier(乘法器),目的是使定时器的时钟更快;第三路到 APB2,类似于 APB1,最高速度快一些,另外还有一个 ADC,由于ADC不需要太快的速度,所以还需要经过分频(ADC Prescaler);PLL 有一路没有走后方,直接下来供给 USB 外设使用,频率为48MHz(这个频率比较特殊,所以单独拉出来一路)

另外一路:OSC32_IN/OSC32_OUT,接的是外部 32.768KHz的晶振,简写成OSC32,为什么是32.768KHz ? 因为这个频率可以产生精确的秒信号(暂不深究)。这个晶振信号进来,经过 LSE OSC (外部低速时钟),进来一个32.768KHz的波,另外下方有一个低速的内部RC振荡器,大概40KHz,同时都进入后方的选择开关,这个选择开关的第三路输入是由上方提供的,三路输入,经选择开关选择,提供RTC时钟(实时时钟),当32.768这一路失效,可以选择另外两路,也能提供相对精确的时钟。

时钟监视系统 CSS:监视 HSE OSC 时钟,这个外部时钟会提供给 CPU 使用,当检测到HSE OSC 失效,则立即切换至 HSI RC

MCO接口:芯片上有一个专门的引脚叫MCO,可以通过选择开关来选择,可以通过示波器测量 SYSCLK、HSI、HSE、PLLCLK各个波形,根据脉冲波形来判断时钟是否正常。除此之外,也可以通过这个接口给其他器件充当晶振。即既能作为内部诊断,也能为外部提供晶振,并且提供晶振的时候还有多种选择。

为什么要这么多时钟?内部时钟?外部时钟?
有内部高速(HSI RC)、外部高速(HSE DSC)、外部低速(LSE DSC)、内部低速(LSI RC),首先高速、低速满足的外设是不一样的,比如低速满足 RTC 时钟和看门狗,至于外部内部,是当外部失效的时候也可以使用内部的振荡器,可以工作,只不过接了外部的晶振,时钟更加精确而已

时钟源

时钟是STM32的脉搏,是驱动源。使用任何一个外设都必须打开相应的时钟。这样的好处就是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果。

STM32的时钟可以由以下4个时钟源提供:
1、 HSI:高速内部时钟信号stm32单片机内带的时钟(8M频率)精度较差
2、 HSE:高速外部时钟信号精度高来源(1)HSE外部晶体/陶瓷谐振器(晶振)(2)HSE用户外部时钟
3、 LSE:低速外部晶体32.768kHz主要提供一个精确的时钟源一般作为RTC时钟使用
4、 LSI:低速内部时钟,主要提供给看门狗

stm32将时钟信号(例如HSE)经过分频或倍频(PLL)后,得到系统时钟,系统时钟经过分频,产生外设所使用的时钟。

RCC 程序流程

设罝时钟流程:
1、 将RCC寄存器重新设罝为默认值 RCC_Delnit
2、 打开夕卜部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON);
3、 等待外部髙速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp();
4、 设置AHB时钟 RCC_HCLKConfig;
5、 设罝高速APB时钟 RCC_PCLK2Config;
6、 设置低速速APB时钟 RCC_PCLK1Config
7、 设置PLL RCC_PLLConfig
8、 打开PLL RCC_PLLCmd(ENABLE);
9、 等待PLL工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) = RESET)
10、设置系统时钟 RCC_SYSCLKConfig
11、判断是否PLL是系统时钟 while[RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟 RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd ()

代码

RCC_Configuration

void RCC_Configuration(void) 
{
	//=============================== 使用内部RC晶振 ===================================
    /*   
	RCC_HSICmd(ENABLE);//使能内部高速晶振 ;
 	RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//选择内部高速时钟作为系统时钟SYSCLOCK=8MHZ	
	RCC_HCLKConfig(RCC_SYSCLK_Div1);//选择HCLK时钟源为系统时钟SYYSCLOCK
  	RCC_PCLK1Config(RCC_HCLK_Div4);//APB1时钟为2M 
  	RCC_PCLK2Config(RCC_HCLK_Div4);//APB2时钟为2M
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);//使能APB2外设GPIOB时钟
	*/

	//==========================使用外部RC晶振========================================
  	RCC_DeInit();				//初始化为缺省状态
  	RCC_HSEConfig(RCC_HSE_ON);  //高速时钟使能
  	while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);  //等待高速时钟使能就绪

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	//Enable Prefetch Buffer 
    FLASH_SetLatency(FLASH_Latency_2);	  					// Flash 2 wait state 
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 						// HCLK = SYSCLK 
    RCC_PCLK2Config(RCC_HCLK_Div1);							// PCLK2 = HCLK 
    RCC_PCLK1Config(RCC_HCLK_Div2);	  						// PCLK1 = HCLK/2 
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);	// PLLCLK = 8MHz * 9 = 72 MHz  
    RCC_PLLCmd(ENABLE);	  									// Enable PLL 
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);		// Wait till PLL is ready 

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);	  			// Select PLL as system clock source 
    while(RCC_GetSYSCLKSource() != 0x08);					// Wait till PLL is used as system clock source 

	//====================================================================================
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	// 使能APB2外设GPIOC时钟
  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);		// Enable TIM2, TIM3 and TIM4 clocks ,可删掉
}

//以下具体函数的设置是参照寄存器手册配置的

/*******************************************************************************
* Function Name  : RCC_DeInit
* Description    : Resets the RCC clock configuration to the default reset state.
* Input          : None
* Output         : None
* Return         : None
* 功能           : 将外设RCC寄存器重设为缺省值 ;
*******************************************************************************/
void RCC_DeInit(void)
{
  /* Set HSION bit */
  RCC->CR |= (u32)0x00000001;

  /* Reset SW[1:0], HPRE[3:0], PPRE1[2:0], PPRE2[2:0], ADCPRE[1:0] and MCO[2:0] bits */
  RCC->CFGR &= (u32)0xF8FF0000;
  
  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (u32)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR &= (u32)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE bits */
  RCC->CFGR &= (u32)0xFF80FFFF;

  /* Disable all interrupts */
  RCC->CIR = 0x00000000;
}

/*******************************************************************************
* Function Name  : RCC_HSEConfig
* Description    : Configures the External High Speed oscillator (HSE).
*                  HSE can not be stopped if it is used directly or through the 
*                  PLL as system clock.
* Input          : - RCC_HSE: specifies the new state of the HSE.
*                    This parameter can be one of the following values:
*                       - RCC_HSE_OFF: HSE oscillator OFF
*                       - RCC_HSE_ON: HSE oscillator ON
*                       - RCC_HSE_Bypass: HSE oscillator bypassed with external
*                         clock
* Output         : None
* Return         : None
* 功能           : 设置外设高速晶振(HSE)
*******************************************************************************/
void RCC_HSEConfig(u32 RCC_HSE)
{
  /* Check the parameters */
  assert_param(IS_RCC_HSE(RCC_HSE));

  /* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/
  /* 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;      
  }
}

/*******************************************************************************
* Function Name  : RCC_GetFlagStatus
* Description    : Checks whether the specified RCC flag is set or not.
* Input          : - RCC_FLAG: specifies the flag to check.
*                    This parameter can be one of the following values:
*                       - RCC_FLAG_HSIRDY: HSI oscillator clock ready
*                       - RCC_FLAG_HSERDY: HSE oscillator clock ready
*                       - RCC_FLAG_PLLRDY: PLL clock ready
*                       - RCC_FLAG_LSERDY: LSE oscillator clock ready
*                       - RCC_FLAG_LSIRDY: LSI oscillator clock ready
*                       - RCC_FLAG_PINRST: Pin reset
*                       - RCC_FLAG_PORRST: POR/PDR reset
*                       - RCC_FLAG_SFTRST: Software reset
*                       - RCC_FLAG_IWDGRST: Independent Watchdog reset
*                       - RCC_FLAG_WWDGRST: Window Watchdog reset
*                       - RCC_FLAG_LPWRRST: Low Power reset
* Output         : None
* Return         : The new state of RCC_FLAG (SET or RESET).
* 功能           : 检查指定的RCC标志位设置与否 ;
*******************************************************************************/
FlagStatus RCC_GetFlagStatus(u8 RCC_FLAG)
{
  u32 tmp = 0;
  u32 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 & ((u32)1 << tmp)) != (u32)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }

  /* Return the flag status */
  return bitstatus;
}

/*******************************************************************************
* Function Name  : FLASH_PrefetchBufferCmd
* Description    : Enables or disables the Prefetch Buffer.
* Input          : - FLASH_PrefetchBuffer: specifies the Prefetch buffer status.
*                    This parameter can be one of the following values:
*                       - FLASH_PrefetchBuffer_Enable: FLASH Prefetch Buffer Enable
*                       - FLASH_PrefetchBuffer_Disable: FLASH Prefetch Buffer Disable
* Output         : None
* Return         : None
* 功能           : 使能或者失能预取指缓存 ;
*******************************************************************************/
void FLASH_PrefetchBufferCmd(u32 FLASH_PrefetchBuffer)
{
  /* Check the parameters */
  assert_param(IS_FLASH_PREFETCHBUFFER_STATE(FLASH_PrefetchBuffer));
  
  /* Enable or disable the Prefetch Buffer */
  FLASH->ACR &= ACR_PRFTBE_Mask;
  FLASH->ACR |= FLASH_PrefetchBuffer;
}

/*******************************************************************************
* Function Name  : FLASH_SetLatency
* Description    : Sets the code latency value.
* Input          : - FLASH_Latency: specifies the FLASH Latency value.
*                    This parameter can be one of the following values:
*                       - FLASH_Latency_0: FLASH Zero Latency cycle
*                       - FLASH_Latency_1: FLASH One Latency cycle
*                       - FLASH_Latency_2: FLASH Two Latency cycles
* Output         : None
* Return         : None
* 功能           : 设置代码延时值 ;
*******************************************************************************/
void FLASH_SetLatency(u32 FLASH_Latency)
{
  /* Check the parameters */
  assert_param(IS_FLASH_LATENCY(FLASH_Latency));
  
  /* Sets the Latency value */
  FLASH->ACR &= ACR_LATENCY_Mask;
  FLASH->ACR |= FLASH_Latency;
}

/*******************************************************************************
* Function Name  : RCC_HCLKConfig
* Description    : Configures the AHB clock (HCLK).
* Input          : - RCC_SYSCLK: defines the AHB clock divider. This clock is
*                    derived from the system clock (SYSCLK).
*                    This parameter can be one of the following values:
*                       - RCC_SYSCLK_Div1: AHB clock = SYSCLK
*                       - RCC_SYSCLK_Div2: AHB clock = SYSCLK/2
*                       - RCC_SYSCLK_Div4: AHB clock = SYSCLK/4
*                       - RCC_SYSCLK_Div8: AHB clock = SYSCLK/8
*                       - RCC_SYSCLK_Div16: AHB clock = SYSCLK/16
*                       - RCC_SYSCLK_Div64: AHB clock = SYSCLK/64
*                       - RCC_SYSCLK_Div128: AHB clock = SYSCLK/128
*                       - RCC_SYSCLK_Div256: AHB clock = SYSCLK/256
*                       - RCC_SYSCLK_Div512: AHB clock = SYSCLK/512
* Output         : None
* Return         : None
* 功能           : 设置AHB时钟(HCLK);
*******************************************************************************/
void RCC_HCLKConfig(u32 RCC_SYSCLK)
{
  u32 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;
}

/*******************************************************************************
* Function Name  : RCC_PCLK2Config
* Description    : Configures the High Speed APB clock (PCLK2).
* Input          : - 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:
*                       - RCC_HCLK_Div1: APB2 clock = HCLK
*                       - RCC_HCLK_Div2: APB2 clock = HCLK/2
*                       - RCC_HCLK_Div4: APB2 clock = HCLK/4
*                       - RCC_HCLK_Div8: APB2 clock = HCLK/8
*                       - RCC_HCLK_Div16: APB2 clock = HCLK/16
* Output         : None
* Return         : None
* 功能           : 设置高速AHB时钟(PCLK2);
*******************************************************************************/
void RCC_PCLK2Config(u32 RCC_HCLK)
{
  u32 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;
}

/*******************************************************************************
* Function Name  : RCC_PCLK1Config
* Description    : Configures the Low Speed APB clock (PCLK1).
* Input          : - 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:
*                       - RCC_HCLK_Div1: APB1 clock = HCLK
*                       - RCC_HCLK_Div2: APB1 clock = HCLK/2
*                       - RCC_HCLK_Div4: APB1 clock = HCLK/4
*                       - RCC_HCLK_Div8: APB1 clock = HCLK/8
*                       - RCC_HCLK_Div16: APB1 clock = HCLK/16
* Output         : None
* Return         : None
* 功能           : 设置低速AHB时钟(PCLK1) ;
*******************************************************************************/
void RCC_PCLK1Config(u32 RCC_HCLK)
{
  u32 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;
}

/*******************************************************************************
* Function Name  : RCC_PLLConfig
* Description    : Configures the PLL clock source and multiplication factor.
*                  This function must be used only when the PLL is disabled.
* Input          : - RCC_PLLSource: specifies the PLL entry clock source.
*                    This parameter can be one of the following values:
*                       - RCC_PLLSource_HSI_Div2: HSI oscillator clock divided
*                         by 2 selected as PLL clock entry
*                       - RCC_PLLSource_HSE_Div1: HSE oscillator clock selected
*                         as PLL clock entry
*                       - RCC_PLLSource_HSE_Div2: HSE oscillator clock divided
*                         by 2 selected as PLL clock entry
*                  - RCC_PLLMul: specifies the PLL multiplication factor.
*                    This parameter can be RCC_PLLMul_x where x:[2,16]
* Output         : None
* Return         : None
* 功能           : 设置PLL时钟源及倍频系数 ;
*******************************************************************************/
void RCC_PLLConfig(u32 RCC_PLLSource, u32 RCC_PLLMul)
{
  u32 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;
}

/*******************************************************************************
* Function Name  : RCC_PLLCmd
* Description    : Enables or disables the PLL.
*                  The PLL can not be disabled if it is used as system clock.
* Input          : - NewState: new state of the PLL.
*                    This parameter can be: ENABLE or DISABLE.
* Output         : None
* Return         : None
* 功能           : 使能或者失能PLL ;
*******************************************************************************/
void RCC_PLLCmd(FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  *(vu32 *) CR_PLLON_BB = (u32)NewState;
}

/*******************************************************************************
* Function Name  : RCC_GetFlagStatus
* Description    : Checks whether the specified RCC flag is set or not.
* Input          : - RCC_FLAG: specifies the flag to check.
*                    This parameter can be one of the following values:
*                       - RCC_FLAG_HSIRDY: HSI oscillator clock ready
*                       - RCC_FLAG_HSERDY: HSE oscillator clock ready
*                       - RCC_FLAG_PLLRDY: PLL clock ready
*                       - RCC_FLAG_LSERDY: LSE oscillator clock ready
*                       - RCC_FLAG_LSIRDY: LSI oscillator clock ready
*                       - RCC_FLAG_PINRST: Pin reset
*                       - RCC_FLAG_PORRST: POR/PDR reset
*                       - RCC_FLAG_SFTRST: Software reset
*                       - RCC_FLAG_IWDGRST: Independent Watchdog reset
*                       - RCC_FLAG_WWDGRST: Window Watchdog reset
*                       - RCC_FLAG_LPWRRST: Low Power reset
* Output         : None
* Return         : The new state of RCC_FLAG (SET or RESET).
* 功能           : 检查指定的RCC标志位设置与否 ;
*******************************************************************************/
FlagStatus RCC_GetFlagStatus(u8 RCC_FLAG)
{
  u32 tmp = 0;
  u32 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 & ((u32)1 << tmp)) != (u32)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }

  /* Return the flag status */
  return bitstatus;
}

/*******************************************************************************
* Function Name  : RCC_SYSCLKConfig
* Description    : Configures the system clock (SYSCLK).
* Input          : - RCC_SYSCLKSource: specifies the clock source used as system
*                    clock. This parameter can be one of the following values:
*                       - RCC_SYSCLKSource_HSI: HSI selected as system clock
*                       - RCC_SYSCLKSource_HSE: HSE selected as system clock
*                       - RCC_SYSCLKSource_PLLCLK: PLL selected as system clock
* Output         : None
* Return         : None
* 功能           : 设置系统时钟(SYSCLK);
*******************************************************************************/
void RCC_SYSCLKConfig(u32 RCC_SYSCLKSource)
{
  u32 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;
}


/*******************************************************************************
* Function Name  : RCC_GetSYSCLKSource
* Description    : Returns the clock source used as system clock.
* Input          : None
* Output         : None
* Return         : 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
* 功能           : 返回用作系统时钟的时钟源 ;
*******************************************************************************/
u8 RCC_GetSYSCLKSource(void)
{
  return ((u8)(RCC->CFGR & CFGR_SWS_Mask));
}

/*******************************************************************************
* Function Name  : RCC_APB2PeriphClockCmd
* Description    : Enables or disables the High Speed APB (APB2) peripheral clock.
* Input          : - RCC_APB2Periph: specifies the APB2 peripheral to gates its
*                    clock.
*                    This parameter can be any combination of the following values:
*                       - RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
*                         RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
*                         RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
*                         RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
*                         RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
*                         RCC_APB2Periph_ALL
*                  - NewState: new state of the specified peripheral clock.
*                    This parameter can be: ENABLE or DISABLE.
* Output         : None
* Return         : None
* 功能           : 使能或者失能APB2外设时钟 ;
*******************************************************************************/
void RCC_APB2PeriphClockCmd(u32 RCC_APB2Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    RCC->APB2ENR |= RCC_APB2Periph;
  }
  else
  {
    RCC->APB2ENR &= ~RCC_APB2Periph;
  }
}

/*******************************************************************************
* Function Name  : RCC_APB1PeriphClockCmd
* Description    : Enables or disables the Low Speed APB (APB1) peripheral clock.
* Input          : - RCC_APB1Periph: specifies the APB1 peripheral to gates its
*                    clock.
*                    This parameter can be any combination of the following values:
*                       - RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
*                         RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
*                         RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
*                         RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4, 
*                         RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2,
*                         RCC_APB1Periph_USB, RCC_APB1Periph_CAN, RCC_APB1Periph_BKP,
*                         RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_ALL
*                  - NewState: new state of the specified peripheral clock.
*                    This parameter can be: ENABLE or DISABLE.
* Output         : None
* Return         : None
* 功能           : 使能或者失能APB1外设时钟 ;
*******************************************************************************/
void RCC_APB1PeriphClockCmd(u32 RCC_APB1Periph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));

  if (NewState != DISABLE)
  {
    RCC->APB1ENR |= RCC_APB1Periph;
  }
  else
  {
    RCC->APB1ENR &= ~RCC_APB1Periph;
  }
}

上一篇:STM32-(25):PWM实验 下一篇:STM32-(27):RTC实时时钟
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值