前言
通过本次学习你可以学到:
1、什么是SysTick定时器?
2、Systick定时器的操作。
3、如何使用Systick定时器。
正文内容参考 ARM Cortex-Mx 权威指南笔记 9.5小节。
什么是Systick定时器
SysTick定时器是Cortex-M处理器内部集成的名为系统节拍定时器,属于NVIC的一部分,并且可以产生Systick异常,是一个向下计数的24位定时器。可以作为一个周期的中断来触发内核,需要保证处理器运行在非特权模式下无法禁止该定时器,以免锁定系统。使用Systick定时器增加了软件的可移植性。由于所有的 Cortex-M处理器都具有相同的SysTick定时器,为一种Cortex-M3/M4 微控制器实现的OS也能适用于其他的Cortex-M3/M4 微控制器。
Systick定时器的操作
SysTick 定时器中存在4 个寄存器。CMSIS-Core 头文件中定义了一个名为SysTick的结构体,方便对这些寄存器的访问。
其内部的包含的24位计数器如图所示,根据处理器时钟或者一个参考信号来减小计数。
在设置控制和状态寄存器的第0位使能该计数器后,当前值寄存器在每个处理器时钟周期或参考时钟的上升沿都会减小。若计数减至0,它会从重加载寄存器中加载数值并继续运行。
另外一个寄存器为 SysTick 校准值寄存器。它为软件提供了校准信息。由于 CMSIS-Core 提供了一个名为 SystemCoreClock 的软件变量,因此它就未使用SysTick 校准值寄存器。系统初始化函数 Systemlnit()函数设置了该变量,而且每次系统时钟配置改变时都要对其进行更新。这种软件手段比利用 SysTick 校准值寄存器的硬件方式更灵活。
Systick的寄存器细节如图所示:
使用Systick定时器
最简单产生周期性Systick中断的方法是:
uint32 t SysTick Config(uint32 t ticks);
该函数将 SysTick 中断间隔设置为 ticks,使能计数器使用处理器时钟,然后设置 SysTick异常为最低优先级。
例如,若要在 30MHz 的时钟频率下产生1kHz的 SysTick 异常则可以使用
SysTick Config(SystemCoreClock / 1000);
变量 SystemCoreClock 应该存放正确的时钟频率数值,也就是 30X 10。另外只需
使用:
SysTick Config(30000); //30MHz /1000=30000
SysTick Handler(void)的触发频率就变成了1kHz。
许多情况下,可能会使用参考时钟或者不想使能 SysTick 中断,那么就不要使用 SysTick_Config 函数。此时需要直接操作 SysTick 寄存器,推荐使用下面的流程:
(1)将0写入 SysTick->CTRL禁止 SysTick 定时器。这个操作是可选的。若重用了其他代码,则由于 SysTick 之前可能已经使能过了,因此本操作是推荐使用的。
(2)将新的重加载值写人 SysTick->LOAD,重加载值应该为周期数减1。
(3)将任何数值写写入SysTick 当前值寄存器SysTick->VAL,该存器会被清零。
(4)写入SysTick 控制和状态寄存器 SysTick->CTRL启动 SysTick 定时器。
由于 SysTick 定时器向下计数到 0,因此,若要设置 SysTick 周期为 1000,则应该将重加载值(SysTick->LOAD)设置为999。
若要在轮询模式中使用 SysTick 定时器则可以利用 SysTick 控制和状态寄存器(SysTick->CTRL)中的计数标志来确定定时器何时变为 0。例如,可以将SysTick 定时器设置为特定数值,然后等它变为 0,并以此实现延时:
SysTick ->CTRL = 0; //禁止 SysTick
SysTick-> LOAD =0xFF; //计数范围 255~(256 个周期)
SysTick -> VAL =0; //清除当前值和计数标志
SysTick ->CTRL= 5; //使能 SysTick 定时器并使用处理器时钟
while((SysTick->CTRL&0x00010000)==0); //等待计数标志置位
SysTick->CTRL = 0; //禁止SysTick
若要将 SysTick 中断用作在一定时间后触发的单发操作,则可以将重加载值减小 12 个周
期,以补偿中断等待时间。例如,要使 SysTick 定时器在 300个时钟周期后执行:
volatile int SysTickFired; //全局软件标志,表示SsTickAlarm 已执行
SysTick->CTRL= 0; //禁止SysTick
SysTick->LOAD =(300-12); //设置重加载值,由于异常等待减去12
SysTick->VAL =0; //将当前值清为0
SysTickFired =0; //将软件标志设为0
SysTick ->CTRL = 0x7; //使能 SysTick,使能 SysTick 异常且使用处器时钟
while (SysTickFired == 0); //等待 SysTick处理将软件标志置位
其他考虑
在使用 SysTick 定时器时需要考虑以下几点:
1、SysTick 定时器中的寄存器只能在特权状态下访问
2、参考时钟在一些微控制器设计中可能会不存在。
3、若应用中存在嵌人式 OS,SysTick 定时器会被 OS 使用因此就不能再被应用务使用了。
4、当处理器在调试期间暂停时,SysTick 定时器会停止计数。
5、根据微控制器的实际设计SysTick 定时器可能会在某些休眠模式中停止计数