新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > LPC1114系統(tǒng)定時(shí)器(SysTick)

LPC1114系統(tǒng)定時(shí)器(SysTick)

作者: 時(shí)間:2016-11-13 來源:網(wǎng)絡(luò) 收藏
LPC1114內(nèi)部有一個(gè)特殊的定時(shí)器——系統(tǒng)定時(shí)器SysTick),它位于Cortex-M0內(nèi)核里面,是ARM內(nèi)核的一部分,主要用來給操作系統(tǒng)提供時(shí)間片輪轉(zhuǎn)的定時(shí),一般固定為10ms的定時(shí),所以中文也稱它為“嘀噠”定時(shí)器。在不跑操作系統(tǒng)時(shí),可以把它當(dāng)作普通定時(shí)器來用,一般用來進(jìn)行程序延時(shí)。在前面的第一個(gè)演示示例中就用到過,下面就來討論一下如何運(yùn)用SysTick來提供延時(shí)。

系統(tǒng)定時(shí)器也位于“私有外設(shè)總線”(Private peripheral bus)內(nèi),其地址為0xE000E010~0xE000E01F。下面先來看一下SysTick的內(nèi)部結(jié)構(gòu),如下圖所示。

本文引用地址:http://2s4d.com/article/201611/316325.htm

從上圖中可以看出,SysTick定時(shí)器的位長度是24位,即最長的計(jì)數(shù)次數(shù)為16777216次,且計(jì)數(shù)為倒數(shù)計(jì)數(shù)形式,遞減到0時(shí)產(chǎn)生中斷請(qǐng)求。計(jì)數(shù)的脈沖可直接取系統(tǒng)時(shí)鐘,也可取半系統(tǒng)時(shí)鐘。下表給出了和SysTick相關(guān)的寄存器。

上表中,SYST_CSR是系統(tǒng)定時(shí)器的控制寄存器,負(fù)責(zé)SysTick的啟動(dòng)、中斷使能、輸入時(shí)鐘選擇、溢出標(biāo)志讀取等操作;SYST_RVR是系統(tǒng)定時(shí)器的初始值重載寄存器,負(fù)責(zé)SysTick的24位初值載入;SYST_CVR是系統(tǒng)定時(shí)器的當(dāng)前值寄存器,負(fù)責(zé)獲取SysTick的24位當(dāng)前計(jì)數(shù)值,當(dāng)對(duì)該寄存器進(jìn)行寫操作時(shí),該寄存器的數(shù)值將會(huì)被清零;SYST_CALIB是系統(tǒng)定時(shí)器的校準(zhǔn)值寄存器,負(fù)責(zé)SysTick的校準(zhǔn)。
下面給出的是上表中控制寄存器SYST_CSR的全部位結(jié)構(gòu)。
從表中可以看出,第0位是使能SysTick,值為1啟動(dòng)計(jì)數(shù),值為0關(guān)閉計(jì)數(shù);第1位是SysTick的中斷使能位,值為1使能中斷,值為0禁能中斷;第2位是輸入時(shí)鐘的選擇位,值為1時(shí)選擇系統(tǒng)時(shí)鐘做為計(jì)數(shù)脈沖,值為0時(shí)選擇半系統(tǒng)時(shí)鐘做為計(jì)數(shù)脈沖的參考時(shí)鐘;第16位是溢出標(biāo)志位,當(dāng)計(jì)數(shù)的值遞減到0時(shí),該位被置1,在讀取該置后自動(dòng)清零。
從上述可以看出,其實(shí)系統(tǒng)定時(shí)器就是一個(gè)普通的定時(shí)器,在使用時(shí)順序進(jìn)行如下操作即可:
1.給SYST_RVR寄存器寫入初始值;
2.寫SYST_CVR寄存器以對(duì)計(jì)數(shù)值進(jìn)行清零;
3.設(shè)置SYST_CSR寄存器啟動(dòng)定時(shí)、使能中斷以及選擇時(shí)鐘源。
下面給出系統(tǒng)時(shí)鐘SysTick的結(jié)構(gòu)體定義。
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定時(shí)器組的基址為0xE000E000,所以要將基址指針強(qiáng)制轉(zhuǎn)換為上述結(jié)構(gòu)體,還要加上下面的定義。

#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 */
對(duì)于系統(tǒng)定時(shí)器SysTick產(chǎn)生的中斷,也有特定的入口函數(shù),形式如下所示。
void SysTick_Handler(void)

{

系統(tǒng)定時(shí)中斷服務(wù)程序部分

}

