zoukankan      html  css  js  c++  java
  • STM时钟

    一、在STM32中,有五个时钟源,为HSIHSELSILSEPLL

    HSI是高速内部时钟,RC振荡器,频率为8MHz。

    HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。

    LSI是低速内部时钟,RC振荡器,频率为40kHz。

    LSE是低速外部时钟,接频率为32.768kHz的石英晶体。

    PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。

    二、在STM32上如果不使用外部晶振,OSC_IN和OSC_OUT的接法:如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理:

    ①对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。
    ②对于少于100脚的产品,有2种接法:第1种:OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能;第2种:分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面)节省2个外部电阻。

    三、用HSE时钟,程序设置时钟参数流程
    01、将RCC寄存器重新设置为默认值   RCC_DeInit;
    02、打开外部高速时钟晶振HSE    RCC_HSEConfig(RCC_HSE_ON);
    03、等待外部高速时钟晶振工作    HSEStartUpStatus = RCC_WaitForHSEStartUp();
    04、设置AHB时钟         RCC_HCLKConfig;
    05、设置高速AHB时钟     RCC_PCLK2Config;
    06、设置低速速AHB时钟   RCC_PCLK1Config;
    07、设置PLL              RCC_PLLConfig;
    08、打开PLL              RCC_PLLCmd(ENABLE);
    09、等待PLL工作   while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    10、设置系统时钟        RCC_SYSCLKConfig;
    11、判断是否PLL是系统时钟     while(RCC_GetSYSCLKSource() != 0x08)
    12、打开要使用的外设时钟    RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()

    四、下面是STM32软件固件库的程序中对RCC的配置函数(使用外部8MHz晶振)

    /*******************************************************************************

    * Function Name  : RCC_Configuration 

    * Description    :  RCC配置(使用外部8MHz晶振)

    * Input            : 无

    * Output         : 无

    * Return         : 无

    *******************************************************************************/

    void RCC_Configuration(void)

    {

      /*将外设RCC寄存器重设为缺省值*/

      RCC_DeInit();

      /*设置外部高速晶振(HSE)*/

      RCC_HSEConfig(RCC_HSE_ON);   //RCC_HSE_ON——HSE晶振打开(ON)

      /*等待HSE起振*/

      HSEStartUpStatus = RCC_WaitForHSEStartUp();

      if(HSEStartUpStatus == SUCCESS)        //SUCCESS:HSE晶振稳定且就绪

      {

        /*设置AHB时钟(HCLK)*/ 

        RCC_HCLKConfig(RCC_SYSCLK_Div1);  //RCC_SYSCLK_Div1——AHB时钟= 系统时钟

        /* 设置高速AHB时钟(PCLK2)*/ 

        RCC_PCLK2Config(RCC_HCLK_Div1);   //RCC_HCLK_Div1——APB2时钟= HCLK

        /*设置低速AHB时钟(PCLK1)*/    

    RCC_PCLK1Config(RCC_HCLK_Div2);   //RCC_HCLK_Div2——APB1时钟= HCLK / 2

        /*设置FLASH存储器延时时钟周期数*/

        FLASH_SetLatency(FLASH_Latency_2);    //FLASH_Latency_2  2延时周期

     /*选择FLASH预取指缓存的模式*/  

        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);       // 预取指缓存使能

        /*设置PLL时钟源及倍频系数*/ 

        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);     

    // PLL的输入时钟= HSE时钟频率;RCC_PLLMul_9——PLL输入时钟x 9

      /*使能PLL */

        RCC_PLLCmd(ENABLE); 

        /*检查指定的RCC标志位(PLL准备好标志)设置与否*/   

        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)      

           {

           }

        /*设置系统时钟(SYSCLK)*/ 

        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 

    //RCC_SYSCLKSource_PLLCLK——选择PLL作为系统时钟

        /* PLL返回用作系统时钟的时钟源*/

        while(RCC_GetSYSCLKSource() != 0x08)        //0x08:PLL作为系统时钟

           { 

           }

         }

     /*使能或者失能APB2外设时钟*/    

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | 

    RCC_APB2Periph_GPIOC , ENABLE); 

    //RCC_APB2Periph_GPIOA    GPIOA时钟

    //RCC_APB2Periph_GPIOB    GPIOB时钟

    //RCC_APB2Periph_GPIOC    GPIOC时钟

    //RCC_APB2Periph_GPIOD    GPIOD时钟

    }

     

    RCC :reset clock control 复位和时钟控制器。主要讲解时钟部分,特别是要着重理解时钟树,理解了时钟树,STM32 的一切时钟的来龙去脉都会了如指掌。

    一、RCC主要作用——时钟部分 
    设置系统时钟SYSCLK、设置AHB分频因子(决定HCLK是多少)、设置APB2分频因子(设定PCLK2等于多少)、设置APB1分频因子(决定PCLK1等于多少);控制AHB/APB2/APB1这3条总线开启,控制每个外设时钟的开启。 
    对于SYSCLK、HCLK、PCLK2、PCLK1这4个时钟的配置一般是:PCLK2=HCLK=SYSCLK=PLLCLK=72MHz,PCLK1=HCLK/2=36MHz.这个配置是库函数的标准配置。


    二、系统时钟 
    STM32时钟树 
    系统时钟包括了: 
    1.HSE高速外部时钟(常用8MHz无源晶振); 
    2.PLL时钟源(来源有HSE和HSI/2,一般选HSE作为时钟来源); 
    3.PLL时钟PLLCLK(通过设置PLL的倍频因子,一般8Mx9=72MHz,72MHz是官方推荐稳定运行时钟,最高128MHz); 
    4.系统时钟SYSCLK(一般SYSCLK=PLLCLK=72MHz); 
    5.AHB总线时钟HCLK(是系统时钟SYSCLK经过AHB分频器分频后得到的时钟,也就是APB总线时钟,一般设置1分频,HCLK=SYSSCLK=72MHz); 
    6.APB2总线时钟HCLK2(APB2总线时钟PCLK2由 HCLK经过高速APB2预分频器得到,分频因子可以是:[1,2,4,8,16],具体由时钟配置寄存器CFGR的位13-11:PPRE2[2:0]决定,一般设置为 1 分频,即 PCLK2 = HCLK =72M); 
    7.APB1总线时钟HCLK1(APB1 总线时钟 PCLK1 由 HCLK 经过低速 APB 预分频器得到,HCLK1 属于低速的总线时钟,最高为 36M,这里只需粗线条的设置好 APB1 的时钟即可。我们这里设置为 2分频,即 PCLK1 = HCLK/2 = 36M)设置系统时钟函数在库函数system_stm32f10x.c

                                        代码清单:设置系统时钟库函数
    
    1 static void SetSysClockTo72(void)
    2 {
    3 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
    4 
    5 // ① 使能 HSE,并等待 HSE 稳定 
    6 RCC->CR |= ((uint32_t)RCC_CR_HSEON);
    7 
    8 // 等待 HSE 启动稳定,并做超时处理 
    9 do {
    10 HSEStatus = RCC->CR & RCC_CR_HSERDY;
    11 StartUpCounter++;
    12 } while ((HSEStatus == 0) &&(StartUpCounter !=HSE_STARTUP_TIMEOUT));
    13 
    14 if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
    15 HSEStatus = (uint32_t)0x01;
    16 } else {
    17 HSEStatus = (uint32_t)0x00;
    18 }
    19 // HSE 启动成功,则继续往下处理 
    20 if (HSEStatus == (uint32_t)0x01) {
    21
    22 //-----------------------------------------------------------
    23 // 使能 FLASH 预存取缓冲区 */
    24 FLASH->ACR |= FLASH_ACR_PRFTBE;
    25 
    26 // SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
    27 // 设置成 2 的时候,SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
    28 // 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
    29 // 0:0 < SYSCLK <= 24M
    30 // 1:24< SYSCLK <= 48M
    31 // 2:48< SYSCLK <= 72M */
    32 FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    33 FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
    34 //------------------------------------------------------------
    35 
    36 // ② 设置 AHB、APB2、APB1 预分频因子
    37 // HCLK = SYSCLK
    38 RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
    39 //PCLK2 = HCLK
    40 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    41 //PCLK1 = HCLK/2
    42 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
    43 
    44 //③ 设置 PLL 时钟来源,设置 PLL 倍频因子,PLLCLK = HSE * 9 = 72 MHz
    45 RCC->CFGR &= (uint32_t)((uint32_t)
    46 ~(RCC_CFGR_PLLSRC
    47 | RCC_CFGR_PLLXTPRE
    48 | RCC_CFGR_PLLMULL));
    49 RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
    50 | RCC_CFGR_PLLMULL9);
    51 
    52 // ④ 使能 PLL
    53 RCC->CR |= RCC_CR_PLLON;
    54 
    55 // ⑤ 等待 PLL 稳定
    56 while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
    57 }
    58 
    59 // ⑥ 选择 PLL 作为系统时钟来源
    60 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    61 RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
    62 
    63 // ⑦ 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
    64 while ((RCC->CFGR&(uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){
    65 }
    66 } else {// 如果 HSE 启动失败,用户可以在这里添加错误代码出来
    67 }
    68 }

    三、其他时钟 
    1. USB时钟 
    USB 时钟是由 PLLCLK 经过 USB 预分频器得到,分频因子可以是:[1,1.5],具体的由时钟配置寄存器 CFGR的位 22:USBPRE配置。USB的时钟最高是 48M,根据分频因子反推过来算 ,PLLCLK 只 能 是 48M 或 者 是 72M。 一 般我 们 设 置 PLLCLK=72M ,USBCLK=48M。USB 对时钟要求比较高,所以 PLLCLK 只能是由 HSE 倍频得到,不能使用 HSI倍频。 
    2. Cortex系统时钟 
    Cortex 系统时钟由 HCLK 8 分频得到,等于 9M,Cortex 系统时钟用来驱动内核的系统定时器 SysTick,SysTick 一般用于操作系统的时钟节拍,也可以用做普通的定时。 
    3. ADC时钟 
    ADC时钟由PCLK2经过ADC预分频器得到,分频因子可以是[2,4,6,8],具体的由时钟配置寄存器 CFGR的位 15-14:ADCPRE[1:0]决定。很奇怪的是怎么没有 1分频。ADC时钟最高只能是 14M,如果采样周期设置成最短的 1.5 个周期的话,ADC 的转换时间可以达到最短的 1us。如果真要达到最短的转换时间 1us 的话,那 ADC 的时钟就得是 14M,反推PCLK2 的时钟只能是:28M、56M、84M、112M,鉴于 PCLK2 最高是 72M,所以只能取28M和 56M。 
    4. RTC时钟、独立看门狗时钟 
    RTC 时钟可由 HSE/128 分频得到,也可由低速外部时钟信号 LSE 提供,频率为32.768KHZ,也可由低速内部时钟信号 HSI 提供,具体选用哪个时钟由备份域控制寄存器BDCR的位9-8:RTCSEL[1:0]配置。独立看门狗的时钟由LSI提供,且只能是由LSI提供,LSI是低速的内部时钟信号,频率为 30~60KHZ直接不等,一般取 40KHZ。 
    5. MCO时钟输出 
    MCO 是 microcontroller clock output 的缩写,是微控制器时钟输出引脚,在 STM32 F1系列中 由 PA8 复用所得,主要作用是可以对外提供时钟,相当于一个有源晶振。MCO 的时钟来源可以是:PLLCLK/2、HSI、HSE、SYSCLK,具体选哪个由时钟配置寄存器CFGR的位 26-24:MCO[2:0]决定。除了对外提供时钟这个作用之外,我们还可以通过示波器监控 MCO引脚的时钟输出来验证我们的系统时钟配置是否正确。


    四、如何配置系统时钟 
    1、使用HSE 
    将HSE经过PLL倍频之后作为系统时钟,通常的配置是:HSE=8MHz,PLL的倍频因子为9,系统时钟SYSCLK=72MHz。在程序来到main函数之前,启动文件statup_stm32f10x_hd.s已经调用SystemInit()函数,把系统时钟初始化为72MHz,SystemInit()函数在库文件system_stm32f10x.c中定义。 
    2.使用HSI 
    如果PLL的时钟来源是HSE,那么当HSE故障时,不仅HSE不能使用,连PLL也会关闭,此时系统会自动切换HSI为系统时钟,此时SYSCLK=HSI=8MHz,如果没有开启CSS和CSS中断的话,整个系统只能在低速率运行,跟系统瘫痪没什么两样。如果开启了CSS,当HSE故障,可以在CSS中断中采取补救措施,使用HSI,并把系统时钟设置为更高的频率,最高是64MHz,一般足够使用如ADC/SPI等,但是思考原来SYSCLK=72MHz,现在外设时钟肯定都变了,外设工作会被打乱。我们是不是在设置 HSI 时钟的时候,也重新调整外设总线的分频因 
    子,即 AHB,APB2 和 APB1 的分频因子,使外设的时钟达到跟 HSE 没有故障之前一样。但是这个也不是最保障的办法,毕竟不能一直使用 HSI,所以当 HSE 故障时还是要采取报警措施。 
    还有一种情况是,有些用户不想用 HSE,想用 HSI,但是又不知道怎么用 HSI 来设置系统时钟,因为调用库函数都是使用 HSE,下面我们给出个使用 HSI 配置系统时钟例子。

                                    代码清单:HSE作为系统时钟来源
    
    1 void HSE_SetSysClock(uint32_t pllmul)
    2 {
    3 __IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;
    4 
    5 // 把 RCC 外设初始化成复位状态,这句是必须的
    6 RCC_DeInit();
    7 
    8 //使能 HSE,开启外部晶振, STM32F103 系列开发板用的是 8M
    9 RCC_HSEConfig(RCC_HSE_ON);
    10 
    11 // 等待 HSE 启动稳定
    12 HSEStartUpStatus = RCC_WaitForHSEStartUp();
    13 
    14 // 只有 HSE 稳定之后则继续往下执行
    15 if (HSEStartUpStatus == SUCCESS) {
    16 //-----------------------------------------------------------------//
    17
    18 // 使能 FLASH 预存取缓冲区
    19 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    20 
    21 // SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
    22 // 设置成 2 的时候,SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
    23 // 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
    24 // 0:0 < SYSCLK <= 24M
    25 // 1:24< SYSCLK <= 48M
    26 // 2:48< SYSCLK <= 72M
    27 FLASH_SetLatency(FLASH_Latency_2);
    28 //-----------------------------------------------------------------//
    29 
    30 // AHB 预分频因子设置为 1 分频,HCLK = SYSCLK
    31 RCC_HCLKConfig(RCC_SYSCLK_Div1);
    32 
    33 // APB2 预分频因子设置为 1 分频,PCLK2 = HCLK
    34 RCC_PCLK2Config(RCC_HCLK_Div1);
    35 
    36 // APB1 预分频因子设置为 1 分频,PCLK1 = HCLK/2
    37 RCC_PCLK1Config(RCC_HCLK_Div2);
    38 
    39 //-----------------设置各种频率主要就是在这里设置-------------------//
    40 // 设置 PLL 时钟来源为 HSE,设置 PLL 倍频因子
    41 // PLLCLK = 8MHz * pllmul
    42 RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
    43 //-------------------------------------------------------------//
    44 
    45 // 开启 PLL
    46 RCC_PLLCmd(ENABLE);
    47 
    48 // 等待 PLL 稳定
    49 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
    50 }
    51 
    52 // 当 PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK
    53 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    54 
    55 // 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
    56 while (RCC_GetSYSCLKSource() != 0x08) {
    57 }
    58 } else {
    59 // 如果 HSE 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
    60 // 当 HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,
    61 // HSI 是内部的高速时钟,8MHZ
    62 while (1) {
    63 }
    64 }
    65 }

    这个函数采用库函数编写,有个形参pllmul,用来设置PLL的倍频因子,调用的时候形参可以是:RCC_PLLMul_x , x:[2,3,…16],这些宏来源于库函数的定义,宏展开是一些 32 位的十六进制数,具体功能是配置了时钟配置寄存器 CFGR 的位 21-18PLLMUL[3:0],预先定义好倍频因子,方便调用。 
    函数调用举例:HSE_SetSysClock(RCC_PLLMul_9); 则设置系统时钟为:8MHZ * 9 =72MHZ。 HSE_SetSysClock(RCC_PLLMul_16); 则设置系统时钟为:8MHZ * 16 = 128MHZ超频慎用。

                                        代码清单:HSI作为系统时钟来源
    
    1 void HSI_SetSysClock(uint32_t pllmul)
    2 {
    3 __IO uint32_t HSIStartUpStatus = 0;
    4 
    5 // 把 RCC 外设初始化成复位状态,这句是必须的
    6 RCC_DeInit();
    7 
    8 //使能 HSI
    9 RCC_HSICmd(ENABLE);
    10 
    11 // 等待 HSI 就绪
    12 HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY;
    13 
    14 // 只有 HSI 就绪之后则继续往下执行
    15 if (HSIStartUpStatus == RCC_CR_HSIRDY) {
    16 //-------------------------------------------------------------//
    17
    18 // 使能 FLASH 预存取缓冲区
    19 FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
    20 
    21 // SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
    22 // 设置成 2 的时候,SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
    23 // 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
    24 // 0:0 < SYSCLK <= 24M
    25 // 1:24< SYSCLK <= 48M
    26 // 2:48< SYSCLK <= 72M
    27 FLASH_SetLatency(FLASH_Latency_2);
    28 //------------------------------------------------------------//
    29 
    30 // AHB 预分频因子设置为 1 分频,HCLK = SYSCLK
    31 RCC_HCLKConfig(RCC_SYSCLK_Div1);
    32 
    33 // APB2 预分频因子设置为 1 分频,PCLK2 = HCLK
    34 RCC_PCLK2Config(RCC_HCLK_Div1);
    35 
    36 // APB1 预分频因子设置为 1 分频,PCLK1 = HCLK/2
    37 RCC_PCLK1Config(RCC_HCLK_Div2);
    38 
    39 //-----------设置各种频率主要就是在这里设置-------------------//
    40 // 设置 PLL 时钟来源为 HSE,设置 PLL 倍频因子
    41 // PLLCLK = 4MHz * pllmul
    42 RCC_PLLConfig(RCC_PLLSource_HSI_Div2, pllmul);
    43 //-- -----------------------------------------------------//
    44 
    45 // 开启 PLL
    46 RCC_PLLCmd(ENABLE);
    47 
    48 // 等待 PLL 稳定
    49 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
    50 }
    51 
    52 // 当 PLL 稳定之后,把 PLL 时钟切换为系统时钟 SYSCLK
    53 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    54 
    55 // 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
    56 while (RCC_GetSYSCLKSource() != 0x08) {
    57 }
    58 } else {
    59 // 如果 HSI 开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
    60 // 当 HSE 开启失败或者故障的时候,单片机会自动把 HSI 设置为系统时钟,
    61 // HSI 是内部的高速时钟,8MHZ
    62 while (1) {
    63 }
    64 }
    65 }

    HSI 设置系统时钟函数跟 HSE 设置系统时钟函数在原理上是一样的,有一个区别的地方就是,HSI 必须 2 分频之后才能作为 PLL 的时钟来源,所以使用 HSI 时,最大的系统时钟 SYSCLK只能是 HSI/2*16=4*16=64MHZ。 
    函数调用举例:HSI_SetSysClock(RCC_PLLMul_9); 则设置系统时钟为:4MHZ * 9 =36MHZ。

    3、MCO输出 
    在STM32F103中,PA8可以复用为MCO的引脚,对外提供时钟输出,也可以用示波器监控该引脚输出判断系统时钟是否设置正确。

                                            代码清单:MCO初始化
    
    1 /*
    2 * 初始化 MCO 引脚 PA8
    3 * 在 F103 系列中 MCO 引脚只有一个,即 PA8,在 F4 系列中,MCO 引脚有两个
    4 */
    5 void MCO_GPIO_Config(void)
    6 {
    7 GPIO_InitTypeDef GPIO_InitStructure;
    8 // 开启 GPIOA 的时钟
    9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    10 
    11 // 选择 GPIO8 引脚
    12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    13 
    14 //设置为复用功能推挽输出
    15 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    16 
    17 //设置 IO 的翻转速率为 50M
    18 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    19 
    20 // 初始化 GPIOA8
    21 GPIO_Init(GPIOA, &GPIO_InitStructure);
    22 }
                                            代码清单:MCO输出时钟选择
    
    1 // 设置 MCO 引脚输出时钟,用示波器即可在 PA8 测量到输出的时钟信号,
    2 // 我们可以把 PLLCLK/2 作为 MCO 引脚的时钟来检测系统时钟是否配置准确
    3 // MCO 引脚输出可以是 HSE,HSI,PLLCLK/2,SYSCLK
    4 //RCC_MCOConfig(RCC_MCO_HSE);
    5 //RCC_MCOConfig(RCC_MCO_HSI);
    6 //RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
    7 RCC_MCOConfig(RCC_MCO_SYSCLK);

    初始化MCO引脚后,可以直接调用库函数RCC_MCOConfig()来选择MCO时钟来源。

                                                代码清单:main
    
    1 int main(void)
    2 {
    3 // 程序来到 main 函数之前,启动文件:statup_stm32f10x_hd.s 已经调用
    4 // SystemInit()函数把系统时钟初始化成 72MHZ
    5 // SystemInit()在 system_stm32f10x.c 中定义
    6 // 如果用户想修改系统时钟,可自行编写程序修改
    7 
    8 // 重新设置系统时钟,这时候可以选择使用 HSE 还是 HSI
    9 
    10 // 使用 HSE 时,SYSCLK = 8M * RCC_PLLMul_x, x:[2,3,...16],最高是 128M
    11 HSE_SetSysClock(RCC_PLLMul_9);
    12 
    13 // 使用 HSI 时,SYSCLK = 4M * RCC_PLLMul_x, x:[2,3,...16],最高是 64MH
    14 //HSI_SetSysClock(RCC_PLLMul_16);
    15 
    16 // MCO 引脚初始化
    17 MCO_GPIO_Config();
    18 
    19 // 设置 MCO 引脚输出时钟,用示波器即可在 PA8 测量到输出的时钟信号,
    20 // 我们可以把 PLLCLK/2 作为 MCO 引脚的时钟来检测系统时钟是否配置准确
    21 // MCO 引脚输出可以是 HSE,HSI,PLLCLK/2,SYSCLK
    22 //RCC_MCOConfig(RCC_MCO_HSE);
    23 //RCC_MCOConfig(RCC_MCO_HSI);
    24 //RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);
    25 RCC_MCOConfig(RCC_MCO_SYSCLK);
    26 
    27 // LED 端口初始化
    28 LED_GPIO_Config();
    29 while (1) {
    30 LED1( ON ); // 亮
    31 Delay(0x0FFFFF);
    32 LED1( OFF ); // 灭
    33 Delay(0x0FFFFF);
    34 }
    35 }

    在main中,可以调用HSE_SetSysClock()或者HSI_SetSysClock()这两个函数把系统时钟设置成为各种常用的时钟,然后通过MCO引脚监控 ,或者通过LED闪烁的快慢体验不同的系统时钟对同一软件延时函数的影响。

    参考:
    https://blog.csdn.net/zxh1592000/article/details/78644121
    https://blog.csdn.net/kevinhg/article/details/17517117
  • 相关阅读:
    【leetcode】1215.Stepping Numbers
    【leetcode】1214.Two Sum BSTs
    【leetcode】1213.Intersection of Three Sorted Arrays
    【leetcode】1210. Minimum Moves to Reach Target with Rotations
    【leetcode】1209. Remove All Adjacent Duplicates in String II
    【leetcode】1208. Get Equal Substrings Within Budget
    【leetcode】1207. Unique Number of Occurrences
    【leetcode】689. Maximum Sum of 3 Non-Overlapping Subarrays
    【leetcode】LCP 3. Programmable Robot
    【leetcode】LCP 1. Guess Numbers
  • 原文地址:https://www.cnblogs.com/zzdbullet/p/9485912.html
Copyright © 2011-2022 走看看