SysTick简介
SysTick—系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit
的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK
等于 72M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往
复。
因为 SysTick 是属于 CM3 内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,
使得软件在 CM3 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维
持操作系统的心跳
SysTick作用与优势
SysTick使用基于硬件的计数器来实现周期性的中断,可用于实现系统的延时、定时、多任务调度等功能。
SysTick的作用
实现系统延时:通过配置SysTick的计数器和中断,可以实现精确的微秒级别延时。这在许多嵌入式系统应用中非常重要,例如控制电机速度、等待传感器响应等。
实现系统定时:通过SysTick中断触发周期性事件,可以实现周期性任务的调度。这对于需要定期执行某些操作的应用非常有用,例如LED闪烁、传感器采集等。
实现多任务调度:通过SysTick中断触发任务切换,可以实现简单的多任务系统。这对于需要同时运行多个任务的应用非常有用,例如控制飞行器深度、高度和姿态等。
SysTick优势
硬件支持:SysTick是处理器内置的硬件模块,无需外部器件支持,具有较高的可靠性和稳定性。
高精度:SysTick计数器精度较高,通常为微秒级别,可满足大多数应用的需要。
灵活配置:SysTick可以配置为不同的时钟源和计数器值,以满足各种应用需求。这使得它非常适合不同嵌入式系统和实时操作系统中的使用场景。
节省功耗:SysTick可以在空闲状态下进入低功耗模式,以节省能源并延长电池寿命。这对于需要追求低功耗的嵌入式系统应用非常有帮助。
SysTick定时时间计算
SysTick 寄存器介绍
SysTick—系统定时器有 4 个寄存器,简要介绍如下。在使用 SysTick 产生定时的时候,只需要配
置前三个寄存器,最后一个校准寄存器不需要使用。
编程 (编写毫秒延时函数和微妙延时函数)
1.了解SysTick 配置库函数
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
// 不可能的重装载值,超出范围
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) {
return (1);
}
// 设置重装载寄存器
SysTick->LOAD = (uint32_t)(ticks - 1);
// 设置中断优先级
NVIC_SetPriority (SysTick_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
// 设置当前数值寄存器
SysTick->VAL = 0;
// 设置系统定时器的时钟源为 AHBCLK=72M
// 使能系统定时器中断
// 使能定时器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk;
return (0);
}
用固件库编程的时候我们只需要调用库函数 SysTick_Config() 即可,形参 ticks 用来设置重装载寄
存器的值,最大不能超过重装载寄存器的值 2^24,当重装载寄存器的值递减到 0 的时候产生中断,然后重装载寄存器的值又重新装载往下递减计数,以此循环往复。紧随其后设置好中断优先级,最后配置系统定时器的时钟等于 AHBCLK=72M,使能定时器和定时器中断,这样系统定时器就配置好了,一个库函数搞定。
2.了解SysTick中断优先级
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if(IRQn < 0) {
SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
else {
NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */
}
函数首先先判断形参 IRQn 的大小,如果是小于 0,则表示这个是系统异常,系统异常的优先级
由内核外设 SCB 的寄存器 SHPRx 控制,如果大于 0 则是外部中断,外部中断的优先级由内核外
设 NVIC 中的 IPx 寄存器控制。
因为 SysTick 属于内核外设,跟普通外设的中断优先级有些区别,并没有抢占优先级和子优先
级的说法。在 STM32F103 中,内核外设的中断优先级由内核 SCB 这个外设的寄存器: SHPRx
(x=1.2.3)来配置。
SPRH1-SPRH3 是一个 32 位的寄存器,但是只能通过字节访问,每 8 个字段控制着一个内核外设
的中断优先级的配置。在 STM32F103 中,只有位 7:4 这高四位有效,低四位没有用到,所以内核
外设的中断优先级可编程为: 0~15,只有 16 个可编程优先级,数值越小,优先级越高。如果软
件优先级配置相同,那就根据他们在中断向量表里面的位置编号来决定优先级大小,编号越小,
优先级越高。
在系统定时器中,配置优先级为 (1 « __NVIC_PRIO_BITS) - 1),其中宏 __NVIC_PRIO_BITS为 4,那计算结果就等于 15,可以看出系统定时器此时设置的优先级在内核外设中是最低的,如果要修改优先级则修改这个值即可,范围为: 0~15。
3.编写延时函数
void SysTick_Delay_us(uint32_t us)
{
uint32_t i ;
SysTick_Config(72);//延时1us
for(i=0;i<us;i++)
{
// 当计数器的值减小到 0 的时候, CRTL 寄存器的位 16 会置 1
while(!((SysTick->CTRL)&(1<<16)));
}
// 关闭 SysTick 定时器
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
void SysTick_Delay_ms(uint32_t ms)
{
uint32_t i ;
SysTick_Config(72000);//延时1ms
for(i=0;i<us;i++)
{
// 当计数器的值减小到 0 的时候, CRTL 寄存器的位 16 会置 1
while(!((SysTick->CTRL)&(1<<16)));
}
// 关闭 SysTick 定时器
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}