OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4636|回复: 18

初入32对系统时钟的初步理解,希望指正

[复制链接]

24

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
128
金钱
128
注册时间
2017-10-21
在线时间
41 小时
发表于 2018-1-27 17:49:59 | 显示全部楼层 |阅读模式

理解时钟没有时钟树图肯定不行,先来了解时钟树图                              

3445.png

图中5个红色框为5个时钟源,个人理解为四个直接时钟源,就是右下角标注的四个,另一个间接时钟源,因为他是对来自两个高速时钟(HSE或者HSI)的倍频得到的。他们都用来做什么?图中其他颜色的标注了时钟主要去向和它来自的时钟源。这里系统时钟就非常重要了。
STM32时钟系统的配置除了初始化的时候在system_stm32f10x.c中的SystemInit()函数中外,其他的配置主要在stm32f10x_rcc.c文件中。
打开system_stm32f10x.c文件,找到SystemInit()函数。
erg.png

函数第一句就是这么一句话,那么这是RCC个什么呢?其实这是个配置时钟的寄存器结构体变量的宏。右击追踪这个RCC可以发现。
drstg.png

那么这是个什么样的结构呢?
继续。。。。。
rehfgj.png

发现下面这个结构体定义,其实这里的结构体变量都是RCC寄存器,我们就可以通过这个宏定义表示的结构体变量的成员变量来操作RCC的各个寄存器。。。。。。。这些寄存器《STM32中文参考手册》60~76页有详细描述。但是从下面的各个寄存器的名称就可以明个大概这个寄存器是干嘛的。
tjhdfj.png

1.       时钟控制寄存器(RCC_CR)
2.       时钟配置寄存器(RCC_CFGR)
3.       时钟中断寄存器 (RCC_CIR)
4.       APB2  外设复位寄存器 (RCC_APB2RSTR)
5.       APB1  外设复位寄存器 (RCC_APB1RSTR)
6.       AHB 外设时钟使能寄存器 (RCC_AHBENR)
7.       APB2  外设时钟使能寄存器(RCC_APB2ENR)
8.       APB1  外设时钟使能寄存器(RCC_APB1ENR)
9.       备份域控制寄存器 备份域控制寄存器 (RCC_BDCR)
10.   控制/ 状态寄存器 (RCC_CSR)
下面继续看SystemInit ()函数中的主要语句;
人体后突然放大.png

根据寄存器手册可以知道这是启动内部高速时钟。
阿瑟噶十多个.png
对方是否过得好.png


这些都是一些相应的配置,主要在后面这个SetSysClock函数。
结合地方.png

打开这个函数看一下
打工皇帝发射管.png

啥鸡毛玩意儿??其实名称也比较容易理解,我们可以通过定义宏来选择执行相应的函数设定相应的时钟频率。


追踪这个宏定义(下图)可以发现默认是72MHz(追踪不到说明是没有声明的),那么我们可以通过修改这个宏来修改系统初始化的时钟频率。
房管局的.png

接下来回头我们看一下这些设置系统时钟的SetSysClock函数是怎么配置相应时钟频率的。打开后发现这里有设置为24M的函数、有设置为36M的函数。。。。等等;以设置系统时钟频率为72M的函数SetSysClockTo72()为例,我们打开这个函数;
核实对方还是.png

这个函数有点长,一点一点看。
按个.png

这里都是操作寄存器来配置,这些配置的结果都已经有官方英文注释,我注释上了中文。有兴趣我们可以对照《STM32中文参考手册》查看这些配置。或者我们直接就知道这些配置的结果是什么就行了。
港顺达.png

红框中第一句配置为HCLK = SYSCLK,通过时钟树我们可以知道就是将AHB预分频器配置为1(不分频);第二句PCLK2 = HCLK,就是讲APB2预分频器配置为1(不分频)。第三句PCLK1 = HCLK,就是讲APB1预分频器配置为2(2分频);

哈.png
接下来配置PLLCLK的时钟源为HSE并且9倍频
黑灰.png

最后将系统时钟来源设定为PLL。


最后简述系统时钟初始化主要过程
1.  打开内部高速时钟HIS;
2.  设置时钟
a)   打开外部高速时钟HSE
b)  配置PLLCLK的时钟来源为高速外部时钟HSE且9倍频
c)   打开PLL时钟使能后将PLL设置为系统时钟来源
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

