微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > LPC1114系统定时器(SysTick)

LPC1114系统定时器(SysTick)

时间:11-13 来源:互联网 点击:
LPC1114内部有一个特殊的定时器——系统定时器SysTick),它位于Cortex-M0内核里面,是ARM内核的一部分,主要用来给操作系统提供时间片轮转的定时,一般固定为10ms的定时,所以中文也称它为“嘀哒”定时器。在不跑操作系统时,可以把它当作普通定时器来用,一般用来进行程序延时。在前面的第一个演示示例中就用到过,下面就来讨论一下如何运用SysTick来提供延时。

系统定时器也位于“私有外设总线”(Private peripheral bus)内,其地址为0xE000E010~0xE000E01F。下面先来看一下SysTick的内部结构,如下图所示。

从上图中可以看出,SysTick定时器的位长度是24位,即最长的计数次数为16777216次,且计数为倒数计数形式,递减到0时产生中断请求。计数的脉冲可直接取系统时钟,也可取半系统时钟。下表给出了和SysTick相关的寄存器。

上表中,SYST_CSR是系统定时器的控制寄存器,负责SysTick的启动、中断使能、输入时钟选择、溢出标志读取等操作;SYST_RVR是系统定时器的初始值重载寄存器,负责SysTick的24位初值载入;SYST_CVR是系统定时器的当前值寄存器,负责获取SysTick的24位当前计数值,当对该寄存器进行写操作时,该寄存器的数值将会被清零;SYST_CALIB是系统定时器的校准值寄存器,负责SysTick的校准。

下面给出的是上表中控制寄存器SYST_CSR的全部位结构。

从表中可以看出,第0位是使能SysTick,值为1启动计数,值为0关闭计数;第1位是SysTick的中断使能位,值为1使能中断,值为0禁能中断;第2位是输入时钟的选择位,值为1时选择系统时钟做为计数脉冲,值为0时选择半系统时钟做为计数脉冲的参考时钟;第16位是溢出标志位,当计数的值递减到0时,该位被置1,在读取该置后自动清零。

从上述可以看出,其实系统定时器就是一个普通的定时器,在使用时顺序进行如下操作即可:

1.给SYST_RVR寄存器写入初始值;

2.写SYST_CVR寄存器以对计数值进行清零;

3.设置SYST_CSR寄存器启动定时、使能中断以及选择时钟源。

下面给出系统时钟SysTick的结构体定义。

typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x000 (R/W) SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x004 (R/W) SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x008 (R/W) SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x00C (R/ ) SysTick Calibration Register */
} SysTick_Type;

SysTick定时器组的基址为0xE000E000,所以要将基址指针强制转换为上述结构体,还要加上下面的定义。

#define SCS_BASE (0xE000E000UL) /*!< System Control Space Base Address */
#define SysTick_BASE (SCS_BASE + 0x0010UL) /*!< SysTick Base Address */
#define SysTick ((SysTick_Type *) SysTick_BASE ) /*!< SysTick configuration struct */

对于系统定时器SysTick产生的中断,也有特定的入口函数,形式如下所示。

void SysTick_Handler(void)

{

系统定时中断服务程序部分

}

接下来讨论一下系统定时器的初始值设置,因为定时的时长由系统时钟频率、系统时钟选择和载入的初始值共同决定。假设系统时钟为48MHz,默认情况下SysTick的CLKSOURCE值为0,即选择半系统时钟频率。这样,输入给定时器计数的时钟就是48/2=24MHz,计数周期为1/(24MHz)=1/24us,则计24次就是1us的定时,但实际上SysTick采用的是倒数计数方式,即从最大值依次递减计数直到0产生溢出信号。所以24次计数实际上是0~23次,即最大值要减1,即24-1=23。同时要注意,由于计数位宽是24位,所以最大计数值不能超过2的24次方(即16777216),由此,可得出微秒级的初始值计算公式,如下:

LOAD=((24*us)-1),其中us取值范围1~699000

同理可得出毫秒级的初始值计算公式:

LOAD=((24000*ms)-1),其中ms取值范围1~699

上升到一般情况,定时初始值可用下面的公式来计算:

上式中,系统时钟SysClk的单位是MHz,CLKSOURCE的值是0或1,得到的是微秒级别的定时,要注意LOAD的值不能大于16777216。

下面来看一下前面第一个演示示例中的延时部分,代码如下:

static volatile uint32_t TimeTick = 0; //设置全局变量

void SysTick_Handler(void)

{

TimeTick++; //系统定时中断中,全局变量加1

}

void delay_ms(uint32_t ms)

{

SysTick->LOAD = (((24000)*ms)-1); //载入初始值

SysTick->VAL = 0;//写当前值寄存器使其清零

SysTick->CTRL |= ((1<1)|(1<0)); //打开中断,启动定时器,选择关系统时钟

while(!TimeTick);

TimeTick = 0;

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top