欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

stm32学习笔记(10)时钟

程序员文章站 2022-06-09 08:28:43
...

提前说说

学习32这么长时间了,中间有一段内容也比较生疏,比如就是这个时钟。那会初学,真的没有搞清楚,今天再次回过头复习一下,彻底把时钟这一部分弄清楚

时钟

时钟树
stm32学习笔记(10)时钟用户可通过多个预分频器配置AHB、高速APB(APB2)和低速APB(APB1)域的频率。AHB和
APB2域
的最大频率是72MHzAPB1域的最大允许频率是36MHz。SDIO接口的时钟频率固定为HCLK/2。
RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick
控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。ADC时钟
由高速APB2时钟经2、4、6或8分频后获得。
定时器时钟频率分配由硬件按以下2种情况自动设置:

  1. 如果相应的APB预分频系数是1,定时器的时钟频率与所在APB总线频率一致。
  2. 否则,定时器的时钟频率被设为与其相连的APB总线频率的2倍。

这里总结一下 SystemInit()函数中设置的系统时钟大小:
SYSCLK(系统时钟) =72MHz
AHB 总线时钟(使用 SYSCLK) =72MHz
APB1 总线时钟(PCLK1) =36MHz
APB2 总线时钟(PCLK2) =72MHz
PLL 时钟 =72MHz

SysTick滴答定时器

void delay_init()
{
#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
	u32 reload;
#endif
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8
	fac_us=SystemCoreClock/8000000;				//为系统时钟的1/8  
#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
	reload=SystemCoreClock/8000000;				//每秒钟的计数次数 单位为K	   
	reload*=1000000/delay_ostickspersec;		//根据delay_ostickspersec设定溢出时间
												//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右	
	fac_ms=1000/delay_ostickspersec;			//代表OS可以延时的最少单位,为5	   

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 						//每1/delay_ostickspersec秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    

#else
	fac_ms=(u16)fac_us*1000;					//非OS下,代表每个ms需要的systick时钟数   
#endif
}					
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8

这一段代码,就是选择delay函数的时钟,为72/8mhz,也就是9mhz。我是这么理解的,现在delay函数时钟为9mhz,那么它的单位就是1/(9mhz)=1/9us

fac_us=SystemCoreClock/8000000;

第二段代码是fac_us为72mhz/8000000,也就是9个单位,那么fac_us=9*(1/9)us=1us。以上是不是操作系统的情况。

这里我们将介绍的是 ALIENTEK 提供的最新版本的延时函数,该版本的延时函数支持在任
意操作系统(OS)下面使用,它可以和操作系统共用 SysTick 定时器。
这里,我们以 UCOSII 为例,介绍如何实现操作系统和我们的 delay 函数共用 SysTick 定时
器。首先,我们简单介绍下 UCOSII 的时钟:ucos 运行需要一个系统时钟节拍(类似 “心跳”),
而这个节拍是固定的(由 OS_TICKS_PER_SEC 宏定义设置),比如要求 5ms 一次(即可设置:
OS_TICKS_PER_SEC=200),在 STM32 上面,一般是由 SysTick 来提供这个节拍,也就是 SysTick
要设置为 5ms 中断一次,为 ucos 提供时钟节拍,而且这个时钟一般是不能被打断的(否则就不
准了)。

因为在 ucos 下 SysTick 不能再被随意更改,如果我们还想利用 SysTick 来做 delay_us 或者
delay_ms 的延时,就必须想点办法了,这里我们利用的是时钟摘取法。以 delay_us 为例,比如
delay_us(50),在刚进入 delay_us 的时候先计算好这段延时需要等待的 SysTick 计数次数,这里
为 50 * 9(假设系统时钟为 72Mhz,那么 SysTick 每增加 1,就是 1/9us),然后我们就一直统计
SysTick 的计数变化,直到这个值变化了 50 * 9,一旦检测到变化达到或者超过这个值,就说明
延时 50us 时间到了。这样,我们只是抓取 SysTick 计数器的变化,并不需要修改 SysTick 的任
何状态,完全不影响 SysTick 作为 UCOS 时钟节拍的功能,这就是实现 delay 和操作系统共用
SysTick 定时器的原理。