对于STM32中,有一个经常用到,却在数据手册上很少资料的工具,那就是Systick,这个工具是所有cortex-M0内核的单片机所共有的,他是一个系统定时器,其存在的主要目的是为嵌入式操作系统提供100Hz(即10ms)的定时节拍。当然,也可以做为其它的普通定时等其他用途。下面,我们就开始理解这个定时器。
寄存器
系统定时器包括四个寄存器,SYST_CSR、SYST_RVR、SYST_CVR、SYST_CALIB。定义如下所示:
对于这几个寄存器我们可以翻译一下:
SYST_CSR寄存器,系统定时器控制和状态寄存器
SYST_RVR寄存器,系统定时器重载值寄存器
SYST_CVR寄存器,系统定时器当前值寄存器
SYST_CALIB寄存器,系统定时器校准寄存器
这样就很明了了,对于这几个寄存器我们一个个的看。
首先是SYST_CSR寄存器:
CSR寄存器用到的位有4个,bit0用于是否开启定时器,bit1用于是否产生中断,bit2用于选择定时器的时钟源是等于主时钟还是等于主时钟的一半,bit16是定时器的状态。
SYST_RVR寄存器
RELOAD 值可以是 0x00000001-0x00FFFFFF 范围内的任何值。您可以将 RELOAD 的值设为 0,这不会产生任何影响,因为计数值从 1变为 0时 SysTick 异常请求和 COUNTFLAG都被激活了。如果要产生一个周期为 N个处理器时钟周期的多次触发定时器,就可以将 RELOAD 值设为 N-1。例如,如果要求每隔 100个时钟脉冲就触发一次 SysTick 中断,RELOAD 就被设为 99。
SYST_CVR寄存器
CVR寄存器用到bit0~23,即24位数,这是一个状态寄存器,当定时器开始运作,这个值在不断地变化,从RVR寄存器获取初值以后,倒计时到0.
SYST_CALIB寄存器
校准寄存器SYST_CALIB不用我们考虑,出厂前就配置好了。
函数
系统自带的Systick函数,由CMSIS(关于什么是CMSIS,去百度搜吧)提供,位于core_cm0.h文件,在其中第656行有如下函数
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
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->LOAD = ticks – 1;”知道,ticks就是LOAD值,即重载值,表示两次中断的计数。
例如,要产生10ms的中断,可以在程序中如下调用函数:Systick_Config(SystemCoreClock/100);函数参数中的SystemCoreClock是当前主频的值,假如现在的主频是48MHz,SystemCoreClock就是48 000 000 ,48 000 000 /100=480 000。我们把参数带进去以后,LOAD=479 999,也就是说,定时器开始运行后,定时器的值会从479 999递减到0,进入中断函数,然后再次从479 999 递减到0,如此循环。至于为什么从479 999递减到0就是10ms?知道每递减一个值需要多长时间,那么递减480 000下,需要多长时间,就知道了。要知道每递减一个值需要多长时间,就需要知道当前定时器运行的时钟是多少。由寄存器CSR知道,定时器的时钟有两种,一种是等于主频,一种是等于主频的二分之一,由CSR寄存器中的bit2决定。
函数中,对控制寄存器的bit0 bit1 bit2都置1,对照前面的寄存器定义可知,时钟设置为等于主频,打开系统定时器中断,允许定时器运行。
我们知道了时钟,就知道定时器每递减一个值需要的时间了,即:1/SystemCoreClock 秒,换算成毫秒即:(1/SystemCoreClock)*1000=1000/SystemCoreClock毫秒,即每递减一个值,耗时1000/SystemCoreClock毫秒。所以如果要使得10ms定时,即10/(1000/SystemCoreClock)=SystemCoreClock/100,所以,我们的设置是正确的。以此类推,需要定时多长时间,你可以自己算一个参数带进去了,需要注意的是,LOAD值是个24位数,带进去的数不要超过24位数的最大值。还有一个需要注意的地方,就是LOAD值最小255,当你给LOAD值带进去小于255值,LOAD会自动变成255。由于定时器SYST_RVR寄存器为24位的,所以最大值为十六进制FFFFFF,化为十进制为16777215,所以最多能储存数据为16777215+1=16777216;
定时器延时
利用CMSIS中的函数我们可以写如下的函数:
__IO uint32_t msTick;
void SysTick_Handler(void) // 中断函数
{
msTick++;
}
void delay_ms(IO uint32_t ms)
{
uint32_t endTime=msTicks+ms;
SysTick_Config((SystemCoreClock/1000)*ms);
while(msTicks } 进行1ms的精确延时。此外还可以修改SystemCoreClock/1000进行不同时间的延时。
上一篇:STM32之SysTick(系统定时器)
下一篇:STM32滴答定时器(Systick)详细详细解析
推荐阅读最新更新时间:2024-03-16 16:09
设计资源 培训 开发板 精华推荐
- 3.5\"嵌入式主板给力开团 仅售599元包邮!
- TI直播| 低功耗技术在 Wi-Fi 摄像头及 PIR 红外传感器设计中的应用
- ST SensorTile物联网开发套件来啦!免费申请抢鲜体验等你来~
- 温故知新:回顾 ST 2017 Roadshow,洞悉电子界技术新潮流!
- TI单芯片毫米波传感器产品组合新品发布会,诚邀参与,预注册赢好礼
- 免费申请TI 样片,晒单赢好礼!
- 2020 STM32全国研讨会火热报名中,新技术新方案等你收获,还有好礼拿!
- 激情竞赛日--看谁最给力!
- TI Simplelink 狂欢正嗨,热门产品 9 折特惠!更有分享好礼任性送!
- 意法半导体工业峰会2023 直播结束