RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ARM Cortex-M學(xué)習(xí)筆記:初識(shí)Systick定時(shí)器

CHANBAEK ? 來源:嵌入式實(shí)驗(yàn)樓 ? 作者:BruceOu ? 2023-05-15 15:01 ? 次閱讀

開發(fā)環(huán)境:

MDK:凱爾 5.30

STM32立方體MX:V6.4.0

單片機(jī):STM32F103ZET6

Cortex-M的內(nèi)核中包含Systick定時(shí)器了,只要是Cortex-M系列的MCU就會(huì)有Systick,因此這是通用的,下面詳細(xì)分析。

4.1 Systick工作原理分析

SysTick 定時(shí)器被捆綁在 NVIC 中,用于產(chǎn)生 SysTick 異常(異常號(hào):15)。 在以前,操作系統(tǒng)和所有使用了時(shí)基的系統(tǒng)都必須有一個(gè)硬件定時(shí)器來產(chǎn)生需要的“滴答”中斷,作為整個(gè)系統(tǒng)的時(shí)基。 滴答中斷對(duì)操作系統(tǒng)尤其重要。 例如,操作系統(tǒng)可以為多個(gè)任務(wù)分配不同數(shù)目的時(shí)間片,確保沒有一個(gè)任務(wù)能霸占系統(tǒng); 或者將每個(gè)定時(shí)器周期的某個(gè)時(shí)間范圍賜予特定的任務(wù)等,操作系統(tǒng)提供的各種定時(shí)功能都與這個(gè)滴答定時(shí)器有關(guān)。 因此,**需要一個(gè)定時(shí)器來產(chǎn)生周期性的中斷,而且最好還讓用戶程序不能隨意訪問它的寄存器,以維持操作系統(tǒng)“心跳”的節(jié)律。 **

Cortex-M3 在內(nèi)核部分包含了一個(gè)簡(jiǎn)單的定時(shí)器——SysTick。 因?yàn)樗械?CM3 芯片都帶有這個(gè)定時(shí)器,軟件在不同芯片生產(chǎn)廠商的 CM3 器件間的移植工作就得以簡(jiǎn)化。 該定時(shí)器的時(shí)鐘源可以是內(nèi)部時(shí)鐘(FCLK,CM3 上的自由運(yùn)行時(shí)鐘),或者是外部時(shí)鐘( CM3 處理器上的 STCLK 信號(hào))。 不過,STCLK 的具體來源則由芯片設(shè)計(jì)者決定,因此不同產(chǎn)品之間的時(shí)鐘頻率可能大不相同。 因此,需要閱讀芯片的使用手冊(cè)來確定選擇什么作為時(shí)鐘源。 在 STM32 中 SysTick 以 HCLK(AHB 時(shí)鐘)或 HCLK/8 作為運(yùn)行時(shí)鐘,見上圖。

SysTick 定時(shí)器能產(chǎn)生中斷,CM3 為它專門開出一個(gè)異常類型,并且在向量表中有它的一席之地。 它使操作系統(tǒng)和其他系統(tǒng)軟件在 CM3 器件間的移植變得簡(jiǎn)單多了,因?yàn)樵谒?CM3 產(chǎn)品間,SysTick 的處理方式都是相同的。 SysTick 定時(shí)器除了能服務(wù)于操作系統(tǒng)之外,還能用于其他目的,如作為一個(gè)鬧鈴、用于測(cè)量時(shí)間等。 **Systick 定時(shí)器屬于Cortex ** 內(nèi)核部件 ,可以參考《ARM Cortex-M3 權(quán)威指南》((英)JosephYiu 著,宋巖譯,北京航空航天大學(xué)出版社出版)或“STM32xxx-Cortex-M3programmingmanual” (這是 ST 官方提供的電子編程手冊(cè),可以在 ST 官網(wǎng)下載)來了解。

4.2 Systick寄存器分析

在傳統(tǒng)的嵌入式系統(tǒng)軟件按中通常實(shí)現(xiàn) Delay(N) 函數(shù)的方法為:

for(i = 0; i <= x; i ++);
x --- ;

對(duì)于STM32系列微處理器來說,執(zhí)行一條指令只有幾十個(gè) ns,進(jìn)行 for 循環(huán)時(shí),要實(shí)現(xiàn) N 毫秒的 x 值非常大,而且由于系統(tǒng)頻率的寬廣,很難計(jì)算出延時(shí) N 毫秒的精確值。 針對(duì) STM32 微處理器,需要重新設(shè)計(jì)一個(gè)新的方法去實(shí)現(xiàn)該功能,以實(shí)現(xiàn)在程序中使用 Delay(N)。

