STM32
直播中

ejlwj

9年用户 961经验值
擅长:处理器/DSP
私信 关注
[问答]

STM32f103的时钟有哪几个来源?

STM32f103的时钟有哪几个来源?

回帖(1)

黄飞高

2021-11-23 10:50:45
STM32f103的时钟有四个来源
高速外部时钟信号(HSE)、低速外部时钟信号(LSE)、高速内部时钟信号(HSI)和低速内部时钟信号(LSI),图中分别用蓝色的①~④标注。
①HSE高速外部时钟:由外部4~16MHz的晶体或有源晶振提供,通常采用8MHz,ST三合一板上的也是8MHz。
②LSI低速外部时钟:外部晶体提供,主要是给实时时钟(RTC),一般为32.768kHz。
③HSI高速内部时钟:由内部RC振荡器产生的8MHz时钟,但不够稳定。④LSI低速内部时钟:内部RC振荡器产生的供给RTC的时钟,频率在30kHz~60kHz之间,通常约40kHz。





时钟在STM32内部最终是供给四大块,图中用红色椭圆圈出——USB的48MHz时钟、系统时钟SYSCLK、实时时钟模块RTC、独立看门狗的时钟IWDGCLK。其中最主要的,也是最大头是系统时钟SYSCLK,它可以是内部或外部高速时钟直接接过来,也可以内、外部高速时钟是PLL倍频后提供的,系统时钟再分别供给Cortex内核、SDIO、AHB总线、DMA、APB1、APB2等。

8MHz外部晶体(或晶振)输入后,先经过一个开关PLLXTPRE(HSE divider for PLL entry),此开关决定对HSE进行2分频再输入到PLL或直接到PLL
第二个开关PLLSRC(PLL entry clock source),此开关决定PLL的时钟来源,是内部高速时钟二分频的时钟还是PLLXTPRE的输出。
到了PLL倍频器,由PLLMUL决定倍频系统数,可以选择2~16倍频输出,但记住,PLL输出频率最高72MHz,所以我们选择9倍频,这样PLL输出就是最高72MHz的PLLCLK时钟了。这时的PLLCLK为USB提供时钟。
开关SW来决定SYSCLK的时钟来源,前面已经提到,这里我们由PLLCLK做为SYSCLK的来源,这样系统时钟SYSCLK就是72MHz了。
查看用户手册,控制时钟的寄存器



















正点原子sys.c文件,时钟初始化的函数


//不能在这里执行所有外设复位!否则至少引起串口不工作.                    
//把所有时钟寄存器复位                  
void MYRCC_DeInit(void)
{       
        RCC->APB1RSTR = 0x00000000;//复位结束                         
        RCC->APB2RSTR = 0x00000000;
          
  RCC->AHBENR = 0x00000014;  //睡眠模式闪存和SRAM时钟使能.其他关闭.          
  RCC->APB2ENR = 0x00000000; //外设时钟关闭.                          
  RCC->APB1ENR = 0x00000000;   
        RCC->CR |= 0x00000001;     //使能内部高速时钟HSION                                                                                                                                  
        RCC->CFGR &= 0xF8FF0000;   //复位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]                                         
        RCC->CR &= 0xFEF6FFFF;     //复位HSEON,CSSON,PLLON
        RCC->CR &= 0xFFFBFFFF;     //复位HSEBYP                     
        RCC->CFGR &= 0xFF80FFFF;   //复位PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE
        RCC->CIR = 0x00000000;     //关闭所有中断                 
        //配置向量表                                  
#ifdef  VECT_TAB_RAM
        MY_NVIC_SetVectorTable(0x20000000, 0x0);
#else   
        MY_NVIC_SetVectorTable(0x08000000,0x0);
#endif
}
//系统时钟初始化函数
//pll:选择的倍频数,从2开始,最大值为16                 
void Stm32_Clock_Init(u8 PLL)
{
        unsigned char temp=0;   
        MYRCC_DeInit();                  //复位并配置向量表
       
        RCC->CR|=0x00010000;  //外部高速时钟使能HSEON
       
        while(!(RCC->CR>>17));//等待外部时钟就绪
        RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
        PLL-=2;                                  //抵消2个单位(因为是从2开始的,设置0就是2)
        RCC->CFGR|=PLL<<18;   //设置PLL值 2~16
        RCC->CFGR|=1<<16;          //PLLSRC ON
        FLASH->ACR|=0x32;          //FLASH 2个延时周期
        RCC->CR|=0x01000000;  //PLLON
        while(!(RCC->CR>>25));//等待PLL锁定
       
        RCC->CFGR|=0x00000002;//PLL作为系统时钟         
        while(temp!=0x02)     //等待PLL作为系统时钟设置成功
        {   
                temp=RCC->CFGR>>2;
                temp&=0x03;
        }   
}
野火开发板的系统时钟初始化源码