接下來討論一下系統(tǒng)定時(shí)器的初始值設(shè)置,因?yàn)槎〞r(shí)的時(shí)長由系統(tǒng)時(shí)鐘頻率、系統(tǒng)時(shí)鐘選擇和載入的初始值共同決定。假設(shè)系統(tǒng)時(shí)鐘為48MHz,默認(rèn)情況下SysTick的CLKSOURCE值為0,即選擇半系統(tǒng)時(shí)鐘頻率。這樣,輸入給定時(shí)器計(jì)數(shù)的時(shí)鐘就是48/2=24MHz,計(jì)數(shù)周期為1/(24MHz)=1/24us,則計(jì)24次就是1us的定時(shí),但實(shí)際上SysTick采用的是倒數(shù)計(jì)數(shù)方式,即從最大值依次遞減計(jì)數(shù)直到0產(chǎn)生溢出信號(hào)。所以24次計(jì)數(shù)實(shí)際上是0~23次,即最大值要減1,即24-1=23。同時(shí)要注意,由于計(jì)數(shù)位寬是24位,所以最大計(jì)數(shù)值不能超過2的24次方(即16777216),由此,可得出微秒級(jí)的初始值計(jì)算公式,如下:

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

同理可得出毫秒級(jí)的初始值計(jì)算公式:

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

上升到一般情況,定時(shí)初始值可用下面的公式來計(jì)算:

上式中,系統(tǒng)時(shí)鐘SysClk的單位是MHz,CLKSOURCE的值是0或1,得到的是微秒級(jí)別的定時(shí),要注意LOAD的值不能大于16777216。

下面來看一下前面第一個(gè)演示示例中的延時(shí)部分,代碼如下:

static volatile uint32_t TimeTick = 0; //設(shè)置全局變量

void SysTick_Handler(void)

{

TimeTick++; //系統(tǒng)定時(shí)中斷中,全局變量加1

}

void delay_ms(uint32_t ms)

{

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

SysTick->VAL = 0;//寫當(dāng)前值寄存器使其清零

SysTick->CTRL |= ((1<<1)|(1<<0)); //打開中斷,啟動(dòng)定時(shí)器,選擇關(guān)系統(tǒng)時(shí)鐘

while(!TimeTick);

TimeTick = 0; //當(dāng)定時(shí)時(shí)間到時(shí),全局變量清零

SysTick->CTRL =0;//關(guān)閉定時(shí)器

}

可見上述定時(shí)是毫秒級(jí)別的,最長可定時(shí)699ms。

至此,第一個(gè)演示示例中的全部?jī)?nèi)容就都討論完了,可見在LPC1114中要實(shí)現(xiàn)一個(gè)簡(jiǎn)單的十二個(gè)LED交替閃爍,涉及到的內(nèi)容還是很多的。下面再來看一個(gè)流水燈的例子,要求實(shí)現(xiàn)一個(gè)12位的流水燈,時(shí)間間隔為100ms。假設(shè)LED采用共陽接法接在GPIO2端口,參考代碼如下:

#include
//===================系統(tǒng)定時(shí)器中斷服務(wù)程序============================
void SysTick_Handler(void)
{
uint32_t temp;//定義臨時(shí)中間變量
temp = LPC_GPIO2->DATA;//讀取當(dāng)前端口2的值
temp = ~temp; //把中間變量進(jìn)行取反
temp<<=1; //把中間變量進(jìn)行左移一位
temp = ~temp; //再次把中間變量進(jìn)行取反
LPC_GPIO2->DATA = temp; //把左移后的量賦給端口2
if(temp==0xFFF) //如果左移到頭,則從頭開始
{
LPC_GPIO2->DATA = 0xFFE;
}
}
//========================系統(tǒng)定時(shí)器初始化=============================
void SysTick_init(void)
{
SysTick->LOAD = (((24000)*100)-1);//設(shè)置100ms的定時(shí)
SysTick->VAL = 0; //計(jì)數(shù)清零
SysTick->CTRL |= ((1<<1)|(1<<0)); //允許中斷,選擇半系統(tǒng)時(shí)鐘,啟動(dòng)定時(shí)器
}
//============================主函數(shù)==================================
int main(void)
{
LPC_GPIO2->DIR = 0xFFF; //設(shè)置端口2為輸出方向
LPC_GPIO2->DATA = 0xFFE;//端口2最低位輸出0,點(diǎn)亮最末一個(gè)LED
SysTick_init();//調(diào)用系統(tǒng)定時(shí)器
while(1)
{
;//空循環(huán)
}
}

把程序編譯后下載到LPC1114中,給系統(tǒng)上電,可看到接到端口2上的12個(gè)LED在閃爍流動(dòng)。



評(píng)論


技術(shù)專區(qū)

關(guān)閉