Cortex-M3 的內(nèi)核中包含一個(gè) SysTick 時(shí)鐘。 SysTick 為一個(gè) 24 位遞減計(jì)數(shù)器,SysTick 設(shè)定初值并使能后,每經(jīng)過 1 個(gè)系統(tǒng)時(shí)鐘周期,計(jì)數(shù)值就減 1。 計(jì)數(shù)到 0 時(shí),SysTick 計(jì)數(shù)器自動(dòng)重裝初值并繼續(xù)計(jì)數(shù),同時(shí)內(nèi)部的 COUNTFLAG 標(biāo)志會(huì)置位,觸發(fā)中斷 (如果中斷使能情況下)。

在 STM32 的應(yīng)用中,使用 Cortex-M3 內(nèi)核的 SysTick 作為定時(shí)時(shí)鐘,設(shè)定每一毫秒產(chǎn)生一次中斷,在中斷處理函數(shù)里對(duì) N 減一,在Delay(N) 函數(shù)中循環(huán)檢測(cè) N 是否為 0,不為 0 則進(jìn)行循環(huán)等待; 若為 0 則關(guān)閉 SysTick 時(shí)鐘,退出函數(shù)。

注:全局變量 TimingDelay , 必須定義為 volatile 類型 , 延遲時(shí)間將不隨系統(tǒng)時(shí)鐘頻率改變。

STM32中的Systick 部分內(nèi)容屬于NVIC控制部分,一共有4個(gè)寄存器,名稱和地址分別是:

  • STK_CTRL, 0xE000E010 -- 控制寄存器

第0位:ENABLE,Systick 使能位

(0:關(guān)閉Systick功能; 1:開啟Systick功能)

第1位:TICKINT,Systick 中斷使能位

(0:關(guān)閉Systick中斷; 1:開啟Systick中斷)

第2位:CLKSOURCE,Systick時(shí)鐘源選擇

(0:使用HCLK/8 作為Systick時(shí)鐘; 1:使用HCLK作為Systick時(shí)鐘)

第16位:COUNTFLAG,Systick計(jì)數(shù)比較標(biāo)志,如果在上次讀取本寄存器后,SysTick 已經(jīng)數(shù)到了0,則該位為1。 如果讀取該位,該位將自動(dòng)清零

  • STK_LOAD, 0xE000E014 -- 重載寄存器

Systick是一個(gè)遞減的定時(shí)器,當(dāng)定時(shí)器遞減至0時(shí),重載寄存器中的值就會(huì)被重裝載,繼續(xù)開始遞減。 STK_LOAD 重載寄存器是個(gè)24位的寄存器最大計(jì)數(shù)0xFFFFFF。

  • STK_VAL, 0xE000E018 -- 當(dāng)前值寄存器

也是個(gè)24位的寄存器,讀取時(shí)返回當(dāng)前倒計(jì)數(shù)的值,寫它則使之清零,同時(shí)還會(huì)清除在SysTick 控制及狀態(tài)寄存器中的COUNTFLAG 標(biāo)志。

  • STK_CALRB, 0xE000E01C -- 校準(zhǔn)值寄存器

校準(zhǔn)值寄存器提供了這樣一個(gè)解決方案:它使系統(tǒng)即使在不同的CM3產(chǎn)品上運(yùn)行,也能產(chǎn)生恒定的SysTick中斷頻率。 最簡(jiǎn)單的作法就是:直接把TENMS的值寫入重裝載寄存器,這樣一來,只要沒突破系統(tǒng)極限,就能做到每10ms來一次 SysTick異常。 如果需要其它的SysTick異常周期,則可以根據(jù)TENMS的值加以比例計(jì)算。 只不過,在少數(shù)情況下, CM3芯片可能無法準(zhǔn)確地提供TENMS的值(如, CM3的校準(zhǔn)輸入信號(hào)被拉低),所以為保險(xiǎn)起見,最好在使用TENMS前檢查器件的參考手冊(cè)。

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

4.3 Systick定時(shí)器實(shí)現(xiàn)-標(biāo)準(zhǔn)庫

4.3.1main文件分析

主函數(shù)如下:

int main(void)
{      
       /* LED 端口初始化 */
       LED_GPIO_Config();

       /* 配置SysTick 為10us中斷一次 */
       SysTick_Init();

       for(;;)
       {

           LED1( ON ); 
           Delay_us(10000);        //10000 * 10us = 100ms
           //Delay_ms(100);
           LED1( OFF );

           LED2( ON );
           Delay_us(10000);             // 10000 * 10us = 100ms
           //Delay_ms(100);
           LED2( OFF );

           LED3( ON );
           Delay_us(10000);             // 10000 * 10us = 100ms
           //Delay_ms(100);
           LED3( OFF ); 
       }     
}

在 main 函數(shù)中,SysTick_Init() 和 Delay_us() 這兩個(gè)函數(shù)比較陌生,它們的功能分別是配置好 SysTick 定時(shí)器和進(jìn)行精確延時(shí)。 整個(gè) main 函數(shù)的流程就是初始化 LED 及SysTick 定時(shí)器之后,就進(jìn)入死循環(huán),輪流點(diǎn)亮 LED1、LED2、LED3,點(diǎn)亮的時(shí)間為精確的 100 ms。

4.3.2 stm32f103_SysTick.c文件分析

  • 配置并啟動(dòng)SysTick

我們看一下 SysTick_Init() 這個(gè)函數(shù),其功能是啟動(dòng)系統(tǒng)滴答定時(shí)器 SysTick ,并將 SysTick 配置為 10μs中斷一次。

void SysTick_Init(void)
{
       /*SystemFrequency / 100000 10us中斷一次
        * SystemFrequency / 1000000 1us中斷一次*/
//    if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0庫版本
       if(SysTick_Config(SystemCoreClock / 100000))     // ST3.5.0庫版本
       {
              /*Capture error */ 
              while(1);
       }
       //關(guān)閉滴答定時(shí)器  
       SysTick->CTRL&= ~ SysTick_CTRL_ENABLE_Msk;
}

本函數(shù)實(shí)際上只是調(diào)用了 SysTick_Config()函數(shù),它是屬于內(nèi)核層的 Cortex-M3 通用函數(shù),位于 core_cm3.h 文件中。 若調(diào)用 SysTick_Config()配置 SysTick 不成功,則進(jìn)入死循環(huán),初始化 SysTick 成功后,先關(guān)閉定時(shí)器,在需要的時(shí)候再開啟。 SysTick_Config() 函數(shù)無法在STM32 外設(shè)固件庫文件中找到其使用方法。 所以我們?cè)?Keil 環(huán)境下直接跟蹤這個(gè)函數(shù)到 core_cm3.h 文件,查看函數(shù)的定義。

static __INLINE uint32_tSysTick_Config(uint32_t ticks)
{ 
 if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);            
/* Reload value impossible */                                                         
 SysTick->LOAD  = (ticks &SysTick_LOAD_RELOAD_Msk) - 1;      /* setreload register */
 NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  
/* set Priority for Cortex-M0 System Interrupts */
 SysTick->VAL   = 0;                                          
/* Load the SysTick Counter Value */
 SysTick->CTRL  =SysTick_CTRL_CLKSOURCE_Msk | 
                  SysTick_CTRL_TICKINT_Msk   | 
                  SysTick_CTRL_ENABLE_Msk;                   
 /* Enable SysTickIRQ and SysTick Timer */
 return (0);           /* Functionsuccessful */
}

在這個(gè)函數(shù)定義的前面有關(guān)于它的注釋,如果我們不想去研究它的具體實(shí)現(xiàn),可以根據(jù)這段注釋了解函數(shù)的功能:這個(gè)函數(shù)啟動(dòng)了 SysTick ; 并把它配置為計(jì)數(shù)至 0 時(shí)引起中斷; 輸入的參數(shù) ticks 為兩個(gè)中斷之間的脈沖數(shù),即相隔 ticks 個(gè)時(shí)鐘周期會(huì)引起一次中斷; 配置 SysTick 成功時(shí)返回 0,出錯(cuò)時(shí)返回 1。 但是,這段注釋并沒有告訴我們它把 SysTick 的時(shí)鐘設(shè)置為 AHB 時(shí)鐘還是 AHB/8,這是一個(gè)十分關(guān)鍵的問題,于是,我們將對(duì)這個(gè)函數(shù)的具體實(shí)現(xiàn)進(jìn)行分析,與大家再分享一下如何分析底層庫函數(shù)。 分析底層庫函數(shù),要有 SysTick 定時(shí)器工作分析的知識(shí)準(zhǔn)備。

  • 檢查輸入?yún)?shù)

