视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
6.3 STM32F407ZGT的时钟深入剖析(32M,40M,72M灵活切换)
2025-09-29 16:30:19 责编:小OO
文档
6.2 时钟 (2)

6.1.1 什么是时钟 (2)

6.1.2 STM32的时钟 (2)

6.1.3 STM32的时钟深入分析 (4)

6.1.4 例程01 STM32芯片32MHZ频率下跑点灯程序 (7)

6.1.1 例程02 STM32芯片40MHZ频率下跑点灯程序 (14)

6.1.2 例程03 STM32芯片72MHZ频率下跑点灯程序 (15)6.2时钟

6.1.1什么是时钟

从CPU的时钟说起。

计算机是一个十分复杂的电子设备。它由各种集成电路和电子器件组成,每一块集成电路中都集成了数以万计的晶体管和其他电子元件。这样一个十分庞大的系统,要使它能够正常地工作,就必须有一个指挥,对各部分的工作进行协调。各个元件的动作就是在这个指挥下按不同的先后顺序完成自己的操作的,这个先后顺序我们称为时序。时序是计算机中一个非常重要的概念,如果时序出现错误,就会使系统发生故障,甚至造成死机。那么是谁来产生和控制这个操作时序呢?这就是“时钟”。“时钟”可以认为是计算机的“心脏”,如同人一样,只有心脏在跳动,生命才能够继续。不要把计算机的“时钟”等同于普通的时钟,它实际上是由晶体振荡器产生的连续脉冲波,这些脉冲波的幅度和频率是不变的,这种时钟信号我们称为外部时钟。它们被送入CPU中,再形成CPU时钟。不同的CPU,其外部时钟和CPU时钟的关系是不同的,下表列出了几种不同CPU外部时钟和CPU时钟的关系。

CPU时钟周期通常为节拍脉冲或T周期,它是处理操作的最基本的单位。

在微程序控制器中,时序信号比较简单,一般采用节拍电位——节拍脉冲二级。就是说它只要一个节拍电位,在节拍电位又包含若干个节拍脉冲(时钟周期)。节拍电位表示一个CPU周期的时间,而节拍脉冲把一个CPU周期划分为几个叫较小的时间间隔。根据需要这些时间间隔可以相等,也可以不等。

指令周期是取出并执行一条指令的时间。

指令周期常常有若干个CPU周期,CPU周期也称为机器周期,由于CPU访问一次内存所花费的时间较长,因此通常用内存中读取一个指令字的最短时间来规定CPU周期。这就是说,这就是说一条指令取出阶段(通常为取指)需要一个CPU周期时间。而一个CPU周期时间又包含若干个时钟周期(通常为节拍脉冲或T周期,它是处理操作的最基本的单位)。这些时钟周期的总和则规定了一个CPU周期的时间宽度。

6.1.2STM32的时钟

系统时钟的选择是在启动时进行,复位时内部16MHZ的RC振荡器被选为默认的CPU 时钟,随后可以选择外部的、具失效监控的4-26MHZ时钟;当检测到外部时钟失效时,它将被隔离,系统将自动地切换到内部的RC振荡器。

在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL,它们都是时钟所提供的来源:

1.HSI是高速内部时钟,RC振荡器,频率默认为16MHz,可以从STM32时钟树中看到

2.HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为

3MHz~25MHz,时钟树的截图如下:

3.LSI是低速内部时钟,RC振荡器,频率为32kHz,可以用于驱动看门狗和通过程序

选择驱动RTC(RTC用于从停机/待机模式下自动唤醒系统),时钟树的截图如下:

4.LSE是低速外部时钟,接频率为32.768kHz的石英晶体,也可以被用来驱动RTC,时钟

树的截图如下:

5.PLL为锁相环输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2等。但是其输出频

率最大不得超过120MHz,时钟树的截图如下::

6.1.3STM32的时钟深入分析

众所周知,微控制器(处理器)的运行必须要依赖周期性的时钟脉冲来驱动——往往由一个外部晶体振荡器提供时钟输入为始,最终转换为多个外部设备的周期性运作为末,这种时钟“能量”扩散流动的路径,犹如大树的养分通过主干流向各个分支,因此常称之为“时钟树”。在一些传统的低端8位单片机诸如51,A VR,PIC等单片机,其也具备自身的一个时钟树系统,但其中的绝大部分是不受用户控制的,亦即在单片机上电后,时钟树就固定在某种不可更改的状态(假设单片机处于正常工作的状态)。比如51单片机使用典型的12MHz 晶振作为时钟源,则外设如IO口、定时器、串口等设备的驱动时钟速率便已经是固定的,用户无法将此时钟速率更改,除非更换晶振。

