日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

STM32系统滴答定时器(systick)应用

發(fā)布時間:2025/6/15 windows 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32系统滴答定时器(systick)应用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一:系統(tǒng)滴答定時器(systick)

1.systick介紹

???? Systick就是一個定時器而已,只是它放在了NVIC中,主要的目的是為了給操作系統(tǒng)提供一個硬件上的中斷(號稱滴答中斷)。滴答中斷?這里來簡單地解釋一下。操作系統(tǒng)進行運轉(zhuǎn)的時候,也會有“心跳”。它會根據(jù)“心跳”的節(jié)拍來工作,把整個時間段分成很多小小的時間片,每個任務(wù)每次只能運行一個“時間片”的時間長度就得退出給別的任務(wù)運行,這樣可以確保任何一個任務(wù)都不會霸占整個系統(tǒng)不放。或者把每個定時器周期的某個時間范圍賜予特定的任務(wù)等,還有操作系統(tǒng)提供的各種定時功能,都與這個滴答定時器有關(guān)。因此,需要一個定時器來產(chǎn)生周期性的中斷,而且最好還讓用戶程序不能隨意訪問它的寄存器,以維持操作系統(tǒng)“心跳”的節(jié)律。?只要不把它在SysTick控制及狀態(tài)寄存器中的使能位清除,就永不停息。

?????知道systick在系統(tǒng)中的地位后,我們來了解systick的實現(xiàn)。這里只是舉例說明systick的使用。它有四個寄存器,筆者把它列出來:

??? SysTick->CTRL,??????? --控制和狀態(tài)寄存器

??? SysTick->LOAD,? ??????--重裝載寄存器

?? ?SysTick->VAL,?????? ???--當(dāng)前值寄存器

?? SysTick->CALIB,???? ???--校準值寄存器????

下圖有他們的分別描述:?????下圖引用地址:http://blog.csdn.net/marike1314/article/details/5673684

2.systick編程

????現(xiàn)在我們想通過Systick定時器做一個精確的延遲函數(shù),比如讓LED精確延遲1秒鐘閃亮一次。

????思路:利用systick定時器為遞減計數(shù)器,設(shè)定初值并使能它后,它會每個1系統(tǒng)時鐘周期計數(shù)器減,計數(shù)到?0時,SysTick計數(shù)器自動重裝初值并繼續(xù)計數(shù),同時觸發(fā)中斷。

那么每次計數(shù)器減到0,時間經(jīng)過了:系統(tǒng)時鐘周期?*計數(shù)器初值。我們使用72M作為系統(tǒng)時鐘,那么每次計數(shù)器減1所用的時間是1/72M,計數(shù)器的初值如果是72000,那么每次計數(shù)器減到0,時間經(jīng)過(1/72M)*72000= 0.001,即1ms(簡單理解:用72M的時鐘頻率,即1s計數(shù)72M=72000000次,那1ms計數(shù)72000次,所以計數(shù)值為72000?

?

首先,我們需要有一個72Msystick系統(tǒng)時鐘,那么,使用下面這個時鐘OK?

??? SystemInit();

????這個函數(shù)可以讓主頻運行到72M。可以把它作為systick的時鐘源。

????接著開始配置systick,實際上配置systick的嚴格過程如下:

??? 1、調(diào)用SysTick_CounterCmd()????? ?--失能SysTick計數(shù)器

??? 2、調(diào)用SysTick_ITConfig()????????? --失能SysTick中斷

??? 3、調(diào)用SysTick_CLKSourceConfig()? --設(shè)置SysTick時鐘源。

??? 4、調(diào)用SysTick_SetReload()???????? --設(shè)置SysTick重裝載值。

??? 5、調(diào)用SysTick_ITConfig()?????? ???--使能SysTick中斷

??? 6、調(diào)用SysTick_CounterCmd()?????? --開啟SysTick計數(shù)器??????????????????????????????????????????????????????

????這里大家一定要注意,必須使得當(dāng)前寄存器的值VAL等于0

??? SysTick->VAL? = (0x00);只有當(dāng)VAL值為0時,計數(shù)器自動重載RELOAD

接下來就可以直接調(diào)用Delay();函數(shù)進行延遲了。延遲函數(shù)的實現(xiàn)中,要注意的是,全局變量TimingDelay必須使用volatile,否則可能會被編譯器優(yōu)化。

下面我們來做一下程序分析:

1)系統(tǒng)時鐘進配置