24

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
128
金钱
128
注册时间
2017-10-21
在线时间
41 小时
 楼主| 发表于 2018-1-27 23:59:04 | 显示全部楼层
在寄存器版本中没有系统时钟初始化,因此需要根据情况自主调用函数配置。原子给打包了一个函数,默认外部时钟经过PLL倍频得到系统时钟,这个函数只需要传递PLL倍频系数就行了,如下;
[mw_shl_code=c,true]//SYSCLK:系统时钟
void delay_init(u8 SYSCLK)
{
#if SYSTEM_SUPPORT_OS                                                 //如果需要支持OS.
        u32 reload;
#endif
        SysTick->CTRL&=~(1<<2);                                        //SYSTICK使用外部时钟源         
        fac_us=SYSCLK/8;                                                //不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS                                                 //如果需要支持OS.
        reload=SYSCLK/8;                                                //每秒钟的计数次数 单位为K          
        reload*=1000000/delay_ostickspersec;        //根据delay_ostickspersec设定溢出时间
                                                                                        //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右       
        fac_ms=1000/delay_ostickspersec;                //代表OS可以延时的最少单位          
        SysTick->CTRL|=1<<1;                                           //开启SYSTICK中断
        SysTick->LOAD=reload;                                         //每1/delay_ostickspersec秒中断一次       
        SysTick->CTRL|=1<<0;                                           //开启SYSTICK   
#else
        fac_ms=(u16)fac_us*1000;                                //非OS下,代表每个ms需要的systick时钟数   
#endif
}        [/mw_shl_code]
这个函数是系统时钟配置函数;
PLL范围为2~16,一般设置为PLL=9倍频,那么系统时钟就为8*9=72MHz(最大频率最好不得超过72M);知道这么多就差不多了,具体实现是操作RCC寄存器实现的。
回复 支持 反对

使用道具 举报

3

主题

85

帖子

0

精华

高级会员

Rank: 4

积分
586
金钱
586
注册时间
2016-5-13
在线时间
106 小时
发表于 2018-1-29 16:18:22 | 显示全部楼层

回帖奖励 +1 金钱

用CUBEMX直接配置,直观还方便
回复 支持 反对

使用道具 举报

24

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
128
金钱
128
注册时间
2017-10-21
在线时间
41 小时
 楼主| 发表于 2018-1-29 18:29:01 | 显示全部楼层
abdfgh 发表于 2018-1-29 16:18
用CUBEMX直接配置,直观还方便

CUBEMX是什么?,,我刚入门32,,,不太懂
回复 支持 反对

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-29 18:33:11 | 显示全部楼层

回帖奖励 +1 金钱

ForestLi 发表于 2018-1-29 18:29
CUBEMX是什么?,,我刚入门32,,,不太懂

刚入门正是应该用CubeMX。它是一个快速生成代码的工具。可以自动配置peripheral、clock、GPIO,非常方便。
回复 支持 反对

使用道具 举报

24

主题

73

帖子

0

精华

初级会员

Rank: 2

积分
128
金钱
128
注册时间
2017-10-21
在线时间
41 小时
 楼主| 发表于 2018-1-29 20:00:01 | 显示全部楼层
a496298685 发表于 2018-1-29 18:33
刚入门正是应该用CubeMX。它是一个快速生成代码的工具。可以自动配置peripheral、clock、GPIO,非常方便 ...

哪里有?
回复 支持 反对

使用道具 举报

6

主题

462

帖子

0

精华

高级会员

Rank: 4

积分
906
金钱
906
注册时间
2017-12-15
在线时间
111 小时
发表于 2018-1-29 22:49:38 | 显示全部楼层

哪里都有。st官网
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
445
金钱
445
注册时间
2017-11-17
在线时间
94 小时
发表于 2018-1-30 15:17:12 | 显示全部楼层

回帖奖励 +1 金钱

cube+1  绝对适合新手入门
回复 支持 反对

使用道具 举报

5

主题

36

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
303
金钱
303
注册时间
2017-12-23
在线时间
77 小时
发表于 2018-1-31 12:29:13 来自手机 | 显示全部楼层
cubemx
回复 支持 反对

使用道具 举报

5

主题

69

帖子

0

精华

高级会员

Rank: 4

积分
567
金钱
567
注册时间
2017-5-30
在线时间
70 小时
发表于 2018-1-31 13:34:11 | 显示全部楼层

回帖奖励 +1 金钱

学习了。
回复 支持 反对