而STM32微控制器的时钟树则是可配置的,其时钟输入源与最终达到外设处的时钟速率不再有固定的关系,下面来详细解析STM32微控制器的时钟树。下图是STM32微控制

器的时钟树:

下表是结合图表明出来的: 标号

释义 1

内部低速振荡器(LSI ,40Khz ) 2 外部低速振荡器(LSE ,32.768Khz )

4 内部高速振荡器(HSI,8MHz)

5 PLL输入选择位

6 RTC时钟选择位

7 PLL1分频数寄存器

8 PLL1倍频寄存器

9 系统时钟选择位

10 USB分频寄存器

11 AHB分频寄存器

12 APB1分频寄存器

13 AHB总线

14 APB1外设总线

15 APB2分频寄存器

16 APB2外设总线

17 ADC预分频寄存器

18 ADC外设

19 PLL2分频数寄存器

20 PLL2倍频寄存器

21 PLL时钟源选择寄存器

22 看门狗设备

23 RTC设备

在认识这颗时钟树之前,首先要明确“主干”和最终的“分支”。假设使用外部8MHz 晶振作为STM32的时钟输入源(这也是最常见的一种做法),则这个8MHz便是“主干”,而“分支”很显然是最终的外部设备比如通用输入输出设备(GPIO)。这样可以轻易找出第一条时钟的“脉络”:

3——5——7——21——8——9——11——13

对此条时钟路径做如下解析:

 对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;

 对于5,通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);

 对于7,设置外部晶振的分频数(假设1分频);

 对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);

 对于8,设置PLL倍频数(假设9倍频);

 对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);

 对于11,设置AHB总线分频数(假设1分频);

 对于13,时钟到达AHB总线;

在上一章节中所介绍的GPIO外设属于APB2设备,即GPIO的时钟来源于APB2总线,同样在上图中也可以寻获GPIO外设的时钟轨迹:3——5——7——21——8——9——11——15——16

 对于3,首先是外部的3-25MHz(前文已假设为8MHz)输入;

 对于5,通过PLL选择位预先选择后续PLL分支的输入时钟(假设选择外部晶振);

 对于7,设置外部晶振的分频数(假设1分频);

 对于21,选择PLL倍频的时钟源(假设选择经过分频后的外部晶振时钟);

 对于8,设置PLL倍频数(假设9倍频);

 对于9,选择系统时钟源(假设选择经过PLL倍频所输出的时钟);

 对于11,设置AHB总线分频数(假设1分频);

 对于15,设置APB2总线分频数(假设1分频)

 对于16,时钟到达APB2总线;

现在来计算一下GPIO设备的最大驱动时钟速率(各个条件已在上述要点中假设):

1) 由3所知晶振输入为8MHz,由○5——○21知PLL的时钟源为经过分频后的外部晶振时钟,并且此分频数为1分频,因此首先得出PLL的时钟源为:8MHz / 1 = 8MHz。

2) 由8、9知PLL倍频9,且将PLL倍频后的时钟输出选择为系统时钟,则得出系统时钟为8MHz * 9 = 72MHz。

3) 时钟到达AHB预分频器,由11知时钟经过AHB预分频器之后的速率仍为72MHz。

4) 时钟到达APB2预分频器,由15经过APB2预分频器后速率仍为72MHz。

5) 时钟到达APB2总线外设

上面是原理的剖析,如果再不明白的,可以接下来看例程代码,理论联系实践是最好的老师。

6.1.4例程01 STM32芯片32MHZ频率下跑点灯程序

1.示例简介

让点灯程序在时钟主频32MHz下面运行,LED灯的正极接的是3.3V电源,所以我们编程让LED负极拉低即GPIO引脚端口F的管脚10拉低,即PD2拉低,那么LED灯就会变亮,相关电路图如下图所示:

2.调试说明:

下载代码,并且按下【复位】键,在神舟王407板上找到LED2,可以看到该LED1灯一亮一灭。

3.关键代码:

/*************** 程序总共2部分之第1部分时钟频率的配置{开始*********************************/

/************ www.armjishu.com *******/

