STM32F207时钟系统解析

在前几天的文章《晶振原理解析》中介绍了晶振如何产生时钟的,板子使用的是25M无源晶振,下文将介绍STM32F207的时钟系统如何将25M晶振时钟转换为120M系统主频时钟的。

01、时钟系统介绍

                                                                    ▲时钟系统专业名词缩写

时钟系统关键组成部分

01 内部高速时钟(HSI)

HSI时钟信号可以通过内部16MHZ的RC振荡器产生,可以直接用于系统时钟或者用于PLL输入。

_HSI的RC振荡器的优势是:_在最小成本(没有外部器件)情况下提供一个时钟源。它的启动速度要比HSE晶体振荡器更快,但是即使校准频率后,它的精度仍然小于外部晶体振荡器或陶瓷谐振器。

02 外部高速时钟(HSE)

外部高速时钟信息(HSE)可以通过两个时钟源产生:

① 外部晶体/陶瓷谐振器

② 外部用户时钟

▲两种时钟源接入示意图

03 主锁相环时钟(PLL)

STM32F2xx具有两个PLL

① 主要的PLL通过HSE或HSI提供时钟,并且有两个输出时钟;

② 专用的PLL(PLLI2S)被用于产生一个精确的时钟去实现高质量音频效果在I2S接口;

HSE/M*N/P得到PLL时钟

关于PLL锁相环说明

从1处输入,3处输出是1的N倍。

3处除以N又作为输入,当1和2的频率一样,就锁定了。(之所以图上是xN,因为从2看向3的)

04 低速外部时钟(LSE)

LSE是一个32.768KHZ低速外部晶振或陶瓷谐振器。

它的优点:提供低速但是高精度时钟给RTC外设,为时钟/日历或其他时间应用。

05低速内部时钟(LSI)

LSI RC作为一个低速时钟源,它可以运行在停止和待机模式中给独立看门狗(IWDG)和自动唤醒(AWU)。它的时钟频率在32MHZ左右。

02、代码分析

时钟初始化代码在system_stm32f2xx.c文件中,大部分时候我们不需要修改时钟代码的,各个总线的频率我们可以在文件头看到。

1============================================================================= 2 *============================================================================= 3 * Supported STM32F2xx device revision | Rev B and Y 4 *----------------------------------------------------------------------------- 5 * System Clock source | PLL (HSE) 6 *----------------------------------------------------------------------------- 7 * SYSCLK(Hz) | 120000000 8 *----------------------------------------------------------------------------- 9 * HCLK(Hz) | 120000000 10 *----------------------------------------------------------------------------- 11 * AHB Prescaler | 1 12 *----------------------------------------------------------------------------- 13 * APB1 Prescaler | 4 14 *----------------------------------------------------------------------------- 15 * APB2 Prescaler | 2 16 *----------------------------------------------------------------------------- 17 * HSE Frequency(Hz) | 25000000 18 *----------------------------------------------------------------------------- 19 * PLL_M | 25 20 *----------------------------------------------------------------------------- 21 * PLL_N | 240 22 *----------------------------------------------------------------------------- 23 * PLL_P | 2 24 *----------------------------------------------------------------------------- 25 * PLL_Q | 5 26 *----------------------------------------------------------------------------- 27 * PLLI2S_N | NA 28 *----------------------------------------------------------------------------- 29 * PLLI2S_R | NA 30 *----------------------------------------------------------------------------- 31 * I2S input clock | NA 32 *----------------------------------------------------------------------------- 33 * VDD(V) | 3.3 34 *----------------------------------------------------------------------------- 35 * Flash Latency(WS) | 3 36 *----------------------------------------------------------------------------- 37 * Prefetch Buffer | ON 38 *----------------------------------------------------------------------------- 39 * Instruction cache | ON 40 *----------------------------------------------------------------------------- 41 * Data cache | ON 42 *----------------------------------------------------------------------------- 43 * Require 48MHz for USB OTG FS, | Enabled 44 * SDIO and RNG clock | 45 *----------------------------------------------------------------------------- 46 *============================================================================= 47 ******************************************************************************

