一、SysTick—系统定时器简介
SysTick—系统定时器是属于CM3内核中的一个外设,内嵌在NVIC中。系统定时器是一个24bit的向下递减的计数器, 计数器每计数一次的时间为1/SYSCLK,一般我们设置系统时钟SYSCLK等于72M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。
因为SysTick是属于CM3内核的外设,所以所有基于CM3内核的单片机都具有这个系统定时器,使得软件在CM3单片机中可以很容易的移植。 系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。
二、SysTick寄存器介绍
SysTick—系统定时器有4个寄存器,简要介绍如下。在使用SysTick产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
SysTick 属于内核的外设,有关的寄存器定义和库函数都在内核相关的库文件core_cm3.h中。
三、 SysTick定时实验
功能:利用SysTick产生1s的时基,LED以1s的频率闪烁。
编程要点
1、设置重装载寄存器的值
2、清除当前数值寄存器的值
3、配置控制与状态寄存器
SysTick_Config()库函数主要配置了SysTick中的三个寄存器:LOAD、VAL和CTRL。
用固件库编程的时候我们只需要调用库函数SysTick_Config()即可,形参ticks用来设置重装载寄存器的值, 最大不能超过重装载寄存器的值224,当重装载寄存器的值递减到0的时候产生中断,然后重装载寄存器的值又重新装载往下递减计数, 以此循环往复。紧随其后设置好中断优先级,最后配置系统定时器的时钟等于AHBCLK=72M,使能定时器和定时器中断,这样系统定时器就配置好了,一个库函数搞定。
//SysTick配置库函数
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// 不可能的重装载值,超出范围
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) {
return (1UL);
}
// 设置重装载寄存器
SysTick->LOAD = (uint32_t)(ticks - 1UL);
// 设置中断优先级
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
// 设置当前数值寄存器
SysTick->VAL = 0UL;
// 设置系统定时器的时钟源为AHBCLK=72M
// 使能系统定时器中断
// 使能定时器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0UL);
}
SysTick 初始化函数
/**
* @brief 启动系统滴答定时器 SysTick
* @param 无
* @retval 无
*/
void SysTick_Init(void)
{
/* SystemFrequency / 1000 1ms 中断一次
* SystemFrequency / 100000 10us 中断一次
* SystemFrequency / 1000000 1us 中断一次
*/
if (SysTick_Config(SystemCoreClock / 100000)) {
/* Capture error */
while (1);
}
}
SysTick 定时时间的计算
当设置好中断时间 T INT 后,我们可以设置一个变量 t,用来记录进入中断的次数,那
么变量 t 乘以中断的时间 TINT 就可以计算出需要定时的时间。
SysTick 定时函数
现在我们定义一个微秒级别的延时函数,形参为 nTime,当用这个形参乘以中断时间
TINT 就得出我们需要的延时时间,其中 TINT 我们已经设置好为 10us。关于这个函数的具体
调用看注释即可。
/*
us 延时程序,10us 为一个单位
Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
*/
void Delay_us(__IO u32 nTime)
{
TimingDelay = nTime;
while (TimingDelay != 0);
}
函数 Delay_us()中我们等待 TimingDelay 为 0,当 TimingDelay 为 0 的时候表示延时时
间到。变量 TimingDelay 在中断函数中递减,即 SysTick 每进一次中断即 10us 的时间
TimingDelay 递减一次。
//SysTick 中断服务函数
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
中断复位函数调用了另外一个函数 TimingDelay_Decrement()
,原型如下:
/*
获取节拍程序
在 SysTick 中断函数 SysTick_Handler()调用
*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00) {
TimingDelay--;
}
}
TimingDelay 的值等于延时函数中传进去的 nTime 的值,比如 nTime=100000,则延时
的时间等于 100000*10us=1s。
主函数
int main(void)
{
/* LED 端口初始化 */
LED_GPIO_Config();
/* 配置 SysTick 为 10us 中断一次,时间到后触发定时中断,
*进入 stm32fxx_it.c 文件的 SysTick_Handler 处理,通过数中断次数计时
*/
SysTick_Init();
while (1) {
LED_ON;
Delay_us(100000); // 10000 * 10us = 1000ms
LED2_ON;
Delay_us(100000); // 10000 * 10us = 1000ms
LED3_ON;
Delay_us(100000); // 10000 * 10us = 1000ms
}
}
主函数中初始化了 LED 和 SysTick,然后在一个 while 循环中以 1s的频率让 LED 闪烁。