您的位置 首页 观点

LPC1114体系定时器(SysTick)

在LPC1114内部有一个特殊的定时器——系统定时器(SysTick),它位于Cortex-M0内核里面,是ARM内核的一部分,主要用来给操作系统提供时间片…

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; //当守时时刻届时,全局变量清零

SysTick->CTRL =0;//封闭守时器

}

可见上述守时是毫秒等级的,最长可守时699ms。

至此,第一个演示示例中的全部内容就都评论完了,可见在LPC1114中要完成一个简略的十二个LED替换闪耀,涉及到的内容仍是许多的。下面再来看一个流水灯的比如,要求完成一个12位的流水灯,时刻距离为100ms。假定LED选用共阳接法接在GPIO2端口,参阅代码如下:

#include
//===================体系守时器中止服务程序============================
void SysTick_Handler(void)
{
uint32_t temp;//界说暂时中心变量
temp = LPC_GPIO2->DATA;//读取当时端口2的值
temp = ~temp; //把中心变量进行取反
temp<<=1; //把中心变量进行左移一位
temp = ~temp; //再次把中心变量进行取反
LPC_GPIO2->DATA = temp; //把左移后的量赋给端口2
if(temp==0xFFF) //假如左移到头,则从头开始
{
LPC_GPIO2->DATA = 0xFFE;
}
}
//========================体系守时器初始化=============================
void SysTick_init(void)
{
SysTick->LOAD = (((24000)*100)-1);//设置100ms的守时
SysTick->VAL = 0; //计数清零
SysTick->CTRL |= ((1<<1)|(1<<0)); //答应中止,挑选半体系时钟,发动守时器
}
//============================主函数==================================
int main(void)
{
LPC_GPIO2->DIR = 0xFFF; //设置端口2为输出方向
LPC_GPIO2->DATA = 0xFFE;//端口2最低位输出0,点亮最末一个LED
SysTick_init();//调用体系守时器
while(1)
{
;//空循环
}
}

把程序编译后下载到LPC1114中,给体系上电,可看到接到端口2上的12个LED在闪耀活动。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/guandian/272831.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部