使用系統定時器SysTick實現精確延時微秒和毫秒函數


SysTick定時器簡介

SysTick定時器是存在於系統內核的一個滴答定時器,只要是ARM Cortex-M0/M3/M4/M7內核的MCU都包含這個定時器,它是一個24位的遞減定時器,當計數到 0 時,將從RELOAD 寄存器中自動重裝載定時初值,開始新一輪計數。使用內核的SysTick定時器來實現延時,可以不占用系統定時器,由於和MCU外設無關,所以代碼的移植,在不同廠家的Cortex-M內核MCU之間,可以很方便的實現。而東芝的這款TT_M3HQ開發板使用的TMPM3HQFDFG芯片,正好是ARM Cortex-M3內核,所以以前使用的延時函數,可以直接拿過來使用,無需任何修改。

精確延時函數的實現

在core_cm3.h文件中,有這樣一個SysTick_Config函數:

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
  if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  {
    return (1UL);                                                   /* Reload value impossible */
  }

  SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  return (0UL);                                                     /* Function successful */
}

通過后面的注釋也可以看出,這是對SysTick定時器進行初始化,配置初始計數值,使能中斷,使能定時器等。對應的中斷函數為:

void SysTick_Handler(void)
{	
}

這個默認是空的,需要我們自己來實現。

如果SysTick初始化為:

SysTick_Config(SystemCoreClock / 1000);     //定時1ms

即SysTick定時器每1ms中斷一次,如果我們定義全局變量,然后在中斷函數中,讓此變量遞減,而在延時函數中,一直判斷此變量是否減到了0,那么這樣就實現了一個延時毫秒的函數。同理改變定時器的計數值為:

SysTick_Config(SystemCoreClock / 1000000);  //定時1us

那么就實現了每1us中斷一次,所以延時微秒和延時毫秒函數的實現:

uint32_t fac_us=0;							//us延時倍乘數			   
uint32_t fac_ms=0;							//ms延時倍乘數,在ucos下,代表每個節拍的ms數
	
void delay_init(void)
{
    SystemCoreClockUpdate();        //可以省略
}
void SysTick_Handler(void)
{
    if(fac_us) fac_us--;
    if(fac_ms) fac_ms--;
}
void delay_us(uint32_t nus)
{	
    SysTick_Config(SystemCoreClock / 1000000);  //定時1us
    fac_us = nus;
    while(fac_us != 0);	 
}

void delay_ms(uint32_t nms)
{	 		  	  
    SysTick_Config(SystemCoreClock / 1000);     //定時1ms
    fac_ms = nms;
    while(fac_ms != 0);	 	  	    
} 

在使用延時函數之前,只需要進行系統時鍾的更新即可,當然也可以不更新,因為在程序之前之前,系統啟動文件中已經執行了系統時鍾更新。

總結

由於SysTick定時器是所有的ARM Cortex-M內核MCU都有的一個定時器,所以以上延時微秒和延時毫秒的函數適用於任何 Cortex-M內核的MCU。有了精確延時函數,那么使用通用GPIO軟件模擬一些通信協議,如IIC、SPI等串行協議,就可以驅動很多硬件設備了,如EEPROM、溫濕度傳感器、顯示屏等等。


推薦閱讀


  • 我的個人博客:www.wangchaochao.top
  • 我的公眾號:mcu149


免責聲明!

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



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