从原理上来说,Systick定时器和开发板上的通用定时器没有区别。从功能上来说,Systick定时器主要是用来用来进行延时的,而通用或者高级定时器往往用来进行PWM输出、输入捕获等功能。至于为什么不用通用定时器或者高级定时器来完成延时功能,则是考虑到节省MCU的资源来做更重要的事。
SysTick系统定时器是属于内核中的一个外设,内嵌在NVIC中。该定时器是一个24位的向下递减的计数器。在裸机编程中常用做延时函数,而在FreeRTOS中则用来给系统提供时钟的,因此非常重要。
SysTick 是 Cortex-M 系列内核中普遍存在的系统定时器,共 24 位(高 8 位保留),通过不断递减进行计数,到达 0 时将 SYST_CSR 的 COUNTFLAG 标志位置 1 并根据 TICKINT 标志位决定是否产生内核中断。因此,利用 SysTick 实现延时函数就分为中断式和非中断式两种。前者容易产生优先级冲突,也不适合在中断函数中调用;这里选择的是后者,直接对寄存器进行操作和查询。需要注意的是,使用 FreeRTOS 等实时操作系统时,修改 SysTick 会影响系统时钟,建议采用软件延时或使用其他定时器。
1.SysTick_CLKSourceConfig 配置时钟源
函数原型:viod SysTick_CLKSourceConfig (u32 SysTick_CLKSource)
功能:选择SysTick的时钟源
参数:SysTick_CLKSource:SysTick时钟源
参数:SysTick_CLKSource
SysTick_CLKSource_HCLK_Div8:SysTick时钟源等于系统时钟的8分频。
SysTick_CLKSource_HLCK:SysTick时钟源等于系统时钟。
例子:viod SysTick_CLKSourceConfig (SysTick_CLKSource_HLCK); //选用AHB时钟作为SysTick的时钟源。
SysTick是1个24bit递减计数器,通过对SysTick控制与状态寄存器的设置,可选择HCLK时钟(72M)或HCLK的8分频(9M,缺省是这个)作为SysTick的时钟源。
2.SysTick_Config 配置定时器时间
SysTick_Config(72000) 函数的参数就是systick重装定时器的值,其实就是一个时钟次数。
如果STM32时钟频率为:72MHz,每次的时间为:T=1/72MHz。
SysTick_Config(72000)代表:72000*(1/72MHz)=1/1000=1(ms)。即定时为1ms。
程序示例:
/*
* 函数名:SysTick_Init
* 描述 :启动系统滴答定时器 SysTick
* 输入 : 无
* 输出 :无
* 调用 : 外部调用
*/
void SysTick_Init(void)
{
if(SysTick_Config(SystemCoreClock/1000)) //1ms定时器
{
while(1);
}
//SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //若无法启动则关闭
}
SysTick_Config(SystemCoreClock / 1000)的目的是确保SysTick定时器每次发生中断的时间间隔都是1ms。(因为使用系统时钟的时钟频率为72000000,SystemCoreClock / 1000等于72000,也就是给重装载寄存器值赋72000,这样计72000正好是1ms)
注意事项:
- SysTick是一个24位定时器,所以最大重装值使2^24=16777215,注意不要超过此最大范围;
- 启动SysTick要确保,定时器的计数器在上一次重装载之后没有再次开始计数,以保证定时的准确性;
- SysTick是ARM Cortex-M3的标准配备,,所以SysTick并不是stm32的外设,不需要再RCC寄存器组打开他的时钟;
- 每次SysTick溢出后,会置位计数标志位和中断标志位,计数标志位在计数值重载后被清除,而中断标志位也会随中断服务响应被清除,所以两个标志位不需要手动清除;