深度剖析STM32时钟系统

发布时间:2024-07-23  

下图是STM32的时钟树。从树上我们可以看到,STM32的时钟有两个来源——内部时钟和外部时钟。按时钟频率来分,又分为高速时钟和低速时钟。所以STM32的时钟有四个来源——高速外部时钟信号(HSE)、低速外部时钟信号(LSE)、高速内部时钟信号(HSI)和低速内部时钟信号(LSI),图中分别用蓝色的①~④标注。
深度剖析STM32时钟系统

①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高速时钟(HSE),所以着重说HSE。我们以前面的GPIO上的时钟为例,由ST的Datasheet可知,GPIO是在APB2高速外设总线上的,图中绿色的线就是时钟的流程,我们一步步地来看。

8MHz外部晶体(或晶振)输入后,先经过一个开关PLLXTPRE(HSE divider for PLL entry),此开关决定对HSE进行2分频再输入到PLL或直接到PLL。我们选择不分频。

这样时钟又到了第二个开关PLLSRC(PLL entry clock source),此开关决定PLL的时钟来源,是内部高速时钟二分频的时钟还是PLLXTPRE的输出。我们选择后者,这时的时钟在进入PLL前还是8MHz,因为在PLLXTPRE我们没有分频。

到了PLL倍频器,由PLLMUL决定倍频系统数,可以选择2~16倍频输出,但记住,PLL输出频率最高72MHz,所以我们选择9倍频,这样PLL输出就是最高72MHz的PLLCLK时钟了。这时的PLLCLK为USB提供时钟。

开关SW来决定SYSCLK的时钟来源,前面已经提到,这里我们由PLLCLK做为SYSCLK的来源,这样系统时钟SYSCLK就是72MHz了。

在供给外设前,先经过AHB预分频,我们选择不分频;在供给GPIO前,还要再经过APB2预分频,因为APB2为高速外设,所以我们选择不分频,这样GPIO的时钟就是72MHz了。注意,低速外设APB1最高频率为36MHz,所以在使用APB1的外设时,要注意设置好分频系统。还要注意,要使用外设,先要对外设时钟进行使能,见图中黄色云形框。这是因为STM32采用了低功耗的设计,对不使用的外设,其时钟不使能,以达到降低功耗的效果。

时钟的设置在程序中是怎么来实现的呢?这里我们以前面GPIO的程序来一步步分析。当然,前面的程序是基于ST库的,其实也就是分析ST的官方库了。

我们看到main()函数中的第一行代码是调用了一个函数:

SystemInit();

这个函数是在system_stm32f10x.c中:

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

}

我们可以看到,程序前面一系统Reset或Disable,最后调用了(红色标记出来)

SetSysClock();

SetSysClock()函数也位于system_stm32f10x.c源文件中:

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时钟,那肯定我们定义了宏SYSCLK_FREQ_72MHz,所以才调用的函数SetSysClockTo72()。我们继续跟踪,会发现在源文件开头,我们的确定义了:

#define SYSCLK_FREQ_72MHz 72000000

在SetSysClockTo72()函数中详细地对72MHz进行设置,这里就不一步步分析。

前面已经提到,在使用外设时,要使能相应的外设时钟,例如,在使用GPIOB进行流水灯实验时,程序中调用了下面的库函数,对外设时钟进行设置:

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);

另外,STM32还可以把时钟输出,如图左下角的咖啡色方框里面,可以由MCO决定,PLL时钟二分频或HIS或HSE或系统时钟作为主时钟输出。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>