LPC1114系统定时器(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;
LPC1114系统定时器SysTic 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)