/**
  * @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;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
  RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* 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;

#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

  /* 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
}


两份源码对比,
第一步 CR寄存器 代码操作时钟控制寄存器,将内部8M高速时钟使能,从这里可以看出系统启动后是首先依靠内部时钟源而工作的。
第二步 CFGR寄存器 设置了MCO(微控制器时钟输出)PLL相关(PLL倍频系数,PLL输入时钟源),ADCPRE(ADC时钟),PPRE2(高速APB分频系数),PPRE1(低速APB分频系数),HPRE(AHB预分频系数),SW(系统时钟切换),开始时,系统时钟切换到HSI,由它作为系统初始时钟宏STM32F10X_CL是跟具体STM32芯片相关的一个宏。
第三步 CR寄存器 将RCC_CR寄存器HSEON,CSSON,PLLON位置0,HSEBYP位置0
第四步  主要是跟中断设置有关。开始时,我们需要禁止所有中断并且清除所有中断标志位。不同硬件有不同之处











407比103复杂,但过程还是一样。

f407时钟初始化函数


//时钟设置函数
//Fvco=Fs*(plln/pllm);
//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));
//Fu***=Fvco/pllq=Fs*(plln/(pllm*pllq));

//Fvco:VCO频率
//Fsys:系统时钟频率
//Fu***:USB,SDIO,RNG等的时钟频率
//Fs:PLL输入时钟频率,可以是HSI,HSE等.
//plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
//pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
//pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
//pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.

//外部晶振为8M的时候,推荐值:plln=336,pllm=8,pllp=2,pllq=7.
//得到:Fvco=8*(336/8)=336Mhz
//     Fsys=336/2=168Mhz
//     Fu***=336/7=48Mhz
//返回值:0,成功;1,失败。
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
        u16 retry=0;
        u8 status=0;
        RCC->CR|=1<<16;                                //HSE 开启
        while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//等待HSE RDY
        if(retry==0X1FFF)status=1;        //HSE无法就绪
        else   
        {
                RCC->APB1ENR|=1<<28;        //电源接口时钟使能
                PWR->CR|=3<<14;                 //高性能模式,时钟可到168Mhz
                RCC->CFGR|=(0<<4)|(5<<10)|(4<<13);//HCLK 不分频;APB1 4分频;APB2 2分频.
                RCC->CR&=~(1<<24);        //关闭主PLL
                RCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);//配置主PLL,PLL时钟源来自HSE
                RCC->CR|=1<<24;                        //打开主PLL
                while((RCC->CR&(1<<25))==0);//等待PLL准备好
                FLASH->ACR|=1<<8;                //指令预取使能.
                FLASH->ACR|=1<<9;                //指令cache使能.
                FLASH->ACR|=1<<10;                //数据cache使能.
                FLASH->ACR|=5<<0;                //5个CPU等待周期.
                RCC->CFGR&=~(3<<0);                //清零
                RCC->CFGR|=2<<0;                //选择主PLL作为系统时钟         
                while((RCC->CFGR&(3<<2))!=(2<<2));//等待主PLL作为系统时钟成功.
        }
        return status;
}  
//系统时钟初始化函数
//plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
//pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
//pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
//pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{  
        RCC->CR|=0x00000001;                //设置HISON,开启内部高速RC振荡
        RCC->CFGR=0x00000000;                //CFGR清零
        RCC->CR&=0xFEF6FFFF;                //HSEON,CSSON,PLLON清零
        RCC->PLLCFGR=0x24003010;        //PLLCFGR恢复复位值
        RCC->CR&=~(1<<18);                        //HSEBYP清零,外部晶振不旁路
        RCC->CIR=0x00000000;                //禁止RCC时钟中断
        Sys_Clock_Set(plln,pllm,pllp,pllq);//设置时钟
        //配置向量表                                  
#ifdef  VECT_TAB_RAM
        MY_NVIC_SetVectorTable(1<<29,0x0);
#else   
        MY_NVIC_SetVectorTable(0,0x0);
#endif
}


              分析函数,Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz
//系统时钟初始化函数
//plln:主PLL倍频系数(PLL倍频),取值范围:64~432.
//pllm:主PLL和音频PLL分频系数(PLL之前的分频),取值范围:2~63.
//pllp:系统时钟的主PLL分频系数(PLL之后的分频),取值范围:2,4,6,8.(仅限这4个值!)
//pllq:USB/SDIO/随机数产生器等的主PLL分频系数(PLL之后的分频),取值范围:2~15.
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
plln=336
pllm=8
pllp=2
pllq=7






    RCC->CR|=1<<16;                //HSE 开启
    while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//等待HSE RDY
    if(retry==0X1FFF)status=1;    //HSE无法就绪
使用HSE,外部高速时钟作为时钟源,8MHz,经过M分频,8M/pllm=1M,N倍频,1M*plln=336M,P分频,336M/2=168M。
则,pll经过倍频,pll时钟源为168MHz。可选做系统时钟SYSCLK。再经过APB分频,2分频得84M,4分频得42M。
然后开启时钟使能,可使用。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分