SysTick_Config() 第 3 行代碼是檢查輸入?yún)?shù) ticks,因?yàn)?ticks 是脈沖計(jì)數(shù)值,要被保存到重載寄存器 STK_LOAD 寄存器中,再由硬件把 STK_LOAD 值加載到當(dāng)前計(jì)數(shù)值寄存器 STK_VAL 中使用,STK_LOAD 和 STK_VAL 都是 24 位的,所以當(dāng)輸入?yún)?shù) ticks 大于其可存儲(chǔ)的最大值時(shí), 將由這行代碼檢查出錯(cuò)誤并返回。

  • 位指示宏及位屏蔽宏

檢查 ticks 參數(shù)沒有錯(cuò)誤后,就稍稍處理一下把 ticks-1 賦值給 STK_LOAD 寄存器,要注意的是減 1,若 STK_VAL 從 ticks?1 向下計(jì)數(shù)至 0,實(shí)際上就經(jīng)過了 ticks 個(gè)脈沖。 這句賦值代碼使用了宏SysTick_LOAD_RELOAD_Msk,與其他庫函數(shù)類似,這個(gè)宏是用來指示寄存器的特定位置或進(jìn)行位屏蔽的。

/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos         16                                            /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk         (1ul <

#define SysTick_CTRL_CLKSOURCE_Pos          2                                            /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk         (1ul <

#define SysTick_CTRL_TICKINT_Pos            1                                            /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk           (1ul <

#define SysTick_CTRL_ENABLE_Pos             0                                            /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk            (1ul <

/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos             0                                            /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */

/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos             0                                            /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFul <

/* SysTick Calibration Register Definitions */
#define SysTick_CALIB_NOREF_Pos            31                                            /*!< SysTick CALIB: NOREF Position */
#define SysTick_CALIB_NOREF_Msk            (1ul <

#define SysTick_CALIB_SKEW_Pos             30                                            /*!< SysTick CALIB: SKEW Position */
#define SysTick_CALIB_SKEW_Msk             (1ul <

#define SysTick_CALIB_TENMS_Pos             0                                            /*!< SysTick CALIB: TENMS Position */
#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFul <
/*@}*/ /* end of group CMSIS_CM3_SysTick */

其中寄存器位指示宏:SysTick_xxx_Pos ,宏展開后即為 xxx 在相應(yīng)寄存器中的位置,如控制 SysTick 時(shí)鐘源的 SysTick_CTRL_CLKSOURCE_Pos,宏展開為 2,這個(gè)寄存器位正是寄存器 STK_CTRL 中的 Bit2。

而寄存器位屏蔽宏:SysTick_xxx_Msk,宏展開是 xxx 的位全部置 1 后,左移SysTick_xxx_Pos 位。 如控制 SysTick 時(shí)鐘源的SysTick_CTRL_CLKSOURCE_Msk,宏展開為“1ul <

配置中斷向量及重置 STK_VAL 寄存器回到 SysTick_Config()函數(shù),接下來調(diào)用了 NVIC_SetPriority () 函數(shù)并配置了 SysTick中斷,這就是為什么我們?cè)谕獠繘]有再使用 NVIC 配置 SysTick 中斷的原因。 配置好SysTick 中斷后把 STK_VAL 寄存器重新賦值為 0(在使能 SysTick 時(shí),硬件會(huì)把存儲(chǔ)在STK_LOAD 寄存器中的 ticks 值加載給它)。配置 SysTick 時(shí)鐘為 AHB在這段代碼最后,向 STK_CTRL 寄存器寫入了 SysTick 的控制參數(shù),配置為使用AHB 時(shí)鐘,使能計(jì)數(shù)至 0 時(shí)引起中斷,使能 SysTick。 執(zhí)行了這行代碼,SysTick 就開始運(yùn)行并進(jìn)行脈沖計(jì)數(shù)了。若讀者想要使用 AHB/8 作為時(shí)鐘,可以調(diào)用庫函數(shù)SysTick_CLKSourceConfig() 進(jìn)行修改,也可以直接對(duì) SysTick_Config() 函數(shù)的代碼進(jìn)行修改。使能、關(guān)閉定時(shí)器由于調(diào)用 SysTick_Config()函數(shù)之后,SysTick 定時(shí)器就被開啟了,但我們?cè)诔跏蓟臅r(shí)候并不希望這樣,而是根據(jù)需要再開啟。 所以在 SysTick_Init() 函數(shù)中,調(diào)用完SysTick_Confi g()并配置好后,應(yīng)先把定時(shí)器關(guān)閉了。 SysTick 的開啟和關(guān)閉由寄存器STK_CTRL 的 Bit0 :ENABLE 位來控制,使用位屏蔽宏以操作寄存器的方式實(shí)現(xiàn)。SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk; // 使能滴答定時(shí)器SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 關(guān)閉滴答定時(shí)器定時(shí)時(shí)間的計(jì)算在調(diào)用SysTick_Config()函數(shù)時(shí),向它輸入的參數(shù)為SystemCoreClock /100000,SystemCoreClock為定義了系統(tǒng)時(shí)鐘(SYSCLK)頻率的宏,即等于 AHB的時(shí)鐘頻率。 在本書的所有例程中AHB 都是被配置為 72 MHz 的,也就是這個(gè) SystemCoreClock 宏展開為數(shù)值 7200 0000。根據(jù)前面對(duì) SysTick_Config()函數(shù)的介紹,它的輸入?yún)?shù)為 SysTick 將要計(jì)時(shí)的脈沖數(shù),經(jīng)過 ticks 個(gè)脈沖(經(jīng)過 ticks 個(gè)時(shí)鐘周期)后將觸發(fā)中斷,觸發(fā)中斷后又重新開始計(jì)數(shù)。 由此我們可以算出定時(shí)的時(shí)間,下面為計(jì)算公式:T=即時(shí)報(bào)價(jià)×(1/f)其中,T 為要定時(shí)的總時(shí)間; ticks 為 SysTick_Config() 的輸入?yún)?shù); 1/ f 即為SysTick 使用的時(shí)鐘源的時(shí)鐘周期,f 為該時(shí)鐘源的時(shí)鐘頻率,當(dāng)時(shí)鐘源確定后為常數(shù)。例如:本實(shí)驗(yàn)例子中,使用時(shí)鐘源為 AHB 時(shí)鐘,其頻率被配置為 72 MHz。 調(diào)用函數(shù)時(shí),把 ticks 賦值為 ticks=SystemFrequency/ 100000 =720,表示 720 個(gè)時(shí)鐘周期中斷一次; 1/f 是時(shí)鐘周期的時(shí)間,此時(shí)(1/f =1/72 μs),所以最終定時(shí)總時(shí)間 T=720×(1/72),為720 個(gè)時(shí)鐘周期,正好是 10 μs。SysTick 定時(shí)器的定時(shí)時(shí)間(配置為觸發(fā)中斷,即為中斷周期)由 ticks 參數(shù)決定,最大定時(shí)周期不能超過 2^24^ 個(gè)。編寫中斷服務(wù)函數(shù)一旦我們調(diào)用了 Delay_us() 函數(shù),SysTick 定時(shí)器就被開啟,按照設(shè)定好的定時(shí)周期遞減計(jì)數(shù),當(dāng) SysTick 的計(jì)數(shù)寄存器的值減為 0 時(shí),就進(jìn)入中斷函數(shù),當(dāng)中斷函數(shù)執(zhí)行完畢之后重新計(jì)時(shí),如此循環(huán),除非它被關(guān)閉。void Delay_us(__IO u32 nTime){ TimingDelay = nTime; // 使能滴答定時(shí)器 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; while(TimingDelay != 0);}使能了 SysTick 之后,就使用 while(TimingDelay != 0)語句等待 TimingDelay 變量變?yōu)?0,這個(gè)變量是在中斷服務(wù)函數(shù)中被修改的。 因此,我們需要編寫相應(yīng)的中斷服務(wù)程序,在本實(shí)驗(yàn)室中我們配置為 10μs 中斷一次,每次中斷把 TimingDelay 減 1。 中斷程序在 stm32f10x_it.c 中實(shí)現(xiàn)。void SysTick_Handler(void){ TimingDelay_Decrement(); }SysTick中斷屬于系統(tǒng)異常向量,在stm32f10x_it.c文件中已經(jīng)默認(rèn)有了它的中斷服務(wù)函數(shù)SysTick_Handler(),但內(nèi)容為空。 我們找到這個(gè)函數(shù),其調(diào)用了用戶函數(shù)TimingDelay_Decrement()。 后者是由用戶編寫的一個(gè)應(yīng)用程序。void TimingDelay_Decrement(void){ if (TimingDelay != 0x00) { TimingDelay--; }}每次進(jìn)入 SysTick 中斷就調(diào)用一次TimingDelay_Decrement()函數(shù),使全局變量TimingDelay 自減一次。 用戶函數(shù) Delay_us ()在TimingDelay 被減至0時(shí),才退出延時(shí)循環(huán),即我們對(duì) TimingDelay 賦的值為要中斷的次數(shù)。 所以總的延時(shí)時(shí)間:T 延時(shí) = T 中斷周期 x TimingDelay至此,SysTick 的精確延時(shí)功能講解完畢。4.4 Systick定時(shí)器實(shí)現(xiàn)-HAL庫4.4.1 STM32Cube配置工程關(guān)于如何使用STM32Cube新建工程在前文已經(jīng)講解過了,這里直說配置GPIO部分內(nèi)容。 本文要實(shí)現(xiàn)流水燈,其實(shí)輸出為初始化設(shè)置為高電平還是低電平都可以,因?yàn)榱魉疅粜枰粩喾崔D(zhuǎn)。 在上一節(jié)筆者已經(jīng)講過了。1.GPIO配置我們將PB0、PG6、PG7配置輸出模式(高電平、低電平均可)、輸出速率、上/下拉等,默認(rèn)即可。2.時(shí)鐘源配置3.時(shí)鐘配置4.sys配置(滴答定時(shí)器配置)以上配置和GPIO流水燈是一樣的,本文只具體講解Systick的內(nèi)容。4.4.2 Systick定時(shí)器具體代碼分析Systick屬于內(nèi)核部分,相關(guān)的寄存器定義與庫函數(shù)都在內(nèi)核相關(guān)的文件core_cm3.h中,在上標(biāo)準(zhǔn)庫函數(shù)版本中已經(jīng)分析過了。 那么HAL庫函數(shù)是如何初始化Systick的呢? 在HAL_Init()函數(shù)中調(diào)用了HAL_InitTick()函數(shù),這才是Systick初始化入口。__weak HAL_StatusTypeDefHAL_InitTick(uint32_t TickPriority){ /* Configure the SysTick to have interrupt in 1ms time basis*/ if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U) { return HAL_ERROR; } /* Configure the SysTick IRQ priority */ if (TickPriority < (1UL << __NVIC_PRIO_BITS)) { HAL_NVIC_SetPriority(SysTick_IRQn,TickPriority, 0U); uwTickPrio = TickPriority; } else { return HAL_ERROR; } /* Return function status */ return HAL_OK;}HAL_SYSTICK_Config()函數(shù)和標(biāo)準(zhǔn)庫函數(shù)差不多,默認(rèn)中斷周期是1ms,HAL_TICK_FREQ_DEFAULT是一個(gè)宏定義表示計(jì)數(shù)的頻率,默認(rèn)是1,也就是1KHz,也就是1/1000,那么中斷一次的時(shí)間為72000000/1000/1*(1/72000000)=1ms。 那么我們要延時(shí)1s怎么做呢。 我們?cè)谏弦还?jié)流水燈使用了HAL_Delay()函數(shù),函數(shù)原型如下。__weak void HAL_Delay(uint32_tDelay){ uint32_t tickstart = HAL_GetTick(); uint32_t wait = Delay; /* Add a freq to guarantee minimum wait */ if (wait < HAL_MAX_DELAY) { wait += (uint32_t)(uwTickFreq); } while ((HAL_GetTick() - tickstart) < wait) { }}在函數(shù)中HAL_Delay(),(HAL_GetTick() -tickstart) < wait用于延時(shí)的中斷周期數(shù),在Systick初始化函數(shù)中,中斷間隔為1ms,HAL_Delay ()函數(shù)的傳入?yún)?shù)Delay表示多少個(gè)中斷周期,也就是我們最終的延時(shí),我們傳入Delay = 500,那么最終的延時(shí)就是500ms。我們?cè)賮砜纯碒AL_GetTick()函數(shù)。__weak uint32_tHAL_GetTick(void){ return uwTick;}HAL_GetTick()函數(shù)很簡(jiǎn)單,不斷獲取uwTick得值,這是一個(gè)全局變量,可以發(fā)現(xiàn)在HAL_IncTick()函數(shù)中使用過。 那么HAL_IncTick()函數(shù)被那個(gè)函數(shù)調(diào)用了呢?__weak void HAL_IncTick(void){ uwTick += uwTickFreq;}不難發(fā)現(xiàn),在stm32f1xx_it.c中間中的SysTick_Handler()函數(shù)中調(diào)用了HAL_IncTick()函數(shù),SysTick_Handler()也就是滴答定時(shí)器的中斷服務(wù)函數(shù),也就是中斷一次會(huì)調(diào)用一次,也就會(huì)uwTick變量累加一次,最終uwTick累加到Delay次,表示此次延時(shí)結(jié)束。void SysTick_Handler(void){ /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); /* USER CODE BEGIN SysTick_IRQn 1 */ /* USER CODE END SysTick_IRQn 1 */}好了,使用STM32Cube配置SysTick定時(shí)器的延時(shí)就講解完成了,在主函數(shù)是使用延時(shí)函數(shù)控制LED就是流水燈了。int main(void){ /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCUConfiguration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and theSystick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0); HAL_Delay(500); HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0); HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6); HAL_Delay(500); HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_6); HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_7); HAL_Delay(500); HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_7); } /* USER CODE END 3 */}4.5實(shí)驗(yàn)現(xiàn)象將編譯好的程序下載到板子中,可以看到三個(gè)LED燈不同地閃爍。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    17123

    瀏覽量

    350979
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9084

    瀏覽量

    367380
  • 定時(shí)器
    +關(guān)注

    關(guān)注

    23

    文章

    3246

    瀏覽量

    114716
  • Cortex-M
    +關(guān)注

    關(guān)注

    2

    文章

    229

    瀏覽量

    29752
  • Systick
    +關(guān)注

    關(guān)注

    0

    文章

    62

    瀏覽量

    13071
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    CKS32F4xx系列MCU SysTick定時(shí)器的原理及使用方法

    、中斷延時(shí)以及測(cè)量函數(shù)運(yùn)行時(shí)間;在實(shí)時(shí)操作系統(tǒng)RTOS中作為滴答定時(shí)器,用于上下文切換。采用Cortex-M內(nèi)核的微處理都有SysTick定時(shí)器,方便不同處理
    的頭像 發(fā)表于 12-18 09:21 ?1331次閱讀
    CKS32F4xx系列MCU <b class='flag-5'>SysTick</b><b class='flag-5'>定時(shí)器</b>的原理及使用方法

    ARM Cortex-M0視頻教程 By SmartMcu】【系統(tǒng)定時(shí)器SysTick

    本帖最后由 rejoice818 于 2015-5-19 13:58 編輯 ARM Cortex-M0視頻教程- 系統(tǒng)定時(shí)器SysTick【SmartMcu】視頻地址:http:
    發(fā)表于 05-19 13:50

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

    SYSTick 簡(jiǎn)介系統(tǒng)定時(shí)器,24bit,只能遞減,存在于內(nèi)核,嵌套在NVIC中,所有的Cortex-M內(nèi)核的單片機(jī)都具有這個(gè)定時(shí)器。一般我們?cè)O(shè)置系統(tǒng)時(shí)鐘 SYSCLK 等于 72
    發(fā)表于 08-18 06:13

    SysTick定時(shí)器的相關(guān)資料推薦

    11.1關(guān)于 SysTick 定時(shí)器SysTick定時(shí)器(又名系統(tǒng)滴答定時(shí)器)是存在于Cortex-M
    發(fā)表于 02-09 06:50

    系統(tǒng)定時(shí)器Systick學(xué)習(xí)筆記

    單獨(dú)拿出來講的一個(gè)內(nèi)核外設(shè)(所以不要期望在STM32中文參考手冊(cè)找到它!即使找到也只會(huì)叫你看cm3內(nèi)核編程手冊(cè)),說明它真的很重要。STM32學(xué)習(xí)筆記(5)——系統(tǒng)定時(shí)器SysTick
    發(fā)表于 02-18 07:26

    基于Arm Cortex-MSysTick系統(tǒng)定時(shí)器具體使用說明

    基于Arm Cortex-M系列內(nèi)核的MCU,都包含了SysTick定時(shí)器。所謂SysTick即為系統(tǒng)
    發(fā)表于 11-25 11:21

    Cortex-M4和Cortex-M3內(nèi)核的systick不進(jìn)中斷的軟件延時(shí)

    資源。其中Cortex-M3默認(rèn)選擇HCLK的8分頻作為SysTick系統(tǒng)定時(shí)器的時(shí)鐘源Cortex-M
    發(fā)表于 12-01 11:51 ?3次下載
    <b class='flag-5'>Cortex-M</b>4和<b class='flag-5'>Cortex-M</b>3內(nèi)核的<b class='flag-5'>systick</b>不進(jìn)中斷的軟件延時(shí)

    STM32入門(十五)----SysTick系統(tǒng)定時(shí)器

    Cortex-M內(nèi)核的單片機(jī)都具有這個(gè)定時(shí)器?!禨TM32參考手冊(cè)》里的一句話:關(guān)于Cortex-M3核心、 SysTick定時(shí)器和NVI
    發(fā)表于 12-01 15:06 ?8次下載
    STM32入門(十五)----<b class='flag-5'>SysTick</b>系統(tǒng)<b class='flag-5'>定時(shí)器</b>

    SysTick 定時(shí)器

    11.1關(guān)于 SysTick 定時(shí)器SysTick定時(shí)器(又名系統(tǒng)滴答定時(shí)器)是存在于Cortex-M
    發(fā)表于 12-05 14:51 ?9次下載
    <b class='flag-5'>SysTick</b> <b class='flag-5'>定時(shí)器</b>

    STM32_SysTick—系統(tǒng)定時(shí)器

    SysTick 的簡(jiǎn)介和寄存的詳細(xì)描述。因?yàn)?SysTick 是屬于CM3 內(nèi)核的外設(shè),有關(guān)寄存的定義和部分庫函數(shù)都在 core_CM3.h 這個(gè)頭文件中實(shí)現(xiàn)。所以
    發(fā)表于 12-23 19:56 ?2次下載
    STM32_<b class='flag-5'>SysTick</b>—系統(tǒng)<b class='flag-5'>定時(shí)器</b>

    STM32學(xué)習(xí)筆記(5)——系統(tǒng)定時(shí)器SysTick

    單獨(dú)拿出來講的一個(gè)內(nèi)核外設(shè)(所以不要期望在STM32中文參考手冊(cè)找到它!即使找到也只會(huì)叫你看cm3內(nèi)核編程手冊(cè)),說明它真的很重要。STM32學(xué)習(xí)筆記(5)——系統(tǒng)定時(shí)器SysTick
    發(fā)表于 12-23 19:56 ?4次下載
    STM32<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>(5)——系統(tǒng)<b class='flag-5'>定時(shí)器</b><b class='flag-5'>SysTick</b>

    STM32筆記(七)---Systick系統(tǒng)定時(shí)器

    SysTick系統(tǒng)定時(shí)器文章目錄SysTick系統(tǒng)定時(shí)器一、 概念1-1 Systick簡(jiǎn)介1-2 Sy
    發(fā)表于 12-23 20:01 ?1次下載
    STM32<b class='flag-5'>筆記</b>(七)---<b class='flag-5'>Systick</b>系統(tǒng)<b class='flag-5'>定時(shí)器</b>

    systick定時(shí)器 延時(shí)計(jì)時(shí)

    systick定時(shí)器是屬于cortex M內(nèi)核的外設(shè),專門為RTOS的系統(tǒng)時(shí)鐘節(jié)拍設(shè)計(jì)的。systick
    發(fā)表于 01-18 10:28 ?7次下載
    <b class='flag-5'>systick</b><b class='flag-5'>定時(shí)器</b> 延時(shí)計(jì)時(shí)

    使用系統(tǒng)定時(shí)器SysTick實(shí)現(xiàn)精確延時(shí)微秒和毫秒函數(shù)

    SysTick定時(shí)器是存在于系統(tǒng)內(nèi)核的一個(gè)滴答定時(shí)器,只要是ARM Cortex-M0/M3/
    發(fā)表于 01-26 18:09 ?3次下載
    使用系統(tǒng)<b class='flag-5'>定時(shí)器</b><b class='flag-5'>SysTick</b>實(shí)現(xiàn)精確延時(shí)微秒和毫秒函數(shù)

    敏矽微電子Cortex-M0學(xué)習(xí)筆記08——基本定時(shí)器詳解

    敏矽微電子Cortex-M0學(xué)習(xí)筆記08——基本定時(shí)器詳解
    的頭像 發(fā)表于 09-26 17:13 ?869次閱讀
    敏矽微電子<b class='flag-5'>Cortex-M</b>0<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>08——基本<b class='flag-5'>定時(shí)器</b>詳解
    RM新时代网站-首页