使用道具 举报

0

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
167
金钱
167
注册时间
2017-11-28
在线时间
58 小时
发表于 2018-1-31 13:44:56 | 显示全部楼层

回帖奖励 +1 金钱

入门篇,谢谢!
回复 支持 反对

使用道具 举报

17

主题

93

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
451
金钱
451
注册时间
2017-2-1
在线时间
74 小时
发表于 2018-1-31 19:47:59 | 显示全部楼层
用cube入门不好,入门该学寄存器,然后往库函数学习,cube和HAL库都确实好用,但是偏应用
回复 支持 反对

使用道具 举报

6

主题

55

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
317
金钱
317
注册时间
2017-12-12
在线时间
47 小时
发表于 2018-2-1 09:39:44 | 显示全部楼层
分析的不错,加油
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165538
金钱
165538
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-7-8 01:49:36 | 显示全部楼层
分析的不错啊
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

17

主题

237

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1312
金钱
1312
注册时间
2017-3-1
在线时间
259 小时
发表于 2018-7-8 23:09:56 | 显示全部楼层
本帖最后由 NewGuard 于 2018-7-8 23:11 编辑

你好看了你的时钟分析,但是还是有点迷茫,其中图片中的HSE_VALUE,感觉好像没使用呀!PREDIV1怎么就是HSE了,我是看的有点糊涂,我时钟树看的要死了!



2018-07-08_230058.jpg
2018-07-08_230250.jpg
回复 支持 反对

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4520
金钱
4520
注册时间
2018-5-11
在线时间
946 小时
发表于 2018-7-9 09:01:28 | 显示全部楼层
NewGuard 发表于 2018-7-8 23:09
你好看了你的时钟分析,但是还是有点迷茫,其中图片中的HSE_VALUE,感觉好像没使用呀!PREDIV1怎么就是HSE ...

时钟是由硬件加控制出来的,
不是定义出来的。
宏定义一下HSE VALUE只是为了库函数能知道你所采用的晶体及MCU型号,进行程序分支控制,并不参与程序运算。
你所要知道的是,时钟树的时钟走向及控制。
PLL只有两个来源,即要么HSI/2, 要么使用HSE,这由你截图1的PLLSRC比特位来控制。
如果选择的是1,则使用的是HSE,也就是PREDIV1的输出,
再往前看,这个输出又有两个来源,即要么直接HSE,要么HSE/2, 这个就由PLLXTPRE比特位来决定了。
HSE的定义值是没有用的(主要用于宏,作预编译),你可以接6M晶体,同样用,最终的频率由上述控制位来决定。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

17

主题

237

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1312
金钱
1312
注册时间
2017-3-1
在线时间
259 小时
发表于 2018-7-9 09:14:26 | 显示全部楼层
warship 发表于 2018-7-9 09:01
时钟是由硬件加控制出来的,
不是定义出来的。
宏定义一下HSE VALUE只是为了库函数能知道你所采用的晶 ...

谢谢你的回复!
我是这么理解:HSE是硬件采集到的实际时钟,软件定义12MHz,但如果晶振是8MHz,9倍频后也是72MHz,另外就是HSE_VALUE这个宏在(void SystemCoreClockUpdate (void),void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks))两个函数中用了,改变外部晶振频率时同时改变宏的值,是为了整个程序的时钟统一性,保证后面用到此宏的程序和当前晶振一致。有不对的地方还望指正,谢谢!
回复 支持 反对

使用道具 举报

31

主题

1955

帖子

3

精华

论坛元老

Rank: 8Rank: 8

积分
4520
金钱
4520
注册时间
2018-5-11
在线时间
946 小时
发表于 2018-7-9 09:25:35 | 显示全部楼层
NewGuard 发表于 2018-7-9 09:14
谢谢你的回复!
我是这么理解:HSE是硬件采集到的实际时钟,软件定义12MHz,但如果晶振是8MHz,9倍频后 ...

理解正确,不用再纠结了。哈哈。
我的开源链接 https://github.com/ShuifaHe/STM32.git  请关注,点赞支持哦。
回复 支持 反对

使用道具 举报

17

主题

237

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1312
金钱
1312
注册时间
2017-3-1
在线时间
259 小时
发表于 2018-7-9 09:37:22 | 显示全部楼层
warship 发表于 2018-7-9 09:25
理解正确,不用再纠结了。哈哈。

非常感谢!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-15 15:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表