新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > LPC1114系統定時器(SysTick)

        LPC1114系統定時器(SysTick)

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

        系統定時器也位于“私有外設總線”(Private peripheral bus)內,其地址為0xE000E010~0xE000E01F。下面先來看一下SysTick的內部結構,如下圖所示。

        本文引用地址:http://www.104case.com/article/201611/316325.htm

        從上圖中可以看出,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在閃爍流動。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 顺义区| 密山市| 池州市| 陇南市| 博乐市| 南充市| 海门市| 竹山县| 施甸县| 滦南县| 揭阳市| 宁南县| 中西区| 潜山县| 新余市| 唐河县| 利津县| 鹤峰县| 政和县| 梁山县| 兴国县| 拜泉县| 阳原县| 江孜县| 武穴市| 乐清市| 秦安县| 汉川市| 教育| 梁河县| 洞头县| 察雅县| 依安县| 昭觉县| 沽源县| 那坡县| 景洪市| 临夏县| 马公市| 江山市| 阜宁县|