STM32F40X之时钟树

一、时钟树概述

目前用到的STM32的许多片上外设都需要先打开相应的时钟,告诉当前这个器件是以什么频率在运行,而每个片上外设的时钟频率其实在出厂时已经固化。

二、时钟树框架

STM32F40X之时钟树_第1张图片

25M / 25 * 336 / 2 = 168M

STM32F40X之时钟树_第2张图片

系统时钟计算公式:SYSCLK=PLLCLK = HSE / M *N / P = 168M

STM32F40X之时钟树_第3张图片

系统时钟 (SYSCLK==168MHZ)可以来自以下三种不同的时钟源。 
● HSI 振荡器时钟 
● HSE 振荡器时钟 
● 主 PLL (PLL) 时钟 
留心:芯片内部未使用时默认都是关闭的,目的是降低功耗,可以单独打开或者关闭。
3概念补充:
(1)MCO1/2: 微处理器的时钟输出,可以向外提供时钟源而且也可以测量芯片内部时钟是否稳定正确。
(2)芯片内部的工作时钟可以由以下四个时钟提供:(重点)
①LSI(low speed inner):内部低速时钟:该时钟是芯片内部的一个32KHZ的RC振荡器,该时钟非常不稳定,一般很少使用。
作用对象:独立看门狗和RTC
②LSE(外部低速时钟):该时钟是由芯片外部提供的的一个32.768KHZ的有源晶振,该时钟要求要很稳定,是RTC专用时钟。
作用对象:RTC也可以向外提供一个时钟源。
③HSI(内部高速时钟):该时钟是芯片内部的一个16MHZ的RC振荡器,该时钟用途很多。
作用对象:向外输出一个时钟源、给系统提供时钟、作为PLL时钟输入源。
④HSE(外部高速时钟):该时钟是由芯片外部提供的的一个25MHZ的有源晶振,该时钟非常稳定.
作用对象:向外输出一个时钟源、给系统提供时钟、作为PLL时钟输入源,作为RTC的时钟输入源。
(3)锁相环(PPL):使得输入和输出两个频率同步即具有稳定频率的作用。能使输出频率是输入频率的倍数,可以实现对输入输出信号的进行调制。

在APB1总线上的外设时钟频率为42M,但是定时器的时钟频率是84M

在APB2总线上的外设时钟频率为84M,但是定时器的时钟频率是168M

框架分析思路:

芯片要想工作需要一个时钟输入,对于该芯片(40x)时钟频率最高168Mhz,所以最终我们需要获得一个168MHZ(系统要求的) 的时钟作为系统时钟,再由该系统时钟经过分频得到各个模块的时钟。
经分析:系统时钟可以来自以下三个输入源:即HIS/HSE/PLL(锁相环)
STM32F40X之时钟树_第4张图片

由上图可知HIS(16MHZ)和HSE(25MHZ)都不能直接选为系统时钟(要求是168MHZ),经分析虽然HIS(16MHZ)和HSE(25MHZ)都不能直得到系统时钟(168MHZ),但是可以选择PLLCLK作为系统时钟,而PLLCLK的时钟要经过锁相环(PLL)处理才能得到。

STM32F40X之时钟树_第5张图片

三、时钟树程序设计

时钟设置步骤如下:                  
1使能HSI 。
2等待HSI打开成功。
3设置电压调节器输出级别默认就行)。
4打开电源开关(默认就行)
5设置AHB/APB1/APB2的分频值。
6关闭主锁相环锁 (可以不要)
7等待关闭成功(可以不要)
8配置PLL(M/N/P包括选择HSI作为锁相环输入时钟源)。
9开启主PLL。
10等待主锁相环稳定。
11设置flash的相关参数(缓存,存取指令数据缓存,等待周期等 默认就可以)    
12切换PLL为系统时钟源。
13 等待PLL作为系统时钟切换成功。

void SystemInit(void)
{
/* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;//把RCC的第0位置1

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000; //CFGR寄存器全部复位

  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR &= (uint32_t)0xFEF6FFFF; //复位HSE,CSS,PLL

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x24003010;//对于后面需要配置的PLL相应的时钟复位成原本的值

  /* Reset HSEBYP bit */
  RCC->CR &= (uint32_t)0xFFFBFFFF;//复位HSEYP的位

  /* Disable all interrupts */
  RCC->CIR = 0x00000000; //复位中断

}

static void SetSysClock(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0; //StartUpCounter 超时计数变量,HSEStatus 标志位

 /* Enable HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);//使能HSE的振荡器
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;//要不就是0,要不就是非零值
    StartUpCounter++;//累加
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
//上面的do while出来的条件有两个:一个是HSE就绪,一个是等待的时间到了

//判断HSE有没有就绪
  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }
 if (HSEStatus == (uint32_t)0x01)
  {
    /* Select regulator voltage output Scale 1 mode */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;//使能电源接口时钟
    PWR->CR |= PWR_CR_VOS;

/* HCLK = SYSCLK / 1*/
 RCC->CFGR |= RCC_CFGR_HPRE_DIV1;//AHB为1分频
 /* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2为2分频

  /* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;//APB1为4分频

RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
//M分频是25,N倍频是336,P分频是2,选择 HSE 振荡器时钟作为 PLL 和 PLLI2S 时钟输入
 /* Enable the main PLL */
 RCC->CR |= RCC_CR_PLLON;//开启PLL时钟源
 /* Wait till the main PLL is ready */
  while((RCC->CR & RCC_CR_PLLRDY) == 0)//死等PLL就绪
  {
  }
 /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL; //选择PLL作为系统时钟源168M

}


HSE改为HSI最后还是168M

你可能感兴趣的:(STM32单片机,stm32,单片机)