首先我們對系統(tǒng)時鐘進行了配置并且SetSysClock(void)函數(shù)使用72M作為系統(tǒng)時鐘;

為了方面看清代碼我選擇截圖:

2)先來看看主函數(shù)

[plain]?view plaincopy
  • int?main(void)??
  • ??
  • {????????????unsigned?char?i=0;??
  • ??
  • ????????unsigned?char?a[]?=?"abncdee";??
  • ??
  • ??????????
  • ??
  • ????????SystemInit1();//系統(tǒng)初始化??
  • ??
  • ???
  • ??
  • ???????if?(SysTick_Config(72000))??//1ms響應(yīng)一次中斷??
  • ??
  • ????????{???
  • ??
  • ????????????/*?Capture?error?*/??
  • ??
  • ?????????????????while?(1);??
  • ??
  • ????????}???
  • ??
  • ????????/*解析:因為要求是每500ms往中位機發(fā)數(shù)據(jù)一件事,所以放在while語句中,??
  • ??
  • *送據(jù)+延時可以完成相當(dāng)于中斷的效果;??
  • ??
  • ???????????????*若是多任務(wù)中,其中一個任務(wù)需要中斷,這把這個任務(wù)放在中斷函數(shù)中調(diào)用;??
  • ??
  • ???????????????*/??
  • ??
  • ????????while?(1)??
  • ??
  • ????????{??
  • ??
  • ?????????????//測試代碼:測試定時器功能,通過延時來測試??
  • ??
  • ???
  • ??
  • ?????????????GPIO_SetBits(GPIOC,?GPIO_Pin_6);??????//V6??
  • ??
  • ?????????????Delay(50);??
  • ??
  • ?????????????GPIO_ResetBits(GPIOC,?GPIO_Pin_6);?????????//V6??
  • ??
  • ?????????????Delay(50);??
  • ??
  • ????????????????????????
  • ??
  • ????????????//功能1代碼:每500ms發(fā)送數(shù)據(jù)??
  • ??
  • ???????????????/*??
  • ??
  • ??????????????????????UART2_TX485_Puts("123450");??
  • ??
  • ??????????????????????Delay(500);??
  • ??
  • ???????????*/??
  • ??
  • ????????????//功能2代碼:上位發(fā)特定指令,中位機執(zhí)行相應(yīng)操作??
  • ??
  • ??????????????//?????RS485_Test();??
  • ??
  • ??????????????}???????
  • ??
  • }??
  • 3)系統(tǒng)滴答定時器的配置--主角登場:

    主函數(shù)中:?SysTick_Config(72000) ;滴答定時器的參數(shù)是72000即計數(shù)72000

    (因為我們使用72M的時鐘頻率,即1s計數(shù)72M=72000000次,那1ms計數(shù)72000次,所以計數(shù)值為72000?

    在文件Core_cm3.h

    SysTick_Config函數(shù)的具體實現(xiàn)如下:

    [html]?view plaincopy
  • static?__INLINE?uint32_t?SysTick_Config(uint32_t?ticks)??
  • ??
  • {???
  • ??
  • ????if?(ticks>SYSTICK_MAXCOUNT)????
  • ??
  • ?????return?(1);??????/*?Reload?value?impossible?*/??
  • ??
  • ????SysTick->LOAD?=?(ticks?&?SYSTICK_MAXCOUNT)?-?1;//systick重裝載值寄存器???/*?set?reload?register?*/??
  • ??
  • ????NVIC_SetPriority?(SysTick_IRQn,?(1<<__NVIC_PRIO_BITS)?-?1);?/*?set?Priority?for?Cortex-M0?System?Interrupts?*/??
  • ??
  • ????SysTick->VAL?=?(0x00);??//systick當(dāng)前值寄存器????????????????????????????????
  • ??
  • ???/*?Load?the?SysTick?Counter?Value?*/??
  • ???SysTick->CTRL?=?(1?<<?SYSTICK_CLKSOURCE)?|?(1<<SYSTICK_ENABLE)?|?(1<<SYSTICK_TICKINT);//使能IRQ(普通中斷)和系器?????????return(0);??????/*?Function?successful?*/??
  • ??
  • }?????????????????????????????????????????
  • 我們來看一下這句代碼:SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<<SYSTICK_ENABLE) | (1<<SYSTICK_TICKINT);?這是使能IRQ(普通中斷)和系統(tǒng)定時器,為什么要使能中斷和系統(tǒng)定時器呢?

    下面我們來看一下stm32f10x_it.h文件中:

    找到滴答定時器中斷函數(shù):SysTickHandler()

    void SysTickHandler(void)

    {

    ??? TimingDelay_Decrement();

    }

    從上文我們通過裝載的計數(shù)值72000知道每1ms發(fā)生一次中斷,在中斷函數(shù)中調(diào)用一個函數(shù)TimingDelay_Decrement();-----即每1ms發(fā)生中斷時就調(diào)用到此函數(shù);

    下面我們來看看TimingDelay_Decrement();在干些什么?

    [html]?view plaincopy
  • /*****************************************************************??
  • ??
  • *函數(shù)名稱:TimingDelay_Decrement??
  • ??
  • *功能描述:中斷里調(diào)用此函數(shù),即沒發(fā)生一次中斷,此函數(shù)被調(diào)用,此函數(shù)里???????
  • ??
  • *??????????的變量TimingDelay?相當(dāng)于減法計數(shù)器??
  • ??
  • *???
  • ??
  • *輸入?yún)?shù):無??
  • ??
  • *返回值:無??
  • ??
  • *其他說明:無??
  • ??
  • *當(dāng)前版本:v1.0??
  • ??
  • *作????者:?梁尹宣??
  • ??
  • *完成日期:2012年8月3日??
  • ??
  • *修改日期??????版本號??????修改人??????修改內(nèi)容??
  • ??
  • *-----------------------------------------------------------------??
  • ??
  • *??
  • ??
  • ******************************************************************/??
  • ??
  • ?????
  • ??
  • void?TimingDelay_Decrement(void)????
  • ??
  • {????
  • ??
  • ????
  • ??
  • ??if?(TimingDelay?!=?0x00)????
  • ??
  • ??{?????
  • ??
  • ????TimingDelay--;????
  • ??
  • ??}??
  • ??
  • }????
  • ??
  • 我們看了TimingDelay的定義,又看了還有哪些函數(shù)調(diào)用到這個變量,如下:??
  • ??
  • /*****************************************************************??
  • ??
  • *????????????????????????????????????????全局變量??
  • ??
  • ******************************************************************/??
  • ??
  • ???
  • ??
  • static?__IO?uint32_t?TimingDelay=0;??
  • ??
  • ???????????
  • ??
  • /*****************************************************************??
  • ??
  • *函數(shù)名稱:????Delay??
  • ??
  • *功能描述:????利用系統(tǒng)時鐘計數(shù)器遞減達到延時功能??
  • ??
  • *???
  • ??
  • *輸入?yún)?shù):nTime?:需要延的時毫秒數(shù)??
  • ??
  • *返回值:無??
  • ??
  • *其他說明:無??
  • ??
  • *當(dāng)前版本:v1.0??
  • ??
  • *作????者:?梁尹宣??
  • ??
  • *完成日期:2012年8月3日??
  • ??
  • *修改日期??????版本號??????修改人??????修改內(nèi)容??
  • ??
  • *-----------------------------------------------------------------??
  • ??
  • *??
  • ??
  • ******************************************************************/??
  • ??
  • ???
  • ??
  • void?Delay(__IO?uint32_t?nTime)//delay被調(diào)用時,nTime=500??
  • ??
  • {???
  • ??
  • ??TimingDelay?=?nTime;??
  • ??
  • ???
  • ??
  • ??while(TimingDelay?!=?0);??
  • ??
  • }??
  • 通過上面幾個函數(shù)我們知道了,在調(diào)用Delay(500)nTime=500;在后在Delay()函數(shù)中TimingDelay?=nTime;(即TimingDelay=500是它的初始值),再TimingDelay_Decrement(void)函數(shù)的作用就是把TimingDelay- -;每毫秒進行遞減直到減到0為止;這樣就起到一個延時的作用;

    現(xiàn)在我們做出來的Delay(1),就是1毫秒延遲。Delay(1000)就是1秒。

    ? 我們來畫個圖,方便這幾個函數(shù)間關(guān)系的理解:

    我們在返回到主函數(shù)main()中看這幾條語句:紅色標注de

    [html]?view plaincopy
  • while?(1)??
  • ??
  • ????????{??
  • ??
  • ?????????????//測試代碼:測試定時器功能,通過延時來測試??
  • ??
  • ?????????????GPIO_SetBits(GPIOC,?GPIO_Pin_6);??????//V6???
  • ??
  • ?????????????Delay(500);??
  • ??
  • ?????????????GPIO_ResetBits(GPIOC,?GPIO_Pin_6);?????????//V6???
  • ??
  • ?????????????Delay(500);??
  • ??
  • ????????????????????????
  • ??
  • ????????????//功能1代碼:每500ms發(fā)送數(shù)據(jù)??
  • ??
  • ???????????????/*??
  • ??
  • ??????????????????????UART2_TX485_Puts("123450");??
  • ??
  • ??????????????????????Delay(500);??
  • ??
  • ???????????*/??
  • ??
  • ????????????//功能2代碼:上位發(fā)特定指令,中位機執(zhí)行相應(yīng)操作??
  • ??
  • ??????????????//?????RS485_Test();??
  • ??
  • ??????????????}???????
  • 經(jīng)過上面系統(tǒng)定時器的分析我們知道Delay(500);是延時500ms ;那么LED就是每隔500ms閃爍一次;

    上面有關(guān)系統(tǒng)滴答定時器的應(yīng)用講解基本完畢!

    ?有關(guān)SysTick編譯后的源代碼包,(其實客官細心的話一經(jīng)發(fā)現(xiàn)上面代碼含有485通訊代碼,

    只不過被暫時屏蔽掉了,下一節(jié)將講到)我放在我的資源里:http://download.csdn.net/detail/yx_l128125/4511622

    ?

    下面我們來看看一下參考資料的問題,一邊對上面我寫的博客有更深入的理解:

    Cortex-M3權(quán)威指南》

    Cortex-M3 Technical Reference Manual

    Q:什么是SYSTick定時器?

    SysTick?是一個24位的倒計數(shù)定時器,當(dāng)計到0時,將從RELOAD寄存器中自動重裝載定時初值。只要不把它在SysTick控制及狀態(tài)寄存器中的使能位清除,就永不停息。

    Q:為什么要設(shè)置SysTick定時器?

    1)產(chǎn)生操作系統(tǒng)的時鐘節(jié)拍

    SysTick定時器被捆綁在NVIC,用于產(chǎn)生SYSTICK異常(異常號:15)。在以前,大多操作系統(tǒng)需要一個硬件定時器來產(chǎn)生操作系統(tǒng)需要的滴答中斷,作為整個系統(tǒng)的時基。因此,需要一個定時器來產(chǎn)生周期性的中斷,而且最好還讓用戶程序不能隨意訪問它的寄存器,以維持操作系統(tǒng)心跳的節(jié)律。

    2)便于不同處理器之間程序移植。

    CortexM3處理器內(nèi)部包含了一個簡單的定時器。因為所有的CM3芯片都帶有這個定時器,軟件在不同?CM3器件間的移植工作得以化簡。該定時器的時鐘源可以是內(nèi)部時鐘(FCLKCM3上的自由運行時鐘),或者是外部時鐘(?CM3處理器上的STCLK信號)。

    不過,STCLK的具體來源則由芯片設(shè)計者決定,因此不同產(chǎn)品之間的時鐘頻率可能會大不相同,你需要檢視芯片的器件手冊來決定選擇什么作為時鐘源。SysTick定時器能產(chǎn)生中斷CM3為它專門開出一個異常類型,并且在向量表中有它的一席之地。它使操作系統(tǒng)和其它系統(tǒng)軟件在CM3器件間的移植變得簡單多了,因為在所有CM3產(chǎn)品間對其處理都是相同的

    3)作為一個鬧鈴測量時間。

    SysTick定時器除了能服務(wù)于操作系統(tǒng)之外,還能用于其它目的:如作為一個鬧鈴,用于測量時間等。要注意的是,當(dāng)處理器在調(diào)試期間被喊停(halt)時,則SysTick定時器亦將暫停運作。

    QSystick如何運行?

    首先設(shè)置計數(shù)器時鐘源,CTRL->CLKSOURCE(控制寄存器)。設(shè)置重載值(RELOAD寄存器),清空計數(shù)寄存器VAL(就是下圖的CURRENT)。置CTRL->ENABLE開始計時。

    如果是中斷則允許Systick中斷,在中斷例程中處理。如采用查詢模式則不斷讀取控制寄存器的COUNTFLAG標志位,判斷是否計時至零。或者采取下列一種方法

    當(dāng)SysTick定時器從1計到0時,它將把COUNTFLAG位置位;而下述方法可以清零之:

    1.?讀取SysTick控制及狀態(tài)寄存器(STCSR

    2.?SysTick當(dāng)前值寄存器(STCVR)中寫任何數(shù)據(jù)

    只有當(dāng)VAL值為0時,計數(shù)器自動重載RELOAD

    Q:如何使用SysTicks作為系統(tǒng)時鐘?

    SysTick?的最大使命,就是定期地產(chǎn)生異常請求,作為系統(tǒng)的時基。OS都需要這種滴答來推動任務(wù)和時間的管理。如欲使能SysTick異常,則把STCSR.TICKINT置位。另外,如果向量表被重定位到SRAM中,還需要為SysTick異常建立向量,提供其服務(wù)例程的入口地址。


    二:就在前一段時間,有人突然問我SysTick_Handler(void)這個定時器中斷處理函數(shù)是怎么定義的?根據(jù)以往的經(jīng)驗,我感覺在底層應(yīng)該會有一個類似于函數(shù)聲明的東西的存在,但是往下跟程序的話,一直都沒有找到相應(yīng)的定義或者聲明,那么究竟SysTick_Handler這個函數(shù)怎么來的呢?是不是可以人為的做修改呢?給我的第一感覺是,肯定是可以做修改的,畢竟只是一個 函數(shù) 的名字而已,于是就翻看LPC1114的數(shù)據(jù)手冊,結(jié)合網(wǎng)上的一些參考文件,去理清楚到底是怎么回事。


    那么還是非常容易找到SysTick_Handler()這個函數(shù)的位置的,如下圖所示:




    ? ? 我們會發(fā)現(xiàn),幾乎所有的中斷函數(shù)的名字都已經(jīng)在這里寫好了,所以我們有的時候在程序中使用的一些中斷,都可以在這個地方進行查找。 ? ? 那么,我們?nèi)绻胍淖円粋€中斷的名字,那么只需要在這里做下修改就可以了,在程序中再使用我們自己定義的中斷的名字,但是結(jié)合實際的情況來考慮問題,如果我們修改了這些中斷函數(shù)的名字的話,那么就會降低我們代碼的可移植性,所以基本上我們在這里不建議大家做修改。

    ? ? ??說到了定時器中斷處理函數(shù),那么定時器Systick是怎樣來進行設(shè)置的呢?



    ?上圖是LPC1114系統(tǒng)滴答定時器SysTick的結(jié)構(gòu)圖。系統(tǒng)滴答定時器位于Cortex-M0內(nèi)核中,也就是說對于LPC1114或者其他的以CortexM0為內(nèi)核的板子中,都會有這個系統(tǒng)的定時器。它存在的主要目的是為嵌入式操作系統(tǒng)提供100HZ(即10ms)的定時功能。 ? ?? ? ? 系統(tǒng)定時器一共有四個寄存器:這個可以從數(shù)據(jù)手冊上面清楚的了解到:


    SYST_CSR ? ?: ?系統(tǒng)定時器控制和狀態(tài)寄存器 SYST_RVR ? ?: ?系統(tǒng)定時器重載值寄存器 SYST_CVR ? ?:系統(tǒng)定時器當(dāng)前值寄存器 SYST_CALIB ?: 系統(tǒng)定時器校準寄存器

    ? ? 在系統(tǒng)定時器的四個寄存器中,SYST_CALIB為校準寄存器,這個是在出廠之前就已經(jīng)配置好了的,我們不必考慮這個寄存器。那么我們一共需要配置3個寄存器就可以完成我們工作的模塊。


    ? 那么接下來我們對我們所要操作的三個寄存器做進一步的剖析 (1)SYST_CSR ? 寄存器

    ? ? CSR寄存器用到的位有4個,bit0用于是否開啟定時器,置1的話就是允許,bit1用于控制是否產(chǎn)生中斷,該位置為1為允許產(chǎn)生中斷,bit2用于設(shè)置定時器的時鐘源,設(shè)為1,定時器的時鐘源為主時鐘,反之設(shè)為0的話定時器的時鐘源為主時鐘的一半。
    (2)SYST_RVR?? 寄存器? ?

    ? ? RVR寄存器用到0~23位,這個值是定時器倒計時的初始值,打開定時器以后,就會從這里設(shè)置的值倒計時到0,倒計時到0以后,又會從此值開始倒計時。
    (3)SYST_CVR? 寄存器???


    ? ? CURRENT ?: ?讀此寄存器返回系統(tǒng)定時器的當(dāng)前值,給這個寄存器賦值,將使定時器歸0,且清CTRL中的COUNTFLAG位。 ? ? CVR寄存器也是用到0~23位,這是一個狀態(tài)寄存器,當(dāng)定時器開始運作的時候,這個值在不斷的變化,從RVR寄存器獲取初值以后,倒計時到0.


    系統(tǒng)定時器函數(shù)——SysTick_Config()函數(shù)


    ?系統(tǒng)自帶的Systick函數(shù),由CMSIS提供,位于core_cm0.h文件中,在使用的時候,可以直接調(diào)用的,函數(shù)有一個參數(shù)ticks,由函數(shù)內(nèi)部的語句 ??SysTick->LOAD ?= (ticks & SysTick_LOAD_RELOAD_Msk) - 1;? 知道ticks就是重載值,表示兩次中斷的計數(shù)。 ? ?? SysTick_Config()函數(shù)中的LOAD就是我們之前說的RSR,VAL就是CVR,CTRL就是之前的CSR,上面的操作就是對寄存器相應(yīng)位進行設(shè)置的過程。 ? ? 函數(shù)中,對控制寄存器的bit0,bit1,bit2都置1,對照前面寄存器相關(guān)位的定義可以知道,時鐘設(shè)置為等于主頻,打開系統(tǒng)定時器中斷,允許定時器運行。

    總結(jié)

    以上是生活随笔為你收集整理的STM32系统滴答定时器(systick)应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。