Systick定时器属于是简单定时器,是为了节省定时器资源而存在的一个一般用于延时和用作实时系统的心跳时钟的一个定时器。
Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
并且SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。即它从计数初值记到0时可以产生中断。Systick中断的优先级也可以设置。
4个相关寄存器:
1.CTRL SysTick 控制和状态寄存器
2.LOAD 自动重装载初值寄存器
3.VAL 当前值寄存器
4.CALIB 标准值寄存器(用于校准,不常用)
相关库函数:
固件库中的Systick相关函数:
SysTick_CLKSourceConfig() //Systick时钟源选择 misc.c文件中
SysTick_Config(uint32_t ticks) //初始化systick,时钟为HCLK,并开启中断
//core_cm3.h/core_cm4.h文件中
Systick中断服务函数:
void SysTick_Handler(void);
相关结构体:
typedef struct
{
__IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
__IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
__IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
__I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;
1.SysTick_CLKSourceConfig
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/* Check the parameters */
assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK;
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}
这个函数非常简单,就是设置时钟源(即设置SysTick时钟周期),无非就两种选择。
- SysTick_Config(uint32_t ticks)
/**
* @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 */
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 SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
从注释可以看出该函数的作用初始化并使能定时和中断。入口参数: ticks: number of ticks between two interrupts。也就是两次中断间的计数次数,即两次中断之间有多少个sysTick时钟周期,归根结底也就是规定两次中断的时间间隔。
3.中断服务函数举例:
static __IO uint32_t TimingDelay;
void Delay(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
void SysTick_Handler(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
int main(void)
{ …
if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms
{
while (1);
}
while(1)
{ Delay(200);//2ms
…
}
}
if (SysTick_Config(SystemCoreClock / 1000)) 把ticks参数设为72M除1000。也就是两次中断中间有这么多个sysTick时钟周期。而sysTick时钟周期为72MHZ(也就是把sysTick时钟周期配置为HCLK,而不是HCLK/8),所以两次中断之间的时间为1ms。Delay(200)会把TimingDelay值设为200,当sysTick定时器计数到0产生中断时中断服务函数工作,把TimingDelay 值减1,然后程序执行又回到 while(TimingDelay != 0);这个空的while循环。中断可以理解为多线程。当触发中断时MCU的使用权归中断服务函数所有,当中断服务函数执行结束该线程挂起,执行权又回到Delay函数,继续执行循环。