int main(void){

/**** 程序总共2部分之第1部分时钟频率的配置 ********************/ /***** 以下是关于RCC时钟详细请见《STM32F20XXX参考手册》5.3节RCC寄存器描述 *******/

unsigned char sws = 0;

RCC->CR |= 0X00010000; //使能外部高速时钟HSEON

while(!(RCC->CR>>17)); //将RCC_CR寄存器的值右移17位,等待HSERDY就绪,即外部时钟就绪

我们在这里,因为STM32神舟王207开发板上的晶振是25MHZ的,我们先25分频,再128倍频,再4分频,输出就能达到STM32的32MHZ工作频率,分别先后用到了,PLLCFGR中的0-5位、6-14位、16-17位。*/

RCC->PLLCFGR

0x19; //25分频

|=

|=0x1<<13; //128倍频

RCC->PLLCFGR

//4分频

RCC->PLLCFGR

|=0x1<<16;

//CPU和FLASH的频率不一样,所以需要等待

FLASH->ACR|=0x1;

RCC->CR |= 1<<24; //将PLL使能

//监控寄存器CR的PLLRDY位,等待PLL时钟就绪

while(!(RCC->CR>>25));

1<<1; //将时钟切换寄存器配置成用PLL输出作为系统时钟

|=

RCC->CFGR

while(sws != 0x2) //等待CFGR寄存器的2,3位为10,系统正式切换到了PLL 输出作为时钟

{

将CFGR寄存器右移2位,将2,3位SWS状态移

//

=

sws

RCC->CFGR>>2;

出来,

// 详情请见《STM32F20XXX参考手册》97页sws &= 0x3; //这里的0x3为二进制的11,这个whlie循环设计的一个算法,为了判断sws是不是为10

}

/*************** 程序总共2部分之第1部分时钟频率的配置结束*********************************/

/*使能AHB1总线的时钟,对GPIO的端口F时钟使能*/

RCC->AHB1ENR |= RCC_AHB1Periph_GPIOF;

/*配置输入输出模式和输入输出的速度*/

GPIOF->MODER &= 0xFFCFFFFF; /*模式*/

GPIOF->MODER |= 0x00100000;

GPIOF->OTYPER &= 0xFFFFBFFF; /*类型*/GPIOF->OTYPER |= 0x00000000;

GPIOF->OSPEEDR &= 0xFFCFFFFF; /*速度*/

GPIOF->OSPEEDR |= 0x00200000;

GPIOF->PUPDR &= 0xFFCFFFFF;

GPIOF->PUPDR |= 0x0000000;

/* Infinite loop 主循环 */

while (1)

{

GPIOF->BSRRL=GPIO_Pin_10; /*熄灭LED灯*/

Delay(0x1FFFFFF);

GPIOF->BSRRH=GPIO_Pin_10; /*点亮LED灯*/

Delay(0x1FFFFFF);

}

}

/** 程序总共2部分之第2部分点灯的配置结束} **/

这个例程主要是体现在如何设置时钟,点灯的代码和原理图都在通用输入/输出的GPIO 章节详细说明了。

STM32的时钟源有几种,有内部的RC,也有外部的晶振,该选择哪种,代码里通过语句:RCC->CR |= 0X00010000;使能外部的晶振,那么CR这个寄存器全称叫做STM23的时钟控制寄存器,在《STM32F4用户手册》的93页可以看到RCC_CR寄存器:

再分析一下RCC->CR |= 0X00010000这个语句16进制0x00010000换成二进制,是第

17位为1,其他31个位都为0,寄存器是从0开始,就是16位置位

可以看到对HSE ON置位就是把外部的高速时钟使能,CPU所需要的时钟是从外部获取;然后接下继续看另外一句代码:while(!(RCC->CR>>17)),在while循环里,如果为1,while 就会一直循环,如果为0的话while就会继续执行;while循环里还有!取反的操作,所以这句代码的意思三个是让while循环等到CR的第17位变成1才往下执行,那么看下第17位是什么,翻到《STM324用户手册》的94页:

可以看到上图,第17位置1表示外部的高速时钟就绪好了,晶振起振稳定,CPU从外部晶振稳定的获取时钟。

接下来,就是操作一个叫做RCC_PLLCFGR寄存器,这个寄存器主要负责内部时钟的分频和倍频。分频就相当于是除法,比如25M的主频,25分频后就是1M了;倍频就是加入输入进来是1M主频,经过128倍频后就是乘以128倍,等于128M了,所以倍频就相当于是乘,这是一个非常重要的寄存器。

这个寄存器是用来配置PLL时钟输出。下面来分析我们如何操作这个寄存器的:

1)RCC->PLLCFGR |= 0x19; //25分频

2)RCC->PLLCFGR |=0x1<<13; //128倍频