在文件开始定义的有系统时钟频率的全局变量SystemCoreClock,其他地方需要时钟频率,可以直接使用该变量。

uint32_t SystemCoreClock = 120000000;

时钟配置从SystemInit函数执行,调用SystemInit的在汇编文件中startup_stm32f2xx.s(Keil编译环境)。

1IMPORT __main 2 LDR R0, =SystemInit 3 BLX R0 4 LDR R0, =__main 5 BX R0 6 ENDP

在这里说明一下文档版本的问题:

▲STM32F20X_User_manual的V7版和V8版对比图

上述两图的区别是系统最大时钟从120MHZ变成了168MHZ,我的理解是同样是STM32F20X,ST由于技术进步或其他,使得新版STM32F207芯片超频支持168MHZ。

文档下载地址:

https://www.st.com/en/microcontrollers-microprocessors/stm32f2x7.html#resource

在线预览地址:

https://www.st.com/content/ccc/resource/technical/document/reference_manual/51/f7/f3/06/cd/b6/46/ec/CD00225773.pdf/files/CD00225773.pdf/jcr:content/translations/en.CD00225773.pdf

下面我们主要分析SystemCoreClock的120M时钟怎么从一个外部25MHZ的HSE得到的。

我们要从25MHZ的外部时钟得到120M的系统时钟,需要上图中标注的重要4点:

1、使能HSE

2、选择HSE作为主PLL的输入时钟

3、主PLL倍频后得到120MHZ时钟

4、系统时钟选择主PLL时钟输出作为系统时钟

我们找到对应的代码

  1、使能HSE

1/* Enable HSE */ 2RCC->CR |= ((uint32_t)RCC_CR_HSEON);

在RCC_CR寄存器(RCCclock control register RCC时钟控制器)中,有打开HSE的控制位

 输入时钟

1/* Configure the main PLL */ 2RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | 3(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

RCC_PLLCFGR_PLLSRC_HSE就是配置HSE作为主PLL的输入时钟

  3、主PLL倍频后得到120MHZ时钟

1/* Configure the main PLL */ 2RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | 3 (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

4、配置主PLL作为系统时钟的输入时钟

1/* Select the main PLL as system clock source */ 2RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); 3RCC->CFGR |= RCC_CFGR_SW_PL

对于主PLL的配置寄存器,在RCC_PLLCFGR寄存器中有说明

整理后得知f(out)=f(in)* N / M / P

1/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */ 2#define PLL_M 25 3#define PLL_N 240 4/* SYSCLK = PLL_VCO / PLL_P */ 5#define PLL_P 2

这样就获得了120M时钟

注意:

PLL_M大于等于2且小于等于63

PLL_N大于等于64且小于等于432

PLL_P只能是2、4、6、或8

但2对应0,4对应1,6对应2,8对应3。

ST并没有使用if或case语句判断,因为对应的数据除以2减去1就是寄存器这两位的值,所以可以按照下面这样写,这种写法值得我们学习。

(((PLL_P >> 1) -1) << 16)

其他外设的时钟配置时

1/* HCLK = SYSCLK / 1*/ 2RCC->CFGR |= RCC_CFGR_HPRE_DIV1; 3/* PCLK2 = HCLK / 2*/ 4RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; 5/* PCLK1 = HCLK / 4*/ 6RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

03、备 注 

时钟中断

可以配置外部晶振出错时的中断,还有RCC中断,因此我们可以在外部时钟出问题时,切换为内部时钟,不至于整个系统挂掉。具体见ST给的官方代码。

 无源晶振不起振

没有程序,无源晶振是不起振的,需要配置RCC时钟控制寄存器的HSEON位打开或关闭HSE振荡器。具体可以看之前的文章《晶振原理解析》。

 关于APB和PCLK

F207是时钟图没有显示PCLK1和PCLK2,应该就是APB1和APB2

应该指的是一个PCLK应该是PeripheralClock的简称,看F105手册

点击查看本文所在的专辑,STM32F207教程

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )