SysTick定時器詳解


SysTick定時器詳解

關於SysTick定時器,如果想從STM32官方手冊去尋找該定時器,會發現並沒有該定時器的相關介紹,僅有庫函數介紹。由此可以看出SysTick並不是意法半導體公司設定的。從Cortex-M3權威指南可以找到該定時器的詳細介紹,由此可以知道SysTick定時器是在ARM芯片當中設定的。
這里有一個疑問,為什么M3有這么多定時器還要弄一個SysTick定時器呢?
這要從它的概念入手,系統滴答定時器是一個非常基本的倒計時定時器,用於在每隔一定時間產生一個中斷,即使是系統在睡眠模式下也能工作。它使得OS在各CM3器件之間的移植中不必修改系統定時器的代碼,移植工作一下子容易多了。SysTick定時器也是作為NVIC的一部分實現的。

如果有外設就一定會存在一堆用來配置該外設的寄存器,SysTick定時器也不例外。用來控制該定時器的寄存器有四個,下面詳細介紹這四個寄存器。

SysTick控制及狀態寄存器(地址:0xE000_E010)

位段 名稱 類型 復位值 描述
16 COUNTFLAG R 0 如果在上次讀取本寄存器后, SysTick 已經數到了 0,則該位為 1。如果讀取該位,該位將自動清零
2 CLKSOURCE R/W 0 0=外部時鍾源(STCLK) 1=內核時鍾(FCLK)
1 TICKINT R/W 0 1=SysTick 倒數到 0 時產生 SysTick 異常請求 0=數到 0 時無動作
0 ENABLE R/W 0 SysTick 定時器的使能位

四個位都挺簡單,對兩個稍難的解釋一下:

TICKINT 該位置為1時,SysTick定時器倒數到零會產生中斷

COUNTFLAG 已經有了TICKINT為什么還要該位呢,原因是當TICKINT位置為0時,如果沒有該位,就無法得知定時器是否已經倒數到0,因為倒數到0不會有任何動作。

SysTick重裝載數值寄存器(地址:0xE000_E014)

位段 名稱 類型 復位值 描述
23:0 RELOAD R/W 0 當倒數至零時,將被重裝載的值

該寄存器24位,最大可裝載值為FF FFFF

SysTick當前數值寄存器(地址:0xE000_E018)

位段 名稱 類型 復位值 描述
23:0 CURRENT R/Wc 0 讀取時返回當前倒計數的值,寫它則使之清零, 同時還會清除在 SysTick 控制及狀態寄存器中的 COUNTFLAG 標志

該寄存器被讀取后,會清零,重裝載寄存器就會將它里面的重裝載值傳遞到該寄存器。

SysTick校准數值寄存器(地址:0xE000_E01C)

位段 名稱 類型 復位值 描述
31 NOREF R 1=沒有外部參考時鍾(STCLK 不可用) 0=外部參考時鍾可用
30 SKEW R 1=校准值不是准確的 10ms 0=校准值是准確的 10ms
23:0 TENMS R/W 0 10ms 的時間內倒計數的格數。芯片設計者應該通 過 Cortex‐M3 的輸入信號提供該數值。若該值讀 回零,則表示無法使用校准功能

介紹完了寄存器,那就去STM32官方手冊看看相關庫函數吧,有一點可以肯定的是,庫函數就是用來設置上面四個寄存器中某些位的。

在core_cm3.h文件中有這么一個函數可以用來配置SysTick定時器:

/**
 * @brief  Initialize and start the SysTick counter and its interrupt.
 *
 * @param   ticks   number of ticks between two interrupts
 * @return  1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 * 初始化並啟動系統滴答定時器和它的中斷/計數器自由運行模式用來產生周期性的中斷
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register * SysTick_LOAD_RELOAD_Msk為0xFFFFFF */
  SysTick->VAL   = 0;                                          /* 把當前計數值設置為0,這* 樣會將重裝載寄存器中的值自動加載進來 Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | 
                   SysTick_CTRL_TICKINT_Msk   | 
                   SysTick_CTRL_ENABLE_Msk;                    /* 將SysTick控制及狀態寄存器低三位全部置為1。0、SysTick 定時器被使能 2、SysTick 倒數到 0 時產生 SysTick 異常請求 3、選擇內核時鍾(FCLK)為時鍾源,也就是72MHZ*/
  return (0);                                                  /* Function successful */
}

#endif

用中斷的方式實現delay:

void SysTick_Configuration(void){
    while(SysTick_Config(72)==1);	//1us產生一次SysTick異常
    SysTick->CTRL &= ~(1<<0);	//SysTick暫不開啟,等使用時再開啟
}

Void delay_us(unsigned long n){
    SysTick->CTRL |= (1<<0);
    while(n);  //每1us會產生一次中斷,n--
    SysTick->CTRL &= ~(1<<0);
}

void SysTick_Handler(void){
    n--;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM