首先我们要明白什么是SysTick定时器?
Sys 系统 ,tick 滴答声 ,系统滴答滴答很形象地表示了它是一个系统节拍器。SysTick 是一个24 位的倒计数定时器,当计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息。
为什么要设置SysTick定时器?
(1)产生操作系统的时钟节拍
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。SysTick的最大使命,就是定期地产生异常请求,作为系统的时基。OS都需要这种“滴答”来推动任务和时间的管理。
(2)便于不同处理器之间程序移植。
Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。它使操作系统和其它系统软件在CM3器件间的移植变得简单多了,因为在所有CM3产品间对其处理都是相同的。
(3)作为一个闹铃测量时间。
SysTick定时器还可以用作闹钟,作为启动一个特定任务的时间依据。它作为一个闹铃,用于测量时间。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。
再来看看SysTick的用法
(1)我们对一个系统编程,老说编程编程什么的,到底我们在编什么程?当然这个问题要探讨起来可能有点远了。我来说说对SysTick的编程,对单片机的编程不过就是对单片机里面的寄存器进行控制,使整个软硬件系统处于一种在你的掌控之下的状态。这就是了嘛,现在我是头,我对我的手下下达一些指令,让它们去做一些事情。所以我们想搞清楚怎样控制SysTick我们还得看我们能对它的哪些部分可以控制。那些部分就是寄存器。
SysTick有4个寄存器 :
寄存器 描述
CTRL SysTick 控制和状态寄存器
LOAD SysTick 重装载值寄存器
VAL SysTick 当前值寄存器
CALIB SysTick 校准值寄存器
对应地在固件函数库中定义了这个东西
typedef struct
{
vu32 CTRL;
vu32 LOAD;
vu32 VAL;
vuc32 CALIB;
} SysTick_TypeDef;
在这背后,已经对定义的寄存器进行了一个地址映射。当我们操控我们定义的寄存器时实际上已是通过那种映射关系操控了芯片内部的值。其实在STM32中对寄存器的操作都是通过这种方式进行的。
具体的映射过程如下,我们可以看一下:
#define SCS_BASE ((u32)0xE000E000)
#define SysTick_BASE (SCS_BASE + 0x0010)
#ifndef DEBUG
...
#ifdef _SysTick
#define SysTick ((SysTick_TypeDef *) SysTick_BASE)
#endif
...
#else
...
#ifdef _SysTick
EXT SysTick_TypeDef *SysTick;
#endif
...
#endif
#ifdef _SysTick
SysTick = (SysTick_TypeDef *) SysTick_BASE;
#endif
为了访问SysTick寄存器,, _SysTick必须在文件“stm32f10x_conf.h”中定义如下:
#define _SysTick
映射过程就不作讨论了。总这这样映射的结果是我们能直接使用SysTick。那就来看一下有关寄存器的设置。
(2)SysTick里的寄存器我也简单地把它理解为是一个32位数。
这里有一张图:
在最新的STM32固件库中的core_cm3.c中提供了这样一个函数来供我们配置SysTick,当我们须要用到SysTick时调用它就可以了:
static __INLINE uint32_t SysTick_Config(uint32_t ticks)//ticks 是要重装载的值
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);
SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
总结:在配置过程对CTRL//LOAD/VAL三个寄存器进行了配置,初始化了SysTick使用的时钟,清除系统当前值,装入重装值,使能SysTick,使SysTick能响应中断,说了半天其实就这一句话。在主程序中调用SysTick_Configuration( uint32_t ticks ),输入重装值就配置完成了。
(3)SysTick 的中断处理函数在stm32f10x_it.c
函数原型为void SysTick_Handler(void)
{
// user code
}
用户只要把须要处理的程序填入这里就完成啦。
例子:
正如上面叙述,SysTick的使用为:
(1)配置SysTick
(2)写中断函数
我们产生1ms的廷时:
在我们自己编写的main.c中有:
//前面的省略 ……
Volatile unsigned int TimingDelay ; //定义一个全局变量,用于计数计时值
//中间部分省略……
void Delay_Ms( uint32_t nTime ) //我们须要的廷时函数
{
TimingDelay = nTime ; //把廷时值赋值给TimingDelay;
while( TimingDelay != 0 ); //等待计时时间到,在SysTick的中断函数
//中每1ms对TimingDelay减1
}
int main(void)
{
//配置电源
//配置GPIO
//配置NVIC 等等
while( SysTick_Configuration( 72000 ) != 0 ) ; //配置SysTick,装入倒数值,我
//们假设系统时钟为72MHz,则
//要定时1ms,输入的倒数值为
//72000
while(1)
{
//user code
}
}
在stm32f10x_it.c中:
//前面省略 ……
extern volatile unsigned int TimingDelay;
void SysTick_Handler(void)
{
// user code
TimingDelay--;
}
上一篇:AVR单片机的相关总结
下一篇:STM32之SysTick
推荐阅读最新更新时间:2024-03-16 15:46