时钟系统_系统时钟 - CSDN
精华内容
参与话题
  • STM32——时钟系统

    2020-04-04 18:12:47
    1、STM32时钟系统概述 1.1 时钟系统的概念与意义 概念 时钟系统是由振荡器(信号源)、定时唤醒器、分频器等组成的电路。常用的信号源有晶体振荡器和RC振荡器。 意义 时钟是嵌入式系统的脉搏,处理器内核在时钟驱动...

    1、STM32时钟系统概述

    1.1 时钟系统的概念与意义

    • 概念
      时钟系统是由振荡器(信号源)、定时唤醒器、分频器等组成的电路。常用的信号源有晶体振荡器和RC振荡器。
    • 意义
      时钟是嵌入式系统的脉搏,处理器内核在时钟驱动下完成指令执行、状态变换等动作,外设部件在时钟的驱动下完成各种工作,比如串口数据的发送、A/D转换、定时器计数等等。因此时钟对于计算机系统是至关重要的,通常时钟系统出现问题也是致命的,比如振荡器不振,振荡不稳、停振。
      在这里插入图片描述

    1.2 常见振荡器简介

    • 概念
      振荡器是用来产生重复电子讯号的电子元件。其构成的电路叫振荡电路,能将直流电转换为具有一定频率交流信号输出的电子电路或装置。
    • 分类
      振荡器主要分为RC、LC振荡器和晶体振荡器。RC振荡器是采用RC网络作为选频移相网络的振荡器。LC振荡器是采用LC振荡回路作为移相和选频网络的正反馈振荡器。晶体振荡器的振荡频率受石英晶体控制。

    1.2.1 RC振荡器

    在这里插入图片描述

    1.2.2 晶体振荡器

    在这里插入图片描述

    1.3 STM32F0 时钟源介绍

    STM32中有四个时钟源

    • HSI:高速内部时钟,RC振荡器,频率为8KHz;
    • HSE:高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围4MHz-16MHz
    • LSI:低速内部时钟,RC振荡器,频率为40KHz。独立看门狗时钟源只能是这个时钟,还可以做RTC时钟源。
    • LSE:低速外部时钟,接32.768KHz的石英晶体。这个主要是RTC的时钟源。
      在这里插入图片描述
      控制时钟的寄存器是RCC

    2、Sys Tick定时器

    • 概念
      定时器:能够定时、计数的器件称为定时器。
      Sys Tick:系统滴答定时器,简称滴答定时器,是一个定是设备,位于Cortex-M0内核中,可以对输入的时钟进行计数,当然,如果时钟信号是周期性的,计数也就是计时。
      系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
    • 工作原理
      滴答定时器是一个24位定时器,也就是最多能计数2^24。在使用的时候,我们一般给计数器送一个初始的计数值,计数器向下计数,每来一个时钟信号,计数初值就减一,计数值减到0的时候,就会出发一次中断。然后重新从计数初值再减一计数,循环不断。
      在这里插入图片描述

    2.1 Sys Tick寄存器

    在这里插入图片描述在这里插入图片描述
    Sys Tick计数算法:假设设置的频率是48MHz,48M/1000 * 1/48MHz。

    基于系统的延时函数HAL_Dealy(),计时以毫秒为单位,它的局限性:在中断服务函数中使用HAL_Delay会引起混乱,因为它是通过中断方式实现,而 Systick 的中断一般操作系统优先级是最低的,所以在中断中运行 HAL_Delay会导致死锁的现象。

    3、通用定时器

    STM32F051xx 系列器件包括6个通用定时器,1个基本定时器和1个高级定时器。
    在这里插入图片描述
    通用定时器功能介绍

    • 通用定时器TIMx功能
      1)定时器定时计数
      2)输入捕获
      3)输出比较
      4)PWM输出
      5)使用外部信号控制定时器和定时器互连的同步电路
    • 高级定时器TIM1功能
      1)通用定时器有的功能
      2)带死区控制和紧急刹车,可用于PWM控制电机
    • 基本定时器TIM6功能
      主要运用于定时计数以及驱动DAC

    输入捕获:可以用来捕获外部事件,比如引脚的电平变化(上升沿、下降沿),并记录下变化的时间,通常可以用来测量外部信号的频率或者电平持续的时间。
    在这里插入图片描述
    输出比较: 此项功能是用来控制一个输出波形,当计数器与捕获/比较寄存器的内容相同时,输出比较功能做出相应动作,比如电平的翻转,通常用于产生PWM波形。
    在这里插入图片描述

    3.1 定时器计数模式

    在这里插入图片描述

    3.2 定时器计数原理

    在这里插入图片描述

    • 时钟源:定时器时钟 TIMxCLK,即内部时钟 CK_INT,经 APB 预分频器后分频提供
    • 计数器时钟:定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数
    • 计数器CNT: 是一个 16 位/32的计数器
    • 自动重装载寄存器:这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断
    • 计时中断时间:1/(TIMxCLK/(PSC+1)) * (ARR+1)
    展开全文
  • STM32开发 -- 时钟系统详解

    万次阅读 多人点赞 2020-03-19 10:59:33
    上一篇文章讲了RTC,里面其实已经包含了时钟系统的介绍了。这篇文章将再详细的讲一下。 一、时钟系统框图 二、时钟系统 STM32 有5个时钟源:HSI、HSE、LSI、LSE、PLL。 ①、HSI是高速内部...

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/81558649

    上一篇文章讲了RTC,里面其实已经包含了时钟系统的介绍了。这篇文章将再详细的讲一下。

    一、时钟系统框图

    这里写图片描述

    二、时钟系统

    1. STM32 有5个时钟源:HSI、HSE、LSI、LSE、PLL。
      ①、HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高。
      ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
      ③、LSI是低速内部时钟,RC振荡器,频率为40kHz,提供低功耗时钟。 
      ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
      ⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
    2. 系统时钟SYSCLK可来源于三个时钟源:
      ①、HSI振荡器时钟
      ②、HSE振荡器时钟
      ③、PLL时钟
    3. STM32可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。
    4. 任何一个外设在使用之前,必须首先使能其相应的时钟。

    三、RCC相关配置寄存器

            /** 
              * @brief Reset and Clock Control
              */
            typedef struct
            {
              __IO uint32_t CR;           // HSI,HSE,CSS,PLL等的使能和就绪标志位 
              __IO uint32_t CFGR;         // PLL等的时钟源选择,分频系数设定
              __IO uint32_t CIR;          // 清除/使能 时钟就绪中断
              __IO uint32_t APB2RSTR;     // APB2线上外设复位寄存器
              __IO uint32_t APB1RSTR;     // APB1线上外设复位寄存器
              __IO uint32_t AHBENR;       // DMA,SDIO等时钟使能
              __IO uint32_t APB2ENR;      // APB2线上外设时钟使能
              __IO uint32_t APB1ENR;      // APB1线上外设时钟使能
              __IO uint32_t BDCR;         // 备份域控制寄存器
              __IO uint32_t CSR;          // 控制状态寄存器
    
            #ifdef STM32F10X_CL  
              __IO uint32_t AHBRSTR;
              __IO uint32_t CFGR2;
            #endif /* STM32F10X_CL */ 
    
            #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)   
              uint32_t RESERVED0;
              __IO uint32_t CFGR2;
            #endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */ 
            } RCC_TypeDef;
    

    四、RCC相关头文件和固件库源文件

    所在文件:stm32f10x_rcc.c

    时钟使能配置:

         RCC_LSEConfig() 、RCC_HSEConfig()、
         RCC_HSICmd() 、 RCC_LSICmd() 、 RCC_PLLCmd() ……
    

    时钟源相关配置:

         RCC_PLLConfig ()、 RCC_SYSCLKConfig() 、
         RCC_RTCCLKConfig() …
    

    分频系数选择配置:

          RCC_HCLKConfig() 、 RCC_PCLK1Config() 、 RCC_PCLK2Config()…
    

    外设时钟使能:

         RCC_APB1PeriphClockCmd():  //APB1线上外设时钟使能
         RCC_APB2PeriphClockCmd();  //APB2线上外设时钟使能
         RCC_AHBPeriphClockCmd();   //AHB线上外设时钟使能
    

    其他外设时钟配置:

        RCC_ADCCLKConfig ();  RCC_RTCCLKConfig();
    

    状态参数获取参数:

         RCC_GetClocksFreq();
         RCC_GetSYSCLKSource();
         RCC_GetFlagStatus()
    

    RCC中断相关函数 :

        RCC_ITConfig() 、 RCC_GetITStatus() 、 RCC_ClearITPendingBit()…
    

    五、系统时钟初始化函数

    系统时钟初始化函数:SystemInit();
    我们在 STM32开发 – 启动流程 中讲过:

    使用V3.5版本的库函数,该函数在系统启动之后会自动调用:

    ; Reset handler
    Reset_Handler    PROC
                     EXPORT  Reset_Handler             [WEAK]
            IMPORT  SystemInit
            IMPORT  __main
                     LDR     R0, =SystemInit
                     BLX     R0
                     LDR     R0, =__main
                     BX      R0
                     ENDP
    

    系统复位后先执行SystemInit,再执行main函数
     通过修改SystemInit函数名称,可以自定义系统初始化过程

    在system_stm32f10x.c文件中找到SystemInit(void)源码:

    /**
      * @brief  Setup the microcontroller system
      *         Initialize the Embedded Flash Interface, the PLL and update the
      *         SystemCoreClock variable.
      * @note   This function should be used only after reset.
      * @param  None
      * @retval None
      */
    void SystemInit (void)
    {
      /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
      /* Set HSION bit */
      RCC->CR |= (uint32_t)0x00000001;    //RCC_CR寄存器最低位置1:打开HSI(内部高速时钟8M)
    
      /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
    #ifndef STM32F10X_CL
      RCC->CFGR &= (uint32_t)0xF8FF0000;
    #else                      //stm32f103ZET6为大容量芯片HD
      RCC->CFGR &= (uint32_t)0xF0FF0000;     //RCC_CFGR寄存器初始化
    #endif /* STM32F10X_CL */
    
      /* Reset HSEON, CSSON and PLLON bits */
      RCC->CR &= (uint32_t)0xFEF6FFFF;    //将RCC_CR寄存器HSEON,CSSON,PLLON位置0
    
      /* Reset HSEBYP bit */
      RCC->CR &= (uint32_t)0xFFFBFFFF;    //将RCC_CR寄存器HSEBYP位置0
    
      /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
      RCC->CFGR &= (uint32_t)0xFF80FFFF;   //将RCC_CFGR寄存器PLLSRC, PLLXTPRE,                         //PLLMUL,USBPRE/OTGFSPRE位置0
    
    #ifdef STM32F10X_CL
      /* Reset PLL2ON and PLL3ON bits */
      RCC->CR &= (uint32_t)0xEBFFFFFF;
    
      /* Disable all interrupts and clear pending bits  */
      RCC->CIR = 0x00FF0000;
    
      /* Reset CFGR2 register */
      RCC->CFGR2 = 0x00000000;
    #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
      /* Disable all interrupts and clear pending bits  */
      RCC->CIR = 0x009F0000;
    
      /* Reset CFGR2 register */
      RCC->CFGR2 = 0x00000000;
    #else                      //stm32f103ZET6为大容量芯片HD
      /* Disable all interrupts and clear pending bits  */
      RCC->CIR = 0x009F0000;        //关闭所有的中断和对应的位(初始化中断)
    #endif /* STM32F10X_CL */
    
    #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
      #ifdef DATA_IN_ExtSRAM
        SystemInit_ExtMemCtl();
      #endif /* DATA_IN_ExtSRAM */
    #endif
    
      /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
      /* Configure the Flash Latency cycles and enable prefetch buffer */
      SetSysClock();
    
    #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讲解
    参看:第一个函数SystemInit()里面有些啥

    RCC->CR |= (uint32_t)0x00000001;
    

    操作时钟控制寄存器,将内部8M高速时钟使能,从这里可以看出系统启动后是首先依靠内部时钟源而工作的。

    #ifndef STM32F10X_CL
      RCC->CFGR &= (uint32_t)0xF8FF0000;
    #else
      RCC->CFGR &= (uint32_t)0xF0FF0000;
    

    这两行代码则是操作时钟配置寄存器,其主要设置了MCO(微控制器时钟输出)PLL相关(PLL倍频系数,PLL输入时钟源),ADCPRE(ADC时钟),PPRE2(高速APB分频系数),PPRE1(低速APB分频系数),HPRE(AHB预分频系数),SW(系统时钟切换),开始时,系统时钟切换到HSI,由它作为系统初始化时钟。宏STM32F10X_CL是跟具体STM32芯片相关的一个宏。

     /* Reset HSEON, CSSON and PLLON bits */
      RCC->CR &= (uint32_t)0xFEF6FFFF;
     
      /* Reset HSEBYP bit */
      RCC->CR &= (uint32_t)0xFFFBFFFF;
     
      /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
      RCC->CFGR &= (uint32_t)0xFF80FFFF;
    

    这几句话则是在先关闭HSE、CSS、PLL等的情况下配置好与之相关参数然后开启,达到生效的目的。

    
    #ifdef STM32F10X_CL
      /* Reset PLL2ON and PLL3ON bits */
      RCC->CR &= (uint32_t)0xEBFFFFFF;
     
      /* Disable all interrupts and clear pending bits  */
      RCC->CIR = 0x00FF0000;
     
      /* Reset CFGR2 register */
      RCC->CFGR2 = 0x00000000;
    #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
      /* Disable all interrupts and clear pending bits  */
      RCC->CIR = 0x009F0000;
     
      /* Reset CFGR2 register */
      RCC->CFGR2 = 0x00000000;      
    #else
      /* Disable all interrupts and clear pending bits  */
      RCC->CIR = 0x009F0000;
    #endif /* STM32F10X_CL */
    

    这段主要是跟中断设置有关。开始时,我们需要禁止所有中断并且清除所有中断标志位。不同硬件有不同之处。

    
    #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
      #ifdef DATA_IN_ExtSRAM
        SystemInit_ExtMemCtl(); 
      #endif /* DATA_IN_ExtSRAM */
    #endif
    

    这段跟设置外部RAM有关。

    SetSysClock();
    

    此函数主要是配置系统时钟频率。HCLK,PCLK2,PCLK1的分频值,分别代表AHB,APB2,和APB1。当然还干了其它的事情,配置FLASH延时周期和使能预取缓冲区。

    /**
      * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
      * @param  None
      * @retval None
      */
    static void SetSysClock(void)
    {
    #ifdef SYSCLK_FREQ_HSE
      SetSysClockToHSE();
    #elif defined SYSCLK_FREQ_24MHz
      SetSysClockTo24();
    #elif defined SYSCLK_FREQ_36MHz
      SetSysClockTo36();
    #elif defined SYSCLK_FREQ_48MHz
      SetSysClockTo48();
    #elif defined SYSCLK_FREQ_56MHz
      SetSysClockTo56();  
    #elif defined SYSCLK_FREQ_72MHz
      SetSysClockTo72();
    #endif
     
     /* If none of the define above is enabled, the HSI is used as System clock
        source (default after reset) */ 
    }
    

    查看可得默认定义系统时钟为72MHz

    #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
    /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
     #define SYSCLK_FREQ_24MHz  24000000
    #else
    /* #define SYSCLK_FREQ_HSE    HSE_VALUE */
    /* #define SYSCLK_FREQ_24MHz  24000000 */ 
    /* #define SYSCLK_FREQ_36MHz  36000000 */
    /* #define SYSCLK_FREQ_48MHz  48000000 */
    /* #define SYSCLK_FREQ_56MHz  56000000 */
    #define SYSCLK_FREQ_72MHz  72000000
    #endif
    

    通过SystemCoreClock获取当前系统时钟频率

    /*******************************************************************************
    *  Clock Definitions
    *******************************************************************************/
    #ifdef SYSCLK_FREQ_HSE
      uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_24MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_36MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_48MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_56MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */
    #elif defined SYSCLK_FREQ_72MHz
      uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */
    #else /*!< HSI Selected as System Clock source */
      uint32_t SystemCoreClock         = HSI_VALUE;        /*!< System Clock Frequency (Core Clock) */
    #endif
    

    然后我们再看一下 SetSysClockTo72() 函数:

    /**
      * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2
      *          and PCLK1 prescalers.
      * @note   This function should be used only after reset.
      * @param  None
      * @retval None
      */
    static void SetSysClockTo72(void)
    {
      __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    
      /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
      /* Enable HSE */
      RCC->CR |= ((uint32_t)RCC_CR_HSEON);    //使能HSE:RCC_CR_HSEON=0x00010000(修改的是第16位HSEON)
    
      /* Wait till HSE is ready and if Time out is reached exit */
      do
      {
        HSEStatus = RCC->CR & RCC_CR_HSERDY;     //开启并就绪:RCC_CR_HSERDY=0x00020000(第17位HSERDY置1)
        StartUpCounter++;
      } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); //循环直到HSE稳定
    
      if ((RCC->CR & RCC_CR_HSERDY) != RESET)
      {
        HSEStatus = (uint32_t)0x01;               //就绪后赋值标志位HSEStatus
      }
      else
      {
        HSEStatus = (uint32_t)0x00;
      }
    
      if (HSEStatus == (uint32_t)0x01) //判断就绪
      {
        /* Enable Prefetch Buffer */
        FLASH->ACR |= FLASH_ACR_PRFTBE;
    
        /* Flash 2 wait state */
        FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
        FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;     //cpu的速度比芯片速度快的多        设置FLASH等待:两个等待状态
    
        /* HCLK = SYSCLK */
        RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//配置AHB预分频器分频系数为1,使HCLK = SYSCLK=72M
                                                                                          //RCC_CFGR_HPRE_DIV1=0x00000000(见手册)
    
        /* PCLK2 = HCLK */
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//配置PCLK2预分频器分频系数为1,使PCLK2 = HCLK=72M
                                                                                            //RCC_CFGR_PPRE2_DIV1=0x00000000(见手册)
        /* PCLK1 = HCLK/2 */
        RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//设置PCLK1预分频器分频系数为2,使PCLK1 = HCLK/2=36M
                                                                                           //RCC_CFGR_PPRE1_DIV2=0x00000400(见手册)
                                                                                           //RCC->CFGR第10,9,8位设置为100 (设置为2分频)
    #ifdef STM32F10X_CL
        /* Configure PLLs ------------------------------------------------------*/
        /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
        /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
    
        RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                                  RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
        RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                                 RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
    
        /* Enable PLL2 */
        RCC->CR |= RCC_CR_PLL2ON;
        /* Wait till PLL2 is ready */
        while((RCC->CR & RCC_CR_PLL2RDY) == 0)
        {
        }
    
        /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
        RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
        RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
                                RCC_CFGR_PLLMULL9);
    #else                         //stm32f103ZET6为大容量芯片HD
        /*  PLL configuration: 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);//HSE为时钟源且PLL倍频系数为9(8*9=72兆)
    #endif /* STM32F10X_CL */
    
        /* Enable PLL */
        RCC->CR |= RCC_CR_PLLON;          //使能PLL时钟,RCC->CR寄存器第24位置1
                              //RCC_CR_PLLON=0x01000000
    
        /* Wait till PLL is ready */
        while((RCC->CR & RCC_CR_PLLRDY) == 0)  //等待PLL时钟源就绪    
                                //RCC_CR_PLLRDYRCC->CR寄存器第25位
        {
        }
    
        /* Select PLL as system clock source */
        RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));//配置PLL作为系统时钟来源
        RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;        //RCC_CFGR_SW_PLL=0x00000002(RCC->CFGR第1,0位设置为10,见手册)
    
        /* Wait till PLL is used as system clock source */
        while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
        {
        }
      }
      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 */
      }
    }
    

    最后源码部分:

    #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. */
    
    

    这段代码主要是实现向量表的重定位。依据你想要将向量表定位在内部SRAM中还是内部FLASH中。这个SCB开始没在STM32参考手册中发现,原来它是跟Cortex-M3内核相关的东西。所以ST公司就没有把它包含进来吧。

    六、总结系统初始化函数流程

    这里写图片描述
     1,打开HSE,等待就绪后,设置Flash等待操作
     2,设置AHB,APB1,APB2分频系数,确定他们各自和系统时钟的关系
     3,设置CFGR寄存器确定PLL的时钟来源和倍频系数(HSE外部8M*9倍=72MHz)
     4,使能PLL,将系统时钟源切换到PLL

    注:
    APB(Advanced Peripheral Bus),片上外设总线。主要用于慢速片上外设与ARM核的通讯
    AHB(Advanced High performance Bus),高性能总线。主要用于系统高性能、高时钟速率模块间通信

    七、补充

    STM32F4 时钟初始化配置
    查看:SetSysClock函数

    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                       (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
    

    stm32f429系统时钟 180MHz:
    #define PLL_M 25
    #define PLL_Q 7
    #define PLL_N 360
    #define PLL_P 2
    外部晶振25MHz
    25360(252)=180MHz
    SYSCLK=25MHz * N/ (MP)=25MHz 360 /(25*2) = 180MHz

    stm32f407系统时钟 168MHz:
    #define PLL_M 8
    #define PLL_Q 7
    #define PLL_N 336
    #define PLL_P 2
    外部晶振8MHz
    SYSCLK=8MHz * N/ (MP)=8MHz 336 /(8*2) = 168MHz

    HSE_VALUE 的值为外部时钟:

    #if !defined (HSE_VALUE)
    #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
    #endif /* HSE_VALUE */
    

    STM32F429设置的时钟频率:

    • 系统时钟
      SYSCLK SYSCLK=PLLCLK=180MHz.
    • HCLK AHB总线时钟
      系统时钟SYSCLK经过AHB预分频器分频之后得到的时钟叫APB总线时钟,即HCLK,大部分外设的时钟都是经过HCLK分频得到,我们这里设置1分频HCLK=SYSCLK=180HMz。
    /* HCLK = SYSCLK / 1*/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
    
    • PCLK2 APB2总线时钟
      由HCLK经过高速APB2预分频器得到。HCLK2属于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如说全部的GPIO、USART、SPI等。至于APB2上的外设 的时钟设置位多少,得等到我们使用该外设的时候才设置,现在我们大致设置好APB2的时钟,这里设置为2分频,即PCLK2=HCLK/2=90MHz。
    /* PCLK2 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
    
    • PCLK1 APB1总线时钟
      由HCLK经过低俗APB预分频器得到。HCLK1属于低速的总线时钟,最高45HMz,低俗外设挂在到这条总线上,比如USART2/3/4/5、SPI2/3、I2C1/2等。这里设置为4分频,即PCLK1=HCLK/4=45MHz。
    /* PCLK1 = HCLK / 4*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
    

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/81558649

    展开全文
  • 时钟系统

    千次阅读 2016-08-02 20:32:47
    时钟系统需要理解其概念,然后会控制时钟系统即可。 时钟概念 时钟可以理解为一个根据同步节拍而进行同步工作的系统,Soc内部有CPU和一系列的内部和外部外设,这些都要同步的进行工作,需要有一个共同时钟系统...

    时钟系统需要理解其概念,然后会控制时钟系统即可。


    时钟概念

    时钟可以理解为一个根据同步节拍而进行同步工作的系统,Soc内部有CPU和一系列的内部和外部外设,这些都要同步的进行工作,需要有一个共同时钟系统来同步指挥,就Soc的时钟,时钟可以产生同步信号,来指挥CPU和外设进行同步工作。
    时钟可以从外部输入获得,例如通过引脚获得时钟频率,也可以通过外部晶振+内部时钟发生器,还可以添加内部PLL来产生高频时钟,添加内部分频器可以得到各种频率的时钟,S5PV210就是这种。
    一般情况下Soc的时钟频率是可以编程控制的,频率的高低对系统性能有很大影响,每个外设的工作都需要时钟,程序员可以为每个外设指定时钟来源和分频系数,从而配置该外设的时钟。
    Soc中设备工作时,时钟频率和发热,稳定性和功耗成正比,这些外设不用的时候最好关闭,以减小损耗和发热,而外设的开关就是控制其时钟的开断。

    S5PV210的时钟系统

    时钟域

    210内部的时钟分为三大块,MSYS域,DSYS域和PSYS域,由桥梁连接。

    MSYS

    主要包括CPU,MFD,3D,DMC,iRAM&iROM等时钟系统,工作在AXI200MHZ

    • ARMCLOCK,该时钟是给CPU内核工作的时钟,就是我们所说的主频
    • HCLOCK_MSYS,MSYS域的高频时钟,DMC使用
    • PCLOCK_MSYS,MSYS域的低频时钟
    • HCLOCK_IMEM,iROM和iRAM等iMemory使用的时钟

    DSYS

    主要包括FIMC,HDMI。JPEG等显示相关的外设时钟系统。

    • HCLOCK_DSYS,DSYS域的高频时钟
    • PCLOCK_DSYS,DSYS域的低频时钟

    PSYS

    主要包括各种内部外设,UART,LOWPOWER,MMC,I2C等

    • HCLOCK_PSYS,PSYS域的高频时钟
    • PCLOCK_PSYS,PSYS域的低频时钟
    • HCLOCK_ONENAND,

    210各个外设都是接在内部的AMBA总线上的,该总线由一条高频分支(AHB)和低频分支(APB),分别对应各个域的HCLOCK和PCLOCK,Soc内部每个外设是挂在总线上的,所以外设的时钟来自于所挂载的总线.

    时钟来源

    210外部有4个晶振接口,在USB处的晶振是最主要的时钟来源,结合内部的时钟发生器产生原始时钟,再经过PLL电路产生高频时钟,经过分频到达各个外设模块上。各模块内部还可以有分频器进行再次分频使用,比如串口。

    PLL

    • APLL:范围30MHG-1GHZ,MSYS域通常使用该PLL,
    • MPLL:范围50MHG-2GHZ,DSYS,PSYS和其他使用该PLL
    • EPLL:范围10MHG-600MHG,DSYS,PSYS和其他使用该PLL
    • VPLL:范围10MHG-600MHG,Video时钟使用该PLL

    各个时钟的默认值

    在iROM内部的BL0初始化PLL的时候,就是在设置各个时钟的默认值,所以210在上电时,是获得了24MHG的时钟,此时运行非常慢,BL0执行之后,由于初始化了PLL时钟系统,各个设备有了默认的时钟频率(由三星推荐的默认值),此时工作才会正常起来,210中典型默认值为:

    • freq(ARMCLK) = 1000 MHz
    • freq(HCLK_MSYS) = 200 MHz
    • freq(HCLK_IMEM) = 100 MHz
    • freq(PCLK_MSYS) = 100 MHz
    • freq(HCLK_DSYS) = 166 MHz
    • freq(PCLK_DSYS) = 83 MHz
    • freq(HCLK_PSYS) = 133 MHz
    • freq(PCLK_PSYS) = 66 MHz
    • freq(SCLK_ONENAND) = 133 MHz, 166 MHz

    时钟控制器

    时钟控制器控制图:
    时钟控制器控制图
    时钟详细分频图:
    时钟详细分频图
    MUX是时钟源控制器,由寄存器中的bit位来控制使用哪个来源的时钟,DIV是分频器,也是由寄存器中的bit位来控制,根据其分频系数范围,来将频率分为特定的值。

    控制器寄存器

    • xPLL_LOCK:控制PLL的锁定周期,
    • xPLL_CONn:控制PLL的开关,锁定状态获取以及设置PLL的倍频参数,
    • CLK_SRCn:设置时钟来源,对应图中的MUX开关,
    • CLK_MASKn:设置MUX开关对应的源的开关,
    • CLK_DIVn:分频参数设置
    • CLK_GATE_x:对时钟进行开关控制,控制最终输出时钟,
    • CLK_MUX/DIV_STATn:状态位,用于查看MUX和DIV的状态

    代码初始化时钟系统

    汇编实现

    // 时钟控制器基地址
    #define ELFIN_CLOCK_POWER_BASE      0xE0100000  
    
    // 时钟相关的寄存器相对时钟控制器基地址的偏移值
    #define APLL_LOCK_OFFSET        0x00        
    #define MPLL_LOCK_OFFSET        0x08
    
    #define APLL_CON0_OFFSET        0x100
    #define APLL_CON1_OFFSET        0x104
    #define MPLL_CON_OFFSET         0x108
    
    #define CLK_SRC0_OFFSET         0x200
    #define CLK_SRC1_OFFSET         0x204
    #define CLK_SRC2_OFFSET         0x208
    #define CLK_SRC3_OFFSET         0x20c
    #define CLK_SRC4_OFFSET         0x210
    #define CLK_SRC5_OFFSET         0x214
    #define CLK_SRC6_OFFSET         0x218
    #define CLK_SRC_MASK0_OFFSET    0x280
    #define CLK_SRC_MASK1_OFFSET    0x284
    
    #define CLK_DIV0_OFFSET         0x300
    #define CLK_DIV1_OFFSET         0x304
    #define CLK_DIV2_OFFSET         0x308
    #define CLK_DIV3_OFFSET         0x30c
    #define CLK_DIV4_OFFSET         0x310
    #define CLK_DIV5_OFFSET         0x314
    #define CLK_DIV6_OFFSET         0x318
    #define CLK_DIV7_OFFSET         0x31c
    
    #define CLK_DIV0_MASK           0x7fffffff
    
    // 这些M、P、S的配置值都是查数据手册中典型时钟配置值的推荐配置得来的。
    // 这些配置值是三星推荐的,因此工作最稳定。如果是自己随便瞎拼凑出来的那就要
    // 经过严格测试,才能保证一定对。
    #define APLL_MDIV               0x7d        // 125
    #define APLL_PDIV               0x3
    #define APLL_SDIV               0x1
    
    #define MPLL_MDIV               0x29b       // 667
    #define MPLL_PDIV               0xc
    #define MPLL_SDIV               0x1
    
    #define set_pll(mdiv, pdiv, sdiv)   (1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
    #define APLL_VAL            set_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
    #define MPLL_VAL            set_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
    
    
    .global clock_init
    clock_init:
        ldr r0, =ELFIN_CLOCK_POWER_BASE
    
        // 1 设置各种时钟开关,暂时不使用PLL
        ldr r1, =0x0
        // 芯片手册P378 寄存器CLK_SRC:Select clock source 0 (Main)
        str r1, [r0, #CLK_SRC0_OFFSET]              
    
        // 2 设置锁定时间,使用默认值即可
        // 设置PLL后,时钟从Fin提升到目标频率时,需要一定的时间,即锁定时间
        ldr r1, =0x0000FFFF                 
        str r1, [r0, #APLL_LOCK_OFFSET]             
        str r1, [r0, #MPLL_LOCK_OFFSET]                 
    
        // 3 设置分频
        // 清bit[0~31]
        ldr r1, [r0, #CLK_DIV0_OFFSET]                  
        ldr r2, =CLK_DIV0_MASK                  
        bic r1, r1, r2
        ldr r2, =0x14131440                     
        orr r1, r1, r2
        str r1, [r0, #CLK_DIV0_OFFSET]
    
        // 4 设置PLL
        // FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz
        ldr r1, =APLL_VAL                       
        str r1, [r0, #APLL_CON0_OFFSET]
        // FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz
        ldr r1, =MPLL_VAL                       
        str r1, [r0, #MPLL_CON_OFFSET]
    
        // 5 设置各种时钟开关,使用PLL
        ldr r1, [r0, #CLK_SRC0_OFFSET]
        ldr r2, =0x10001111
        orr r1, r1, r2
        str r1, [r0, #CLK_SRC0_OFFSET]
    
        mov pc, lr
    • 设置时钟开关,不使用PLL,这里先使用原始的24MHZ的原始时钟,来设置各个时钟的开关,这里设置了CLK_SRC0寄存器的bit0和bit4来达到作用
    • 设置锁定时间,设置为推荐的默认时间,设置CLK_LOCK寄存器,设置为0xFFFF就可以达到效果
    • 设置分频,分频系数决定由PLL出来的最高时钟由分频器来分频,设置CLK_DIV寄存器,值为0x14131440,
    • 设置PLL,设置PLL的倍频系数,决定由24MHZ可以得到多大的输出频率,默认主频是1GHZ,主要寄存器是xPLLCON,
    • 打开PLL,开启设定好的PLL,得到想要的频率,设置CLK_SRC,值设置为0x10001111就可以打开了
    展开全文
  • 具体得有:http://www.51hei.com/stm32/4155.html

    在这里插入图片描述

    在这里插入图片描述具体得有:http://www.51hei.com/stm32/4155.html

    展开全文
  • 什么是时钟系统? A:通常所说的系统时钟就是指时钟系统,它是由振荡器(信号源)、定时唤醒器、分频器等组成的电路。常用的信号源有晶体振荡器和RC振荡器。 2.Q:时钟系统有什么作用? A:时钟是嵌入式系统的脉搏,...
  • 时钟系统的作用 1.Q:什么是系统时钟?什么是时钟系统? A:通常所说的系统时钟就是指时钟系统,它是由振荡器(信号源)、定时唤醒器、分频器等组成的电路。常用的信号源有晶体振荡器和RC振荡器。 2.Q:时钟系统有什么...
  • 【STM32】系统时钟RCC详解(超详细,超全面)

    万次阅读 多人点赞 2020-09-02 10:57:19
    时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。 为什么 STM32 ...
  • STM32L4时钟系统(转载)

    2020-08-13 13:18:10
    时钟系统是 CPU 的脉搏,就像人的心跳一样。 STM32 本身非常复杂,外设非常的多,但是并不是所有外设都需要系统时钟这么高的频率。比如看门狗以及 RTC 只需要几十k的时钟即可。 同一个电路,时钟越快功耗越大,...
  • 实时时钟:RTC时钟,用于提供年、月、日、时、分、秒和星期等的实时时间信息,由后备电池供电,当你晚上关闭系统和早上开启系统时,RTC仍然会保持正确的时间和日期。 系统时钟:是一个存储于系统内存中的逻辑时钟...
  • 我自学了快一年的单片机,DIY过51、msp430、STM32,会做一些基本的小项目,也了解一点单片机的工作原理与结构,参加过2018年江苏省电子设计大赛,还获得了一等奖。...那么,我们就来了解一下时钟系统。 如今这...
  • STM32如何使用内部时钟源当系统时钟

    万次阅读 2014-10-07 12:28:30
    void RCC_Configuration(void) {  RCC_DeInit();//将外设 RCC寄存器重设为缺省值  RCC_HSICmd(ENABLE);//使能HSI  ... while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET)//等待HSI使能成功 ...
  • STM32系统时钟默认设置

    万次阅读 多人点赞 2017-08-15 20:01:22
    “我们一直都说STM32有一个非常复杂的时钟系统,然而在原子或者野火的例程中,只要涉及到时钟,我们却只能看到类似的库函数调用,如RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);...
  • 如何修改Linux系统时间 ubuntu

    万次阅读 2012-05-30 11:00:19
    如何修改Linux系统时间 ubuntu 两步 (1)date 102718362009 (2)hwclock -w 第一步的意思是设置时间,设置完了可以用date命令查看对不对...注意是月日时分年 第二步的意思是写入主板的rtc芯片.. ==========...
  • STM8S之时钟设置

    万次阅读 2015-06-25 17:31:49
    1,STM8S的4种时钟源可用做主时钟: ● 1-24MHz高速外部晶体振荡器(HSE) ● 最大24MHz高速外部时钟信号(HSE user-ext) ● 16MHz高速内部RC振荡器(HSI) ● 128KHz低速内部RC(LSI) 各个时钟源可单独打开或关闭,从而...
  • /sbin/hwclock 用于同步硬件时钟系统的时间与 Linux操作系统时间. 查看当前硬件时钟系统时间的命令为 /sbin/hwclock --show 将硬件时钟系统时间同步到 Linux操作系统时间的命令为 /sbin/hwclock --...
  • 修改linux 系统时间和硬件时间

    万次阅读 2018-01-10 20:53:12
    linux系统时钟有两个,一个是硬件时钟,即BIOS时间,另一个是系统时钟,是linux系统Kernel时间,程序运行时读取的时间是系统时间。当Linux启动时,系统Kernel会去读取硬件时钟的设置,然后系统时钟就会独立于硬件...
  • STM32 系统时钟的配置

    万次阅读 2017-04-27 09:06:19
    有三种不同的时钟源可被用来驱动系统时钟: ● 内部高速 (HSI)8MHz RC 振荡器时钟 ● 外部高速 (HSE) 振荡器时钟 ● PLL 时钟 2.系统时钟的简介 在STM32中,我们说要配置系统时钟就是指的配置下图标识红色...
  • 需求说明:FPGA基本知识 内容 :第一部分 FPGA各个时钟说明  第二部分 FPGA时钟... 第三部分 异步时钟同步化及门控时钟 来自 :时间的诗 第一部分 FPGA各个时钟说明 来自:http://blog.chinaunix.net/uid-
  • STM32使用内部时钟系统时钟

    千次阅读 2019-06-01 15:01:53
    最近刚开始接触STM32,因为项目中所使用的STM32没有外部晶振,再加上需要使用一些高频外设,所以说就只能...下图为STM32F10时钟系统框图以及相应说明: 下面为我参考STM32相应资料所写的系统时钟的初始化函数: ...
  • 最近stm32f103编程中遇到好多个问题,都是因为系统时钟配置不正确引起的 SYSCLOCK AHBCLK APB1CLK APB2CLK 这些时钟配置如果搞不清楚,很容易引起编程错误,查找起来也不方便,还有像flash读写操作,必须开启HSI内部...
1 2 3 4 5 ... 20
收藏数 201,264
精华内容 80,505
关键字:

时钟系统