STM32学习笔记3——Systick

对于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<endTime) ;
}

进行1ms的精确延时。此外还可以修改SystemCoreClock/1000进行不同时间的延时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值