![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cGcq5yM0cTN1UGNhhTYzYGNxYzYxYzXzADN0IDM1IzLcJTMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.jpg)
文章目錄
-
-
- 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