SysTick定时器以及delay延迟函数(寄存器版)解析

2018-11-29  本文已影响0人  水大栏杆素面菊

一、什么是SysTick

1、Systick定时器也叫滴答定时器或者系统定时器,是一个24位的内核级别的倒计数定时器,从装载值倒计数到0时,再继续重装载值,只要不清除Systick使能位,就永不停息,常用做延迟和系统心跳时钟。

优点:节省MCU资源,不需要浪费一个定时器,,即使在睡眠模式下也能工作;捆绑在NVIC中断优先级管理,能产生Systick异常(即在每次计数到0时,可产生中断,编写相应的中断服务函数(SysTick_Handler(void)))即可,也可设置中断优先级。


二、 3个重要的Systick寄存器

1、 SysTick 控制和状态寄存器- CTRL 

 SysTick 控制和状态寄存器- CTRL 

位0:使能定时器

位1:设置是否产生中断

位2:0为外部时钟(即AHB/8,若外部时钟为72M,则SysTick时钟为其8分频的9M);  1为内核时钟。

位16:判断 SysTick 的当前值VAL计数器是否计到0的标志。

2、SysTick  重装载寄存器 -LOAD

SysTick  重装载寄存器 -LOAD

3、SysTick  当前值寄存器-VAL

SysTick  当前值寄存器-VAL

定时器工作方式:


图1 定时器工作方式

如图1所示:每经过一个Systick时钟,VAL寄存器值-1,当VAL=0时(可产生中断),LOAD寄存器中的重装载值赋值给VAL寄存器作为初值再继续上面步骤。


三、怎么利用SysTick 做us和ms延时?

从上面的介绍已经知道了,用SysTick做延迟,取决于两个参数:SysTick的时钟周期 和 重装载值LOAD

1、首先我们要知道1us和1ms SysTick的延迟次数(分别需要几个SysTick时钟)

图2 延迟初始化函数

如图2,如果不使用 OS(操作系统 )的时候,只是设置一下 SysTick 的时钟源(SYSCLK)以及确定 fac_us (1us 需要的SysTick时钟数目)和 fac_ms(1ms 需要的SysTick时钟数目) 的值。

1)、SysTick->CTRL&=~(1<<2);便是选择外部时钟作为SysTick时钟源,如果为72M,则它的时钟为9M.(对应周期为us级别)

2)、fac_us=SYSCLK/8;那么延迟1us,需要72/8=9次SysTick时钟周期

3)、fac_ms=(u16)fac_us*1000;则,延迟1ms,需要9000次SysTick时钟周期。

2、此时我们来看看实现延迟n us的函数(正点原子)如图3

图3  延迟 n(us)

图3 的代码其实很简单只需要变化重装载值LOAD即可,1us需要fac_us次SysTick时钟,那么nus便需要nus*fac_us次SysTick时钟;装载好之后清空当前值寄存器VAL,再开启倒数功能,下面只需等待直到控制和状态寄存器CTRL第16位置1(即倒数到0),跳出循环,关闭计数器,清空VAL值便OK了。

3、实现延迟n ms的函数便是同理了,也是改变重装载计数器LOAD的值即可(用延迟1ms的SysTick时钟周期*n)。如图4 

图4  延迟 n( ms )

需要注意的是,重装载计数器LOAD是一个24位的计数器,装载的值不要超出即可(nms*fac_ms<=2^24和nus*fac_us<=2^24)。

最后如果想要调用两个延迟函数delay_ms()和delay_us(),得在主函数中先初始化即先执行delay_init()函数,来选择SysTick的时钟源,然后将两个因子fac_us (1us 需要的SysTick时钟数目)和 fac_ms(1ms 需要的SysTick时钟数目) 的值计算出来,再调用便好了。

上一篇下一篇

猜你喜欢

热点阅读