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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

stm32系统滴答定时器使用

發布時間:2025/3/15 windows 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32系统滴答定时器使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
 STM32菜鳥成長記錄---系統滴答定時器(systick)應用 標簽: delay任務測試reference編譯器工作 47395人閱讀 評論(4) 收藏 舉報 本文章已收錄于: 分類: 嵌入式(53) 作者同類文章X
    ARM(27) 作者同類文章X

      1.systick介紹

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

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

      ??? SysTick->CTRL,??????? --控制和狀態寄存器

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

      ?? ?SysTick->VAL,?????? ???--當前值寄存器

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

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

      2.systick編程

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

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

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

      ?

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

      ??? SystemInit();

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

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

      ??? 1、調用SysTick_CounterCmd()????? ?--失能SysTick計數器

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

      ??? 3、調用SysTick_CLKSourceConfig()? --設置SysTick時鐘源。

      ??? 4、調用SysTick_SetReload()???????? --設置SysTick重裝載值。

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

      ??? 6、調用SysTick_CounterCmd()?????? --開啟SysTick計數器 ?????????????????????????????????????????????????????

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

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

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

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

      1)系統時鐘進配置

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

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

      2)先來看看主函數

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

      3)系統滴答定時器的配置--主角登場:

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

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

      在文件Core_cm3.h

      SysTick_Config函數的具體實現如下:

      [html] view plaincopyprint?
    • 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當前值寄存器????????????????????????????????
    • ??
    • ???/*?Load?the?SysTick?Counter?Value?*/??
    • ???SysTick->CTRL?=?(1?<<?SYSTICK_CLKSOURCE)?|?(1<<SYSTICK_ENABLE)?|?(1<<SYSTICK_TICKINT);//使能IRQ(普通中斷)和系器?????????return(0);??????/*?Function?successful?*/??
    • ??
    • }?????????????????????????????????????????
    • 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當前值寄存器 /* 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(普通中斷)和系統定時器,為什么要使能中斷和系統定時器呢?

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

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

      void SysTickHandler(void)

      {

      ??? TimingDelay_Decrement();

      }

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

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

      [html] view plaincopyprint?
    • /*****************************************************************??
    • ??
    • *函數名稱:TimingDelay_Decrement??
    • ??
    • *功能描述:中斷里調用此函數,即沒發生一次中斷,此函數被調用,此函數里???????
    • ??
    • *??????????的變量TimingDelay?相當于減法計數器??
    • ??
    • *???
    • ??
    • *輸入參數:無??
    • ??
    • *返回值:無??
    • ??
    • *其他說明:無??
    • ??
    • *當前版本:v1.0??
    • ??
    • *作????者:?梁尹宣??
    • ??
    • *完成日期:2012年8月3日??
    • ??
    • *修改日期??????版本號??????修改人??????修改內容??
    • ??
    • *-----------------------------------------------------------------??
    • ??
    • *??
    • ??
    • ******************************************************************/??
    • ??
    • ?????
    • ??
    • void?TimingDelay_Decrement(void)????
    • ??
    • {????
    • ??
    • ????
    • ??
    • ??if?(TimingDelay?!=?0x00)????
    • ??
    • ??{?????
    • ??
    • ????TimingDelay--;????
    • ??
    • ??}??
    • ??
    • }????
    • ??
    • 我們看了TimingDelay的定義,又看了還有哪些函數調用到這個變量,如下:??
    • ??
    • /*****************************************************************??
    • ??
    • *????????????????????????????????????????全局變量??
    • ??
    • ******************************************************************/??
    • ??
    • ???
    • ??
    • static?__IO?uint32_t?TimingDelay=0;??
    • ??
    • ???????????
    • ??
    • /*****************************************************************??
    • ??
    • *函數名稱:????Delay??
    • ??
    • *功能描述:????利用系統時鐘計數器遞減達到延時功能??
    • ??
    • *???
    • ??
    • *輸入參數:nTime?:需要延的時毫秒數??
    • ??
    • *返回值:無??
    • ??
    • *其他說明:無??
    • ??
    • *當前版本:v1.0??
    • ??
    • *作????者:?梁尹宣??
    • ??
    • *完成日期:2012年8月3日??
    • ??
    • *修改日期??????版本號??????修改人??????修改內容??
    • ??
    • *-----------------------------------------------------------------??
    • ??
    • *??
    • ??
    • ******************************************************************/??
    • ??
    • ???
    • ??
    • void?Delay(__IO?uint32_t?nTime)//delay被調用時,nTime=500??
    • ??
    • {???
    • ??
    • ??TimingDelay?=?nTime;??
    • ??
    • ???
    • ??
    • ??while(TimingDelay?!=?0);??
    • ??
    • }??
    • /******************************************************************函數名稱:TimingDelay_Decrement*功能描述:中斷里調用此函數,即沒發生一次中斷,此函數被調用,此函數里 * 的變量TimingDelay 相當于減法計數器* *輸入參數:無*返回值:無*其他說明:無*當前版本:v1.0*作 者: 梁尹宣*完成日期:2012年8月3日*修改日期 版本號 修改人 修改內容*-----------------------------------------------------------------*******************************************************************/void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; }} 我們看了TimingDelay的定義,又看了還有哪些函數調用到這個變量,如下:/****************************************************************** 全局變量******************************************************************/static __IO uint32_t TimingDelay=0;/******************************************************************函數名稱: Delay*功能描述: 利用系統時鐘計數器遞減達到延時功能* *輸入參數:nTime :需要延的時毫秒數*返回值:無*其他說明:無*當前版本:v1.0*作 者: 梁尹宣*完成日期:2012年8月3日*修改日期 版本號 修改人 修改內容*-----------------------------------------------------------------*******************************************************************/void Delay(__IO uint32_t nTime)//delay被調用時,nTime=500{ TimingDelay = nTime;while(TimingDelay != 0);}

      通過上面幾個函數我們知道了,在調用Delay(500)nTime=500;在后在Delay()函數中TimingDelay =nTime;(即TimingDelay=500是它的初始值),再TimingDelay_Decrement(void)函數的作用就是把TimingDelay- -;每毫秒進行遞減直到減到0為止;這樣就起到一個延時的作用;

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

      ? 我們來畫個圖,方便這幾個函數間關系的理解:

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

      [html] view plaincopyprint?
    • while?(1)??
    • ??
    • ????????{??
    • ??
    • ?????????????//測試代碼:測試定時器功能,通過延時來測試??
    • ??
    • ?????????????GPIO_SetBits(GPIOC,?GPIO_Pin_6);??????//V6???
    • ??
    • ?????????????Delay(500);??
    • ??
    • ?????????????GPIO_ResetBits(GPIOC,?GPIO_Pin_6);?????????//V6???
    • ??
    • ?????????????Delay(500);??
    • ??
    • ????????????????????????
    • ??
    • ????????????//功能1代碼:每500ms發送數據??
    • ??
    • ???????????????/*??
    • ??
    • ??????????????????????UART2_TX485_Puts("123450");??
    • ??
    • ??????????????????????Delay(500);??
    • ??
    • ???????????*/??
    • ??
    • ????????????//功能2代碼:上位發特定指令,中位機執行相應操作??
    • ??
    • ??????????????//?????RS485_Test();??
    • ??
    • ??????????????}???????
    • while (1){//測試代碼:測試定時器功能,通過延時來測試GPIO_SetBits(GPIOC, GPIO_Pin_6); //V6 Delay(500);GPIO_ResetBits(GPIOC, GPIO_Pin_6); //V6 Delay(500);//功能1代碼:每500ms發送數據/*UART2_TX485_Puts("123450");Delay(500);*///功能2代碼:上位發特定指令,中位機執行相應操作// RS485_Test();}

      經過上面系統定時器的分析我們知道Delay(500);是延時500ms ;那么LED就是每隔500ms閃爍一次;

      上面有關系統滴答定時器的應用講解基本完畢!

      ?有關SysTick編譯后的源代碼包,(其實客官細心的話一經發現上面代碼含有485通訊代碼,

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

      ?

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

      Cortex-M3權威指南》

      Cortex-M3 Technical Reference Manual

      Q:什么是SYSTick定時器?

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

      Q:為什么要設置SysTick定時器?

      1)產生操作系統的時鐘節拍

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

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

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

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

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

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

      QSystick如何運行?

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

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

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

      1. 讀取SysTick控制及狀態寄存器(STCSR

      2. SysTick當前值寄存器(STCVR)中寫任何數據

      只有當VAL值為0時,計數器自動重載RELOAD

      Q:如何使用SysTicks作為系統時鐘?

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

      總結

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

      如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。