时钟树的认识及固件库中时钟的配置

由开发板的原理图可知,开发板使用的外源晶振是8MHZ。接入到OSC_IN和OSC_OUT,同时,并不存在OSC32_IN和OSC32_OUT这俩个引脚,又有XTIN和XTOUT俩个引脚接了6MHZ的晶振。

在这里插入图片描述
1.HSE:高速的外部时钟,一般是8M的晶振
RCC时钟控制寄存器的位16,即HSEON:外部高速时钟使能
HSERDY:外部高速时钟就绪标志,当HSEON置1,使HSE使能, HSERDY也会置1,表示HSE已经就绪,可以进行下一步的配置。

2.HSI:高速的内部时钟,一般也是8M的晶振
RCC时钟控制寄存器的位0,即HSEON:外部高速时钟使能
HSERDY:外部高速时钟就绪标志,当HSION置1,使HSI使能, HSIRDY也会置1,表示HSE已经就绪,可以进行下一步的配置。
只有在HSE故障时,系统才会自动切换到HSI,直到HSE重新启动为止。

一般来说,HSE会经倍频之后设置为系统时钟,一般是9倍频,但如果HSE故障,自动切换到HSI时,并不会倍频,此时系统时钟只有8M,系统运行速度大大减缓,几乎瘫痪。

3.PLL_CLK:PLL_CLK一般是HSE在不分频的情况下,经倍频后产生的。由图可知,HSI必须是在2分频的情况下,才能进入PLL_MUL。最大16倍频之后也才4*16=64M,没有达到ST公司设置的最大时钟频率72M,所以,一般会选择HSE进入PLL_SRC,然后经倍频后产生PLL_CLK.
PLL_SRC:由时钟配置寄存器位16 PLLSRC来控制
PLL_MUL由时钟配置寄存器位[21:18] PLLMUL来控制

4.SYS_CLK可以看到,SYS_CLK是可以有3种路径来设置,HSI或HSE或PLL_CLK。一般选择PLL_CLK为系统时钟。
由时钟配置寄存器位[1:0] SW(系统时钟切换)来控制。
同样的也有SWS(系统时钟状态)会被相应的置位,用来读取当前时钟的状态是哪一个。

5.AHB:由图可以看出来,SYS_CLK出来之后是AHB预分频器,AHB预分频器之后是AHB设备,APB1预分频器,APB2预分频器。一般的,AHB不分频,是72M,由钟配置寄存器位[7:4] HPRE进行配置,APB1一般2分频,最大是36M,由钟配置寄存器位[10:8]PPRE1进行控制,APB2,最大是72M,由钟配置寄存器位[13:11]PPRE2进行控制.
值得注意的是,(1)APB2会为ADC提供时钟,会经ADC预分频器分频,ST规定最大只能是14M。但预分频器只是是2、4、6、8分频,因此,72M在分频后最大只能是12M,达不到最大值(2)预分频器之后,会有一个选择预分频系数,如果是1,则频率不变,如果不是1,则频率*2,一般,AHB、APB2的预分频系数为1,APB1为2,如此一来,他们所挂接的定时器的时钟仍然都是最大72M。

6.RTC为芯片内部RTC外设提供时钟。有3个来源。HSE经128分频后得到,或LSE,或LSI,此芯片没有HSE和HSI。
7.MCO微控制器时钟输出,一般是对PA8进行复用,然而开发板原理图中PA8引脚并没有复用,所以应该不存在。

了解了时钟树,接下来就应该了解固件库中怎么配置时钟,固件库中配置时钟的是system_stm32f10x.c文件。在startup_stm32f10x.s中有一句是LDR R0, =SystemInit,启动文件通过调用函数SystemInit()来配置时钟。而system_stm32f10x.c中的函数SystemInit()首先是配置RCC各个寄存器的值,最后会调用函数 SetSysClock()来初始化系统时钟。SetSysClock()中可以看出是根据不同的宏来调用不同的函数,查看宏定义,会发现,系统只定义了宏SYSCLK_FREQ_72MHz,这是因为ST官方定义72M是最大的最合适的时钟。其他的都被注释了,所以这里调用函数SetSysClockTo72(void);

SetSysClockTo72(void)是系统时钟配置函数,其中使用了#ifdef STM32F10X_CL;STM32F10X_CL是指互联型产品,而f103系列是基础性产品,因此,这个宏未定义,相应代码不会执行。
以下是SetSysClockTo72(void)的代码及注释,
//这里有俩句代码需要参考STM32F10xxx闪存编程参考手册

static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 的配置 */    
  /* 使能HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* 等待HSE启动就绪,并做超时处理*/
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;  
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));//HSE启动成功,跳出循环

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)//再次判断一下HSE是否启动
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }  

  if (HSEStatus == (uint32_t)0x01)//HSE启动确实成功了
  {
  /*如果HSE使能,表示系统时钟可以正常工作,那么,如果说时钟是开发板的心脏,指令就是开发板的血液,时钟驱动指令来带动整个开发板程序的正常执行。因此,当时钟使能以后,就需要配置指令的读取方式,指令在f103当中,是存放在Flash中的(f103是哈佛结构),因此,需要配置flash的寄存器*/
//STM32F10xxx闪存编程参考手册->  第3章 寄存器说明->   ACR寄存器
    /*使能  指令预取缓冲区 */
    FLASH->ACR |= FLASH_ACR_PRFTBE;//PRFTBE:预取缓冲区使能,是指是否使用指令预取功能

    /*设置时延 */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);//LATENCY:时延,这些位表示SYSCLK(系统时钟)周期与闪存访问时间的比例
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    //俩个等待状态

 //然后就该配置AHB、APNB1、APB2的预分频因子,
    /* HCLK = SYSCLK=72M */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK =72M*/
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK =36M*/
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//二分频
//这里已经删除了宏STM32F10X_CL部分的代码
    /*  PLL 锁相环时钟: PLLCLK = HSE * 9 = 72 MHz */
    //时钟配置寄存器(RCC_CFGR)的位[21:16]
    //这是在把HSE倍频9倍之后变成PLL_CLK,然后选择PLL_CLK成为系统时钟
    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);


    /*使能PLL */
    RCC->CR |= RCC_CR_PLLON;

    /*循环等待PLL设置稳定下来*/
    while((RCC->CR & RCC_CR_PLLRDY) == 0)//时钟控制寄存器(RCC_CR)的位25
    {
    }
    
    /* 选择PLL作为系统时钟 */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /*同样的,也需要等待PLL切换系统时钟变得稳定 */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  {
  	 /* 如果HSE启动失败,用户自己在这里添加错误处理代码*/
  }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值