六:SysTick定时器

学记实验室2020-09-15 16:52:21

现在我们开始讲解SysTick定时器

那么什么是SysTick定时器呢

Systick定时器,是一个简单的定时器,对于CM3,CM4内核芯片,都有Systick定时器。

Systick定时器常用来做延时,或者实时系统的心跳时钟。这样做的好处是可以节省MCU资源,不用浪费一个定时器。比如UCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做UCOS心跳时钟。


Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0时,将从RELOAD 寄存器中自动重装载定时初值。(比如100从后往前数,数到0后再重装载到100,以此来形成永不停息的循环)

只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。

SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。[可以理解为SysTick是可以产生中断的,比如从100到0就可以中断一次]

Systick中断的优先级也可以设置。

sdfd


SysTick定时器有4个寄存器

分别是

控制及状态寄存器:SysTick_CTRL

重装载数值寄存器:SysTick_LOAD

当前数值寄存器:SysTick_VAL

校准数值寄存器:SysTick_CALRB


CTRL寄存器

*可以在Cortex-M3权威指南(中文)找到

位段0就是操纵是否使能的。位段1主要用于是否要使用中断。位段2中对于STM32外部时钟源是HCLK(AHB总线时钟)的1/8,内核时钟是HCLK时钟。

配置函数:SysTick_CLKSourceConfig();

段位16是在一个周期后给该位为1,如果再读取该位再清零,这可以防止误读。


LOAD寄存器

用以自动重装载值


VAL寄存器

就是读取当前值的


还有一个校准寄存器,但使用较少,就暂时不讲


SysTick库函数

固件库中的Systick相关函数:

  1. SysTick_CLKSourceConfig()

//Systick时钟源选择  misc.c文件中

   2. SysTick_Config(uint32_t ticks)

//初始化systick,时钟为HCLK,并开启中断

//core_cm3.h/文件中

Systick中断服务函数:

void SysTick_Handler(void);


下面开始分析

看到这个函数

它是用来选择时钟源的

配置的寄存器是Systick的CRTL寄存器

可以看到Systick的定义属于内核级别的

查看定义

有一个结构体类型

将寄存器名称和地址映衬

回到前面看它的入口参数

只能选择两种入口参数

这个在上文讲过

在系统时钟72M时

如果我们选择8分频的话

SysTick时钟就是9M

如果选择HCLK就直接是72M

再看这个函数

这个Systick_config有什么作用呢

它是开启Systick中断

使能Systick

以及配置Systick中断的时间多少

两个中断之间的时间间隔

中间能有几个Systick时钟周期

第一行代码是对有效性进行判断

因为systick是24位

是有范围的

看到下一句

LOAD用以设置重装载值

如果我们定时的值是1000

那么我们就需要给LOAD=999

主要因为这里的-1

然后设置优先级

具体下面讲

对于的分别是:

把VAL设置为0

选择时钟源

开启中断

使能定时器


现在我们看这样一个程序

static __IO uint32_t TimingDelay;//定义了TimingDelay这个变量

void Delay(__IO uint32_t nTime)//我们需要使用这个函数,且有一个入口参数

{

   TimingDelay = nTime;

   while(TimingDelay != 0);//在这一块等中断,等到=0时就退出函数实现200ms延时

}

void SysTick_Handler(void)//每到1ms就会用到这个中断

{

    if (TimingDelay != 0x00)//这个变量只要不=0就-1

     {

       TimingDelay--;

     }

}

 int main(void)

 {  …

    if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms这是我们首先调用的函数,如果我们把systick时钟源设置为HCLK,那么在系统时钟中SystemCoreClock=72M,即72000000,我们除以1000设置为入口参数,也就是设置中断的时间间隔为1ms。72000/72000000=0.001s

     {

     while (1);

     }

    while(1)

     { Delay(200);//200ms//在这里入口参数200进入函数

     …

     }

}


在我们原子的例程中

delay函数的编写方法是扫描查询

在delay.h中可以看到这些

然后我们看到delay.c

有OS的宏定义

这一块我们不讲

因为是实时系统的时候用的

我们只讲解基础的

首先上面定义了这两个因子

看到delay初始化函数

OS部分不看

看我们框起来的地方

首先选择Systick的时钟源

HCLK8分频就是9M

fac_us=9M/8000000=9

也就是1us=9个systick周期

因为us的因子是9

ms自然是其1000倍

然后看后面两个函数

delay_us的入口参数是有限制的

是2的24次方-1,

因为LOAD是24位的

delay_ms的入口参数也同理

函数的解释可以看注释

具体寄存器上面都讲过

函数就讲到这里

写好delay函数之后

进行调用需要delay.h头文件

在延时之前需要delay_init来初始化

初始化要选择时钟源和写因子

如果不初始化的话因子为0

延时就会错误