代孕费用一般多少钱?

代孕费用【国内首家正规代孕】【薇信:13802269370】代孕是一种新的观念,新的趋势。在现今社会里人类文明高度发达,依然有不少不孕不育的夫妇。随着人工生殖科技的迅速发展,七十年代以来,欧美各国陆续开始有人委托代理孕母怀孕生子,代孕是一种解决不孕不育的临床选择。

一、在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
 
分类: 嵌入式

一、在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

猜你喜欢

转载自www.cnblogs.com/360wenda/p/9491477.html