3)RCC->PLLCFGR |=0x1<<16; //4分频

第1句代码是设置PLLCFGR的PLLM(0-5位)。0x19化为二进制为:0001 1001=25。可以看出刚好分频了25倍。

第2句代码是设置PLLCFGR的PLLN(6-14位),由下图可以看出,它只能半字节或一个字节操作。二进制0100 0000 0刚好等于128。代码0x1<<13就是将第bits13置1,倍频128倍。

第2句代码是设置PLLCFGR的PLLP(16-17位), 代码RCC->PLLCFGR |=0x1<<16; 就是4分频的意思了。

这个寄存器主要负责配置STM32内部总线上的一些时钟参数,比如时钟切换状态(可以知道目前哪个时钟作为系统时钟,比如有内部的时钟,也有外部的),这个寄存器还负责STM32时钟内部总线的配置,比如APB1时钟总线,APB2时钟总线是怎么分频(有几种分频方式,例如不分频,2分频,4分频,8分频,16分频等);还有RTC的分频等;可以看到这个寄存器完成了许多的功能,下面来分析我们如何操作这个寄存器的:

RCC->CFGR |= 1<<1;

这句代码表示将时钟切换到外部时钟,都设置好之后,通知STM32的芯片可以将系统的时钟切换给外部晶振提供时钟了:

程序代码选择的是外部的HSE提供时钟;可以从下图看到,RCC_PLLCFGR寄存器里的PLLM,程序代码里配置的是25分频,如果这里外部晶振是25MHz的,25倍频后就是1MHz的频率。RCC_PLLCFGR寄存器里的PLLN,程序代码里配置的是128倍频,1MHz 的128倍为128MHz。RCC_PLLCFGR寄存器里的PLLP,程序代码里配置的是4分频,128MHz 的4分频为32MHz。程序里选择的是PLLCLK,这个来自HSE外部晶振然分频,倍频,再分频后的时钟做为整个STM32芯片的主时钟。

上图上面已经经过详细分析了,接下来就是一个while(sws != 0x2)循环

0x2)

!=

while(sws

{

sws = RCC->CFGR>>2;

sws &= 0x3;

}

上面的代码是将RCC_CFGR寄存器右移2位后,在与上0x3相当于与上二进制的11,最低两位是1,其他高位都是0;这样的意思就是把SWS这个系统时钟切换状态的值单独截取出来,然后用while(sws != 0x2)语句一直等待SWS的值为0x2,0x2化成二进制是10,就是

PLL输出作为系统时钟,下图可以知道:

那么这里就奇怪了,为什么不是HSE的晶振作为系统时钟呢?而是采用PLL,因为我们可以看到,我们在代码里设置的就是走左边这张图的配置路线,因为把外部的晶振进行分频和

倍频了的,也有右边这种选择,只是这个例程我们在代码里没有这么设计,以后大家可以这样设计:

最后代码配置好了,就开始点灯程序,具体细节请见代码,因为上一章节已经有详细分析。

6.1.1例程02 STM32芯片40MHZ频率下跑点灯程序

1.示例简介

让点灯程序在时钟主频40MHz下面运行,其他不变,同上个例程一样,唯一的改变就是把主频从32MHz改成40MHz了。

2.调试说明:

下载代码,并且按下【复位】键,在神舟王407开发板上可以看到该LED灯一亮一灭。

3.关键代码:

查看RCC_PLLCFGR寄存器的第6~14位的PLLN。

关键代码的改变与上面一模一样,唯一的改变就是将RCC->PLLCFGR |=0x1<<13;

//128倍频;变成了RCC->PLLCFGR |=0x5<<11; //160倍频;这句不同6.1.2例程03 STM32芯片72MHZ频率下跑点灯程序

1.示例简介

让点灯程序在时钟主频72MHz下面运行,其他不变,同上个例程一样,唯一的改变就是把主频从40MHz改成72MHz了。

2.调试说明:

下载代码,并且按下【复位】键,在神舟王407开发板上可以看到该LED灯一亮一灭。

4.关键代码:

查看RCC_PLLCFGR寄存器的第6~14位的PLLN。

关键代码的改变与几乎上面一模一样,唯一的改变就是将RCC->PLLCFGR |=0x5<<11;变成了RCC->PLLCFGR |=0x48<<7; //144倍频。然后把4分频改为2分频,这两句不同。

STM32神舟开发板资料更新与下载链接:

http://blog.sina.com.cn/s/blog_7691b90c0101edpx.html下载本文

显示全文
专题