STM32笔记 (五) RCC时钟系统

简介

由于STM32的性能强大,内部组成复杂,而且时钟频率普遍比51单片机高,不能简单的用一个51单片机的时钟系统来调配,对于F1系列时钟频率高达72MHz,如果把STM32的每一个外设的时钟都打开,那么功耗是不可想象的,同时对于一个电路,时钟频率越快,抗干扰能力就越弱,因此STM32采用了多时钟源的方式来解决这些问题,并且对于每一个片上外设,都需要单独设置时钟的使能位。

时钟源

  1. HSE时钟–High Speed External Clock Signal (高速外部时钟)
    精度高,位于芯片外部,通过OSC_IN 和OSC_OUT 引脚连接外部晶振
    常用的是无源晶振(4~16MHZ)通常使用8MHZ(无源) ,一般倍频为72MHZ

晶振分类:
1.无源晶振是有2个引脚的无极性元件,需要借助于时钟电路才能产生振荡信号,自身无法振荡起来
2.有源晶振有4只引脚,是一个完整的振荡器,其中除了石英晶体外,还有晶体管和阻容元件主要看 你应用到的电路,如果有时钟电路,就用无源,否则就用有源。

  1. HSI时钟–High Speed Internal Clock Signal(高速内部时钟)
    位于芯片内部,当外部时钟出现故障时,会切换使用HSI时钟,直到HSE启动成功
    大小为8MHZ 一般会被分频成4MHZ
  2. LSE时钟–Low Speed External Clock Signal(低速外部时钟)
    位于芯片外部,通过OSC32_IN和OSC32_OUT连接频率为32.768MHz的石英晶体
  3. LSI时钟–Low Speed Internal Clock Signal(低速内部时钟)
    位于芯片内部,是一个RC震荡器,频率为40KHz
  4. PLLCLK–锁相倍频时钟源
    PLLCLK本身的不是一个独立的内部或者外部时钟源,其来源可以是HSE或者HSI

相关寄存器

typedef struct
{
  __IO uint32_t CR; //时钟控制寄存器
  __IO uint32_t CFGR; //时钟配置寄存器
  __IO uint32_t CIR; //时钟中断寄存器
  __IO uint32_t APB2RSTR; //APB2 外设复位寄存器 
  __IO uint32_t APB1RSTR; //APB1 外设复位寄存器
  __IO uint32_t AHBENR; //AHB外设时钟使能寄存器 
  __IO uint32_t APB2ENR; //APB2 外设时钟使能寄存器 常用
  __IO uint32_t APB1ENR; //APB2 外设时钟使能寄存器 常用
  __IO uint32_t BDCR; //备份域控制寄存器
  __IO uint32_t CSR; //控制/状态寄存器 
  }RCC_TypeDef;

时钟树

稍加注释,原版可在参考手册中找到
在这里插入图片描述
几个名词这里解释一下:
分频:指的的将时钟频率除以一个常数,分频因子就是这个常数,例如,16MHz经过2分频后就是8MHz
倍频:将时钟频率乘以一个常数,倍频因子就是这个常数,例如,8MHz经过9倍倍频后就是72MHz


APB1和APB2总线配置流程图示例
在这里插入图片描述


RTC(实时时钟)时钟源

实时时钟是一个独立的定时器。 RTC模块拥有一组连续计数的计数器,在相应软件配置下,可
提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。

在这里插入图片描述
RTC 时钟可由 HSE/128 分频得到,也可由低速外部时钟信号 LSE 提供,频率为32.768KHZ,也可由低速内部时钟信号 HSI 提供,具体选用哪个时钟由备份域控制寄存器BDCR 的位 9-8: RTCSEL[1:0]配置。独立看门狗的时钟由 LSI 提供,且只能是由 LSI 提供(LSI 是低速的内部时钟信号,频率为 30~60KHZ 直接不等,一般取 40KHZ)。

MCO 时钟输出

  • MCO 是 Microcontroller Clock Output 的缩写,STM32允许输出时钟信号到外部MCO引脚,可以对外提供时钟,相当于一个有源晶振
  • 时钟来源有: PLLCLK/2HSIHSESYSCLK
  • RCC->CFGR寄存器配置
    在这里插入图片描述

配置HSE为系统时钟

编程要点:

  1. 开启 HSE , 等待 HSE稳定
  2. 设置 AHB、 APB2、 APB1 的预分频因子
  3. 设置 PLL 的时钟来源,和 PLL 的倍频因子
  4. 开启 PLL,等待 PLL 稳定
  5. 把 PLLCK 切换为系统时钟 SYSCLK
  6. 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
void HSE_SetSysClk( uint32_t RCC_PLLMul_x ) //x为倍频因子,如RCC_PLLMul_9
{
	ErrorStatus ErrorStatus;
	
	//把RCC复位成刚上电的状态
	RCC_DeInit();

	//使能HSE
	RCC_HSEConfig(RCC_HSE_ON);
	
	//等待HSE设置成功 返回success和error
	ErrorStatus	= RCC_WaitForHSEStartUp();
	
	if( ErrorStatus == SUCCESS ) //如果启动成功
	{
		//使能预取址
		FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
		
		FLASH_SetLatency(FLASH_Latency_2);
		
		//AHB总线分频为1
		RCC_HCLKConfig(RCC_SYSCLK_Div1);
		//APB1总线分频为
		RCC_PCLK1Config(RCC_HCLK_Div2);
		//APB2总线分频为
		RCC_PCLK2Config(RCC_HCLK_Div1);
		
		//配置PLL锁相环   
		//配置PLLCLK = HSB * RCC_PLLMul_x (倍频因子)
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_x);//8*x = xxxMHz
		
		//使能PLL
		RCC_PLLCmd(ENABLE);
		//等待PLL稳定
		while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET );
		
		//选择系统时钟为PLLCLK
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
		//检查系统时钟来源是否正确
		while( RCC_GetSYSCLKSource() != 0x08 );
		
		
	}
	else //启动失败
	{
		/* 可以在这里添加错误时运行的代码 */
	}
	
}

原创文章 12 获赞 0 访问量 1105

猜你喜欢

转载自blog.csdn.net/zcy_cyril/article/details/105893441