STM32复位和时钟系统

阻容复位

  • 系统复位、上电复位和备份区域复位

时钟源

任一个时钟源都可被独立地启动或关闭,优化系统功耗。

  • 主时钟源
    三种不同的时钟源可被用来驱动系统时钟(SYSCLK)
    HSI 振荡器时钟。
    HSE振荡器时钟
    PLL 时钟[主PLL和专用PLL)

  • 二级时钟源
    LSI时钟:32KHz低速内部RC
    LSE时钟:32.768khz低速外部晶体

  • 时钟树
    在这里插入图片描述

  • [1] LSI是低速内部时钟,RC振荡器,供独立看门狗和自动唤醒单元使用

  • [2] LSE是低速外部时钟,主要是RTC的时钟源

  • [3] HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。HSE也可以直接做为系统时钟或者PLL输入

  • [4] HSI是高速内部时钟,RC振荡器,频率为16MHz。可以直接作为系统时钟或者用作PLL输入

  • [5] PLL为锁相环倍频输出。STM32F4有两个PLL:
    1、主PLL(PLL)由HSE或者HSI提供时钟信号,并具有两个不同的输出时钟。第一个输出PLLP用于生成高速的系统时钟(最高168MHz)第二个输出PLLQ用于生成USB OTG FS的时钟(48MHz),随机数发生器的时钟和SDIO时钟。
    2、专用PLL(PLLI2S)用于生成精确时钟,从而在I2S接口实现高品质音频性能

  • [A] 这里是看门狗时钟输入。看门狗时钟源只能是低速的LSI时钟。

  • [B] 这里是RTC时钟源,从图上可以看出,RTC的时钟源可以选择LSI,LSE,以及HSE分频后的时钟,HSE分频系数为2~31。

  • [C] 这里是STM32F4输出时钟MCO1和MCO2。MCO1是向芯片的PA8引脚输出时钟。它有四个时钟来源分别为:HSI,LSE,HSE和PLL时钟。MCO2是向芯片的PC9输出时钟,它同样有四个时钟来源分别为:HSE,PLL,SYSCLK以及PLLI2S时钟。MCO输出时钟频率最大不超过100MHz。

  • [D] 这里是系统时钟。SYSCLK系统时钟来源有三个方面:HSI,HSE和PLL。
    HCLK = SYSCLK / 1 (AHB1Periph) = 168MHz
    PCLK2 = HCLK / 2 (APB2Periph) = 84MHz
    PCLK1 = HCLK / 4 (APB1Periph) = 42MHz
    APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14
    APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11

  • [E] 这里我们指的是以太网PTP时钟,AHB时钟,APB2高速时钟,APB1低速时钟。这些时钟都是来源于SYSCLK系统时钟。其中以太网PTP时钟是使用系统时钟。AHB,APB2和APB1时钟是经过SYSCLK时钟分频得来。这里大家记住,AHB最大时钟为168MHz, APB2高速时钟最大频率为84MHz,而APB1低速时钟最大频率为42MHz。

  • [F] 这里是指I2S时钟源。I2S的时钟源来源于PLLI2S或者映射到I2S_CKIN引脚的外部时钟。I2S出于音质的考虑,对时钟精度要求很高。STM32F4开发板使用的是内部PLLI2SCLK。

  • [G] 这是STM32F4内部以太网MAC时钟的来源。对于MII接口来说,必须向外部PHY芯片提供25Mhz的时钟,这个时钟,可以由PHY芯片外接晶振,或者使用STM32F4 的MCO输出来提供。然后,PHY 芯片再给STM32F4提供ETH_MII_TX_CLK和ETH_MII_RX_CLK时钟。对于RMII接口来说,外部必须提供50Mhz的时钟驱动PHY和STM32F4的ETH_RMII_REF_CLK,这个50Mhz时钟可以来自PHY、有源晶振或者STM32F4的MCO。我们的开发板使用的是RMII 接口,使用PHY 芯片提供50Mhz时钟驱动STM32F4 的ETH_RMII_REF_CLK。

  • [H] 这里是指外部PHY提供的USB OTG HS(60MHZ)时钟。

时钟初始化配置

  • 系统启动以后默认使用的是内部 16MHz 的 RC 振荡器,启动过程中 NRST 引脚产生复位信号,从而进入 STM32F4 的复位中断服务程序,在里面调用相关的函数,将时钟切换到 HSE,进入到 main 函数执行。
  • SystemInit()功能:建立系统时钟(系统时钟源,PLL分频和倍频因子,AHB/APBx 分频,FLASH 设置)
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
  • SystemInit函数开始先进行浮点运算单元设置,然后是复位PLLCFGR,CFGR寄存器,同时通过设置CR寄存器的HSI时钟使能位来打开HSI时钟。此代码就是RCC->CR |=(uint32_t)0x00000001,打开HSI振荡器,在设置完相关寄存器后,接下来SystemInit函数内部会调用SetSysClock函数。
static void SetSysClock(void)
{
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* Enable HSE 在第16bit置1将HSE振荡器打开*/
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  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;
  }
 
  if (HSEStatus == (uint32_t)0x01)
  {
    /* Select regulator voltage output Scale 1 mode, System frequency up to 168 MHz */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR |= PWR_CR_VOS;
 
    /* HCLK = SYSCLK / 1*不分频/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK / 2*2分频/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    
    /* PCLK1 = HCLK / 4*4分频/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
 
    /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
 
    /* Enable the main PLL */
    RCC->CR |= RCC_CR_PLLON;
 
    /* Wait till the main PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
   
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
 
    /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;
 
    /* Wait till the main PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
  }
/******************************************************************************/
/*                          I2S clock configuration                           */
/******************************************************************************/
  /* PLLI2S clock used as I2S clock source */
  RCC->CFGR &= ~RCC_CFGR_I2SSRC;
 
  /* Configure PLLI2S */
  RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28);
 
  /* Enable PLLI2S */
  RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON);
 
  /* Wait till PLLI2S is ready */
  while((RCC->CR & RCC_CR_PLLI2SRDY) == 0)
  {
  }
}
  • HSE 就绪就绪后配置流程如下:
    HCLK = SYSCLK / 1。
    PCLK2 = HCLK / 2。
    PCLK1 = HCLK / 4。
    配置主 PLL,并等待其就绪。
    配置 Flash prefetch, Instruction cache, Data cache 和 wait state。
    选择 mian PLL 作为系统时钟源
    到这里基本完成了HSE 作为系统时钟的初始化工作,剩下就可以进入 main 函数进行操作了。到这里时钟系统就告一段落。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值