SysTick定时器,也叫滴答定时器或者系统定时器。
12.1、Systick定时器基础知识讲解
12.2、Systick相关寄存器库函数讲解
12.3、delay延时函数讲解(Systick应用)
本节参考资料:《STM32F1开发指南-库函数版本》,5.1节delay文件夹介绍
12.1、Systick定时器基础知识讲解
(1)Systick定时器是什么?
Systick定时器是一个比较简单的定时器,常用于延时或者计时,也可以用作实时系统的心跳时钟。节省通用定时器的资源。
Systick定时器是一个24位倒计数的定时器,计时到0时,会自动从RELOAD寄存器中自动重装载定时初值。只要不把它在Systick控制及状态寄存器中的使能位清除,就永不停息。(只要不把Systick定时器关闭,它就会循环往复计时)在睡眠模式下也能工作。
Systick定时器被捆绑在NVIC(中断优先管理),用于产生Systick异常(意思是Systick定时器也可以产生中断,即每次从初值倒计数到0就可以视为一次中断,可以编写中断控制函数)
Systick中断的优先级也可以设置。
(2)4个Systick寄存器
CTRL: Systick控制和状态寄存器
RELOAD(LOAD): Systick自动重装载初值寄存器
VAL: Systick当前值寄存器
CALIB: Systick校准寄存器
VAL中存放的数值在每一个Systick周期后减1,当减为0后,VAL就会从LOAD中加载初值,再进行倒计数。
(3)Systic控制和状态寄存器-CTRL
HCLK:即AHB总线时钟
PS:在任何情况下,我们使用一个资源,一般都有使能位,并且,我们在调用该资源时,第一步都是使能该资源的时钟,因此在上表中的位0:ENABLE就是Systick的使能位。
上表中位1:TICKINT的意思是:在使用时选择Systick是否要产生中断。若把位2设置为1,则Systick在从初值倒计数到0时就会产生中断。
上表中位2:用于设置Systick的时钟源。设置为0,则Systick的时钟源就是外部时钟;设置为1,则Systick的时钟源就是内部时钟。
(4)Systick重装载数值寄存器-LOAD
重装载寄存器也为24位(0~23)这是因为Systick是24位时钟,因此其寄存器也应为24位。
(5)Systick当前值急寄存器-VAL
12.2、Systick相关寄存器库函数讲解
(1)固件库中Systick相关函数:
SysTick_CLKSourceConfig() //SysTick时钟源选择;
SysTick_Config(unit32_t ticks) //初始化SysTick时钟为HLCK,并且开启中断;
(2)SysTick中断服务函数
void SysTick_Handler(void);
PS:上述代码均可以在“跑马灯实验-库函数版本----->FWLIB------>misc.c”中查到。
关于在STM32库函数中SysTick的定义以及其寄存器对应地址的映射如下:
#define SysTick ((SysTick_Type *) SysTick_BASE) //对SysTick的宏定义
//systick寄存器对应的映射地址,包装在一个结构体中
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;
如何设置或者选择SysTick的时钟源?函数如下:
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK; //选择内部时钟源HLCK时钟
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; //选择外部时钟源HCLK的1/8
}
}
PS:对于STM32,外部时钟源是HCLK的1/8,内核时钟是HCLK。
如何开启中断,这一部分函数位于内核,几乎所有STM32的芯片都适用;
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 */
}
注意:systick=sysclk,而sysclk有二个来源,可以二选一,HSI,HSE,这二个的意思是一个外部晶振电路提供的频率,一个内部rc震荡提供的频率这二个频率自身只有8MHZ是无法给cpu提供频率,所以要通过pll倍频电路倍频到72MHZ(103的工作频率),然后AHB等等之类的总线是挂载在sysclk下的不同分支上,有的分频了36MHZ有的未分频等等
意思是AHB总线的频率就=sysclk的频率,而其他的APB等总线频率只有sysclk的八分之一
对于这段话的理解,可以参考时钟总线框图:
12.3、delay延时函数讲解(Systick应用)
1、用中断的方式实现delay延时
在使用延时函数前,记得初始化延时函数
delay_init(); //初始化延时函数