STM32-SysTick-系统定时器
SysTick—系统定时器
SysTick 简介
SysTick—系统定时器是属于 CM4 内核中的一个外设,内嵌在 NVIC 中。系统定时器是一个 24bit
的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK
等于 180M。当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环
往复。
因为 SysTick 是属于 CM4 内核的外设,所以所有基于 CM4 内核的单片机都具有这个系统定时器,
使得软件在 CM4 单片机中可以很容易的移植。系统定时器一般用于操作系统,用于产生时基,维
持操作系统的心跳。
SysTick 定时实验
1、设置重装载寄存器的值
2、清除当前数值寄存器的值
3、配置控制与状态寄存器
SysTick 初始化函数
1 | void SysTick_Init(void) |
SysTick 中断时间的计算
SysTick 定时器的计数器是向下递减计数的,计数一次的时间 TDEC=1/CLKAHB,当重装载寄存器
中的值 VALUELOAD 减到 0 的时候,产生中断,可知中断一次的时间 TINT=VALUELOAD* TDEC 中断
= VALUELOAD/CLKAHB,其中 CLKAHB =168MHZ。如果 VALUELOAD 设置为 180,那中断一次的时
间 TINT=168/168M=1us。不过 1us 的中断没啥意义,整个程序的重心都花在进出中断上了,根本
没有时间处理其他的任务。
1 | SysTick_Config(SystemCoreClock / 100000)) |
SysTick_Config()的形我们配置为 SystemCoreClock / 100000=180M/100000=1680,从刚刚分析我们知道这个形参的值最终是写到重装载寄存器 LOAD 中的,从而可知我们现在把 SysTick 定时器
中断一次的时间 TINT=1680/168M=10us。
SysTick 定时时间的计算
当设置好中断时间 TINT 后,我们可以设置一个变量 t,用来记录进入中断的次数,那么变量 t 乘
以中断的时间 TINT 就可以计算出需要定时的时间。
SysTick 定时函数
1 | void Delay_us(__IO u32 nTime) |
函数 Delay_us() 中我们等待 TimingDelay 为 0,当 TimingDelay 为 0 的时候表示延时时间到。变量
TimingDelay 在中断函数中递减,即 SysTick 每进一次中断即 10us 的时间 TimingDelay 递减一次。
SysTick 中断服务函数
1 | void SysTick_Handler(void) |
中断复位函数调用了另外一个函数 TimingDelay_Decrement(),原型如下:
1 | void TimingDelay_Decrement(void) |
TimingDelay 的值等于延时函数中传进去的 nTime 的值,比如 nTime=100000,则延时的时间等于
100000*10us=1s。
另外一种更简洁的定时编程
上面的实验,我们是使用了中断,而且经过多个函数的调用,还使用了全局变量,理解起来挺费
劲的,其实还有另外一种更简洁的写法。我们知道, systick 的 counter 从 reload 值往下递减到 0 的
时候, CTRL 寄存器的位 16:countflag 会置 1,且读取该位的值可清 0,所有我们可以使用软件查
询的方法来实现延时。
1 | void SysTick_Delay_Us( __IO uint32_t us) |
1 | void SysTick_Delay_Ms( __IO uint32_t ms) |
在这两个微秒和毫秒级别的延时函数中,我们还是调用了 SysTick_Config 这个固件库函数 ,其中 SystemCoreClock 是一个宏,大小为 168000000,如果不想使用这个宏,也可以直接改成数字。
1 | // 这个 固件库函数 在 core_cm3.h 中 |