STM32 F4 (8) Systick滴答定时器-延时函数讲解 QQ群 860099671

 SysTick定时器适用所有的STM32开发板,这节课讲解SysTick定时器产生的 延时函数,STM32开发指南5.1小节有有关SysTick相关的 介绍,在程序中在delay文件夹中,SysTick定时器是内核级别的,这个定时器很简单,主要用来延时和用作实时系统里面的心跳时钟 可以节省单片机资源,SysTick定时器就是系统滴答定时器,是一个24位的倒计数定时器,当他计数到0时就会从RELOD寄存器(重装载寄存器)重新装载计数初值,由此循环。只要 不把他的使能 位清除,他就会永不停息的工作,即使在睡眠模式下也能正常工作。

   SysTick定时器它是捆绑在NVIC中,可以产生SysTick异常,SysTick也可以产生中断 ,可以设置中断优先级,可编写中断服务函数

SysTick有四个寄存器,前面3个比较常用,LOAD放重装载值,VAL寄存器一个时钟周期会减一,一直减到0之后又会从这个LOAD寄存器重新加载到VAL寄存器, 这样去循环

SysTick控制和状态寄存器 CTRL   下面这个表在Cortex M3权威指南里有,

位0 (ENABLE)SysTick定时器的使能位,

位1   (TICKINT) 当VAL寄存器计数到0时是否要产生中断

为1  产生中断        为0不产生中断

位2(CLKSOURCE)时钟源,为 0使用外部时钟源(STCLK)   为1 使用内核时钟(FCLK)

对于STM32而言    0.使用外部时钟源是HCLK(AHB总线时钟的1/8)

                             1.内核时钟是HCLK时钟

这里M3经过   Systeminit()后系统时钟是72M,那么SysTick时钟就是72/8=9M

       M4经过   Systeminit()后系统时钟是168M  那么SysTick时钟就是168/8=21M

SysTick定时器的时钟源可以由SysTick_CLKSourceConfig()配置,由这个函数的入口参数确定使用哪一个作为时钟源。这里

对于M3\M4都是一样的,因为它是属于内核级别的,都是属于同一 SysTick定时器。

位16  (COUNTFLAG)  如果SysTick计数到0,该位为1,如果读取该位,该位将自动清零 

第二寄存器叫做  重装载数值寄存器-LOAD,是一个24位寄存器

第三个寄存器是 SysTick当前值寄存器-VAL,一个周期减一

Systick相关库函数

SysTick_CLKSourceConfig();  是配置CTL寄存器的,用于时钟源的选择

SysTick_Config(uint32_t ticks)  这个函数会开启SysTick 中断, ticks是一秒钟产生中断的次数

这里的中断函数 void SysTick_Handler(void);  对于M3/M4都是一样的

下面看代码  这个 函数有一个入口参数叫 Systick_CLKSource

实际上是配置CTRL寄存器位2(CLKSOURCE),   为0 就是配置为外部时钟 HCLK(AHB总线时钟)的1/8

                                                                                为1就是配置为内核时钟,就是HCLK

还有一个函数在core_cm4.h/core_cm3.h里面的SysTick_Config(uint32_ticks)这个代码的作用;初始化SysTick相关的寄存器,并且开启SysTick相关的寄存器,入口参数ticks.,也就是说ticks个时钟周期产生一次中断。

代码的第一行对这个ticks的值进行一个有效性判断,因为这个ticks的值不能是无限大,因为ticks最终是要写到LOAD寄存器的,从LOAD寄存器被加载到这个VAL寄存器,ticks的值 不能大于

 我们可以看到是6个F(就是2的24次方-1),也就是ticks不能大于2的24次方。

将 ticks-1赋值给这个load寄存器(也就是重装载寄存器的值设置为ticks-1),那么他就会加载到这个VAL寄存器当中,当VAL的值计数到0,LOAD寄存器又从新将初值装载到VAL当中。

接下来 是设置优先级,那么设置优先级在NVIC相关的视频会去讲解

接着把这个VAL设置为0, 为什么要设置为0呢?因为当我们这个VAL值为0的时候他会从新去加载计数初值,所以这里初始化的时候把它设置为0,后面如果开启了SysTick定时器,第一次他就会把初值加载到VAL当中。

上图代码就是就是开启这个SysTick定时器,1设置 时钟源    2开启中断  3使能SysTick定时器。

对于Systick库函数,有一个·SysTick_Config(uint32_ticks)利用中断实现的delay函数

这里函数的备注错了,应该是200ms的延时

上面这段代码作简单讲解

1.首先 在主函数里面他会调用一个SysTick_Config(uint32_ticks)这样的一个函数,入口参数是ticks,这里SysTick的时钟是HCLK是168M,因为要定时1ms,那么通过计算就是:168000000/1000,然后是 上面写的一个delay函数,在这个函数前面定义了一个全局变量,TimerDelay(168M时钟,1s计数168000 000次,那么1ms就计数计数168 000次,所以168M时钟/1000=1ms 延时)

上面的代码中入口参数是200,就等待他为0才能够结束。

函数功能:每1ms产生一次中断,进一次中断TimingDelay就-1,直到TimingDelay为0就延时了200ms。

正点原子的系统文件夹 的delay.c是是使用查询的方式实现延时的,在delay.h里面有三个函数

1,。delay_init(u8 SYSCLK)  这是对SysTick进行初始化,然后是两个 毫秒和微秒的延时。因为正点原子的delay.c里面支持ucos操作系统,所以有一部分代码是通过宏定义来支持的。

上图中 的两个变量在初始化函数当中我们会设置他的值,假如系统时钟是 168M,SysTick的时钟频率是系统时钟的8分频,也就是21M,那么  fac_us 含义就是我们要延时1us要用多少个SysTick时钟周期?

因为系统时钟是21M,所以就是21时钟周期是1us。

那么延时1ms要多少个时钟周期?  就是21000个时钟周期

这里SYSCLK和HCLK是一样的为168,

这一行代码是UCOS相关的,暂时不看。

上图入口参数, 选择HCLK的8分频作为SysTick的时钟频率,那么SysTick的时钟频率就是21M,

这里SYSCLK/8=168/8=21,所以fac_us=21,也就是说1us需要21个时钟周期。

上图这一段代码也是ucos相关的暂时不看。

到最后这个就是设置ms的因子。下面就开始写我们的ms、us的延时函数,有3个函数

delay_us这个函数他就有一个入口函数叫nus。就告诉我们调用这个函数输入100就是100us

怎么实现呢?

也就是让初值LOAD=nms*fac_ms

使能SysTick计数器,让LOAD寄存器的值加载到VAL寄存器,并开始计数,当计数到0时,CTRL寄存器就有一个位16标志位,计数到0就会置1.之后我们就关闭计数器。然后再清空计数器。

注意:延时时间是有一个范围的,怎么来确定这个范围呢?LOAD寄存器是一个24位的寄存器,也就是说他的最大值是2的24次方-1,所以nus*fac_us不能大于79815us这个值

这里将入口参数除以540是为什么呢?,目的是增加延时时间的范围,比如说我们要延时一个任意长度的延时时间,那么我们这里实际上就把他切成了540毫秒一份,比如说你要延时1000ms,他就先延时540ms再延时460ms这样就延时了1000ms。

这个函数和微秒 的配置是一样的。这里不在介绍。

猜你喜欢

转载自blog.csdn.net/weixin_38787597/article/details/82255891