时钟系统介绍

来源:互联网 发布:iphone4s支持4g网络吗 编辑:程序博客网 时间:2024/06/05 08:01

STM32F4时钟

三种不同的时钟源可被用来驱动系统时钟(SYSCLK)
HSI 振荡器时钟
HSE 振荡器时钟
PLL 时钟
这些设备有以下两种二级时钟源:
1. 32kHz 低速内部 RC,可以用于驱动独立看门狗和通过程序选择驱动 RTC。RTC 用于从停机/待机模式下自动唤醒系统。
2. 32.768kHz 低速外部晶体也可用来通过程序选择驱动 RTC(RTCCLK)。当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。
下图是参考手册上面的时钟树。
Markdown

由时钟控制器的时钟树可以看出,STM32F4在应用中可以选择外部晶体或者内部 RC 振荡器来驱动内核和外设,像以太网,USB,I2S 和 SDIO 需要专用时钟。

AHB 总线 高支持 168MHz 的时钟,通过 AHB 总线分频,APB2 高支持 84MHz,APB1 高支持 42MHz。
所有的外设驱动全部来自 SYSCLK 除了下面几个:
1. USB OTG FS 的时钟(48MHz)、随机信号发生器时钟(<=48MHz)和 SDIO 时钟(<=48MHz)全部来自 PLL48CLK。
2. I2S 时钟,为了达到高性能的要求,I2S 时钟可以用内部时钟 PLLI2S 或者使用外部时钟,通过 I2S_CLKIN 引脚输入得到。
3. USB OTG HS(60MHz)需要外部 PHY 芯片提供。
4. 以太网时钟(TX,RX 和 RMII)也需要外部 PHY 芯片提供时钟。

RCC 通过 AHB 时钟(HCLK)8 分频后作为 Cortex 系统定时器(SysTick)的外部时钟。通过对 SysTick 控制与状态寄存器的设置,可选择上述时钟或 Cortex(HCLK)时钟作为 SysTick 时钟。定时器时钟频率分配由硬件按以下 2 种情况自动设置:
1. 如果相应的 APB 预分频系数是 1,定时器的时钟频率与所在 APB 总线频率一致。
2. 定时器的时钟频率被设为与其相连的 APB 总线频率的 2 倍。具体就是下面这样:

HCLK = SYSCLK / 1  (AHB1Periph)  = 168MHz PCLK2 = HCLK / 2   (APB2Periph)  = 84MHz PCLK1  =  HCLK / 4      (APB1Periph)      = 42MHzAPB1 prescaler != 1时, APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2;  当APB2 prescaler != 1时, APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock; APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11 

STM32F4复位介绍

STM32F4 支持三种复位形式,分别为系统复位、上电复位和备份区域复位

进行IAP编程,由APP跳转回IAP的时候,可使用系统复位这一函数。

RCC相关库文件说明

在startup_stm32f40_41xxx.s文件中,跳转到了systeminit函数—>在system_stm32f4xx.c中:

  1. 本文件提供了两个函数和一个全局变量用于被用户函数调用。
    • SystemInit(): 这个就是前面复位中断服务程序调用的函数,建立系统时钟(系统时钟源,PLL分频和倍频因子,AHB/APBx 分频,FLASH 设置)。时钟的配置可以用官方的 clock xls 配置工具进行设置(这个工具我还没有用过)。
    • SystemCoreClock variable:也就是 HCLK。
    • SystemCoreClockUpdate():更新变量 SystemCoreClock,在程序的执行过程中,内核时钟发生了变化,这个函数必须被调用。
  2. 系统复位后是使用的内部 16MHz 的 RC 振荡器作为系统时钟源,然后调用函数 SystemInit()重新配置时钟,进入到 main 函数执行。
  3. 如果用户选择系统时钟源失败,那么仍然用内部 RC 振荡器做系统时钟源,用户可以通过在函数
    SetSysClock()添加一些代码来解决这个问题。
  4. HSE 外接晶振的默认频率时 25MHz,HSE_VALUE 在文件 stm32f4xx.h 里面定义,
  5. 当直接或者通过 PLL 将 HSE 作为系统时钟源时,根据使用的晶振频率重新配置 HSE_VALUE 的数值。
  6. STM32F40xxx/41xxx,我们这里重点说这个的相关配置。

我们看一下SystemInit函数:

/**  * @brief  Setup the microcontroller system  *         Initialize the Embedded Flash Interface, the PLL and update the   *         SystemFrequency variable.  * @param  None  * @retval None  */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  //开启FPU(浮点处理)  /*-------------------------------------------------------------------------*/  /* 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;    //关闭所有中断  /*--------------------------------------------------------------------------*/#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)  SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */  /* 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}//SCB->VTOR 是中断向量表地址寄存器。可以将中断向量表放在内部 Flash 或者内部 SRAM//如果需要将程序定位在 CPU 内部 SRAM,请打开 "VECT_TAB_SRAM" 宏定义。

接下来我们看一下

//将HSE作为系统时钟输入/**  * @brief  Configures the System clock source, PLL Multiplier and Divider factors,   *         AHB/APBx prescalers and Flash settings  * @Note   This function should be called only once the RCC clock configuration    *         is reset to the default reset state (done in SystemInit() function).     * @param  None  * @retval None  */static void SetSysClock(void){/******************************************************************************//*            PLL (clocked by HSE) used as System clock source                *//******************************************************************************/  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;  /* Enable 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)              //HSE已就绪  {    /* 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;#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx)          /* PCLK2 = HCLK / 2*/    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;    /* PCLK1 = HCLK / 4*/    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */#if defined (STM32F401xx)    /* PCLK2 = HCLK / 2*/    RCC->CFGR |= RCC_CFGR_PPRE2_DIV1;    /* PCLK1 = HCLK / 4*/    RCC->CFGR |= RCC_CFGR_PPRE1_DIV2;#endif /* STM32F401xx */    /* 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)    {    }#if defined (STM32F427_437xx) || defined (STM32F429_439xx)    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */    PWR->CR |= PWR_CR_ODEN;    while((PWR->CSR & PWR_CSR_ODRDY) == 0)    {    }    PWR->CR |= PWR_CR_ODSWEN;    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)    {    }          /* Configure Flash prefetch, Instruction cache, Data cache and wait state */    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;#endif /* STM32F427_437x || STM32F429_439xx  */#if defined (STM32F40_41xxx)         /* Configure Flash prefetch, Instruction cache, Data cache and wait state */    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;#endif /* STM32F40_41xxx  */#if defined (STM32F401xx)    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS;#endif /* STM32F401xx */    /* 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 */  }}
原创粉丝点击