STM32复位和时钟控制(RCC)

 

STM32RCC(Reset and Clock Control)是STM32微控制器系列中的一个模块,它负责配置和管理系统时钟。

以下是一些STM32RCC的主要功能和作用:

1. 系统时钟配置:STM32微控制器通常具有多个时钟源可供选择,例如内部振荡器、外部晶体振荡器、外部时钟源等。STM32RCC模块允许用户根据需要配置系统时钟源,并进行时钟源切换。

2. 时钟使能控制:系统中的各个外设需要时钟信号来进行操作,STM32RCC模块提供了对各个外设时钟的使能控制。用户可以通过STM32RCC模块配置和启用相应的时钟,以激活具体的外设功能。

3. 时钟分频控制:STM32RCC模块允许用户对系统时钟进行分频,以调整系统时钟频率。这可以用来降低功耗、减小时钟信号传输距离引起的噪音等。

4. 时钟安全机制:STM32RCC模块还提供了一些时钟安全机制,如时钟失效检测、时钟频率监测等,旨在确保系统时钟的稳定性和可靠性。

总之,STM32RCC模块在STM32微控制器中负责配置和管理系统时钟,并提供了时钟源选择、时钟使能控制、时钟分频控制和时钟安全机制等功能。它是系统中确保时钟稳定和外设正常运行的重要模块。

1.时钟树

我们知道当我们编写的程序启动的时候会先执行汇编文件,在汇编文件里面会调用SystemInit,这是固件库编辑的一个函数,它里面会把时钟初始化位72MHZ,当我们开始执行main函数的时候,系统已经给我们将系统时钟设置为了72MHZ。所以我们在学习点亮LED的时候并不需要设置系统时钟 。

时钟树如下图:

STM32复位和时钟控制(RCC)_第1张图片

1.1.HSE时钟

HSE:High Speed External Clock signal,即高速的外部时钟。从上图的OSC_OUT和OSC_IN端口进入,我们也可以通过原理图晶振电路模块查看。来源是无源晶振(4-16M),我们通常使用8M。如果要使用HSE这个时钟,需要RCC_CR时钟控制寄存器的位16:HSEON控制。RCC_CR时钟控制寄存器如下图:

STM32复位和时钟控制(RCC)_第2张图片

STM32复位和时钟控制(RCC)_第3张图片

 当HSEON位置0时振荡器关闭,当置1时振荡器开启。因为起振需要一定的时间,所以就需要用到位17的HSERDY:外部高速时钟就绪标志

STM32复位和时钟控制(RCC)_第4张图片

当这个位为0时表示振荡器没有就绪,为1时表示振荡器就绪。 

1.2.HSI时钟 

HSI:High Speed Internal Clock signal,高速的内部时钟。HSI来源自芯片内部,大小也为8M,当HSE故障的时候,系统时钟会自动切换到HSI,直到HSE启动成功。同样HSI时钟的控制需要用到RCC_CR时钟控制器的HSION和HSIRDY两个位,作用和HSE的两个位的作用相同。 

STM32复位和时钟控制(RCC)_第5张图片

 1.3.系统时钟形成

STM32复位和时钟控制(RCC)_第6张图片 

当HSE以8M通过HSE OSC进入,然后又两条路,一条路以8M继续进入下一步,另一条路将8M二分频为4M,这两条路的选择通过时钟配置寄存器RCC_CFGR的位17的PLLXTPRE控制

STM32复位和时钟控制(RCC)_第7张图片

一般我们通过PLLXTPRE置0,不分频继续以8M传输到PLLSRC,PLLSRC也是 由RCC_CFGR寄存器控制

因为有两条路进入PLLSRC,一条是经过 PLLXTPRE的HSE,另一条则是被2分频的HSI,PLLSRC的作用就是控制是HSE还是HSI时钟作为PLL的输入时钟。

进入到PLL后通过PLLMUL乘上倍频因子(2-16),PLLMUL也是通过RCC_CFGR寄存器控制

STM32复位和时钟控制(RCC)_第8张图片

最终PLLCLK这个时钟就被倍频为72MHZ。

系统时钟来源有三个,HSI、PLLCLK、HSE,通过 RCC_CFGR寄存器的SW位来控制

STM32复位和时钟控制(RCC)_第9张图片

 因为时钟切换需要时间,所以SWS位用于表示当前是哪个输入作为系统时钟。

STM32复位和时钟控制(RCC)_第10张图片

 系统时钟通过AHB总线分预频器进入到APB1和APB2总线的预分频器,这三个预分频器同样由RCC_CFGR寄存器控制

STM32复位和时钟控制(RCC)_第11张图片

STM32复位和时钟控制(RCC)_第12张图片一般将AHB一倍频,APB1是低速总线最高36MHZ,所以要将72MHZ2分频为36MHZ,APB2是高速总线,最高为72MHZ,配置为1分频。

1.4.RTC时钟 和MCO时钟输出

RTC时钟有单个来源,一个是HSE128分频后得到,一个是LSE,一个是内部低速的LSI (30-60MHZ)。

MCO:mircrocontroller clock output,微控制器时钟输出引脚。来源:PLLCLK/2、HSE、SHI、SYSCLK。控制:CRGR:MCO。

可以通过MCO这个引脚连接示波器查看频率是否和设置的值一致。 

2.SetSysClockTo72(void)函数分析 

 SetSysClockTo72(void)这个函数是用于将系统时钟设置为72MHZ。

static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* 使能HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* 等待 HSE就绪并作超时处理 */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  //如果HSE使能成功程序继续执行
  if (HSEStatus == (uint32_t)0x01)
  {
    /* 使能预取 */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* 两个等待周期 */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

 
    /* HCLK = SYSCLK = 72MHZ */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK = 72MHZ */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK = 36MHZ */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

    /*  锁相环配置: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

    /* 使能锁相环 */
    RCC->CR |= RCC_CR_PLLON;

    /* 等待锁相环稳定 */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* 选择锁相环作为系统时钟 */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* 等待锁相环切换为系统时钟*/
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* 如果HSE启动失败,用户可以在这里添加处理错误的代码 */
  }
}

2.1.使能HSE

通过RCC->CR |= ((uint32_t)RCC_CR_HSEON)使HSE使能,然后通过do...while()循环等待 HSE就绪并作超时处理,当HSE成功使能后, HSEStatus值为1,while条件判断为假,跳出循环,然后再用一个if...else判断一下。然后剩下的过程通过一个if...else判断,如果HSE使能成功则程序继续执行,在else中添加处理错误的代码。

2.2.配置FLASH 

紧接着是FLASH相关的代码,因为我们代码是放在FLASH中缓存的,读取的时候是一条一条的读取,所以有一个预取缓冲区,取指的时候有一个等待时间,不能取得很快,等待的时间和频率是一样的,72MHZ要配置成两条指令之间取的时间要等待多少时间是有规定的。

通过闪存访问控制寄存器(FLASH_ACR)控制

STM32复位和时钟控制(RCC)_第13张图片

这里用到了PRFTBE启动预取缓冲区,通过LATENCY设置时延。 

2.3.配置系统时钟 

接着配置AHB、APB1和APB2,然后配置锁相环 ,通过PLLXTPRE让HSE不分频,通过PLLMULL9将时钟倍频为72MHZ。然后使能锁相环,然后使用一个空白的while循环判断PLLRDY值,等待锁相环稳定,然后通过SW设置锁相环为系统时钟,再用一个whlie循环等待时钟切换,这样就系统时钟就配置为72MHZ。

你可能感兴趣的:(stm32,单片机,嵌入式硬件)