首页 > 代码库 > STM32学习之路-不得不说的SysTick时钟

STM32学习之路-不得不说的SysTick时钟

SysTick时钟,俗称“嘀嗒定时器”,这家伙能按固定的时间产生一次中断,通常是多长时间产生一次中断呢?官方给出的一个时间是1ms

那么,它是怎么准确的产生1ms的呢.. 先来看看这家伙在时钟树的哪里吧


是它,是它,就是它,红色框里的东东,可以看到,它是由HCLK/8得到的,也就是:72MHz/8=9MHz

我们还能在STM32手册上找到这么一句话:系统嘀嗒校准值固定位9000,当系统嘀嗒时钟设为9MHz,产生1ms时间基准.

让我们来看看9000是怎么来的,这里要看下SysTick寄存器的配置了


当然,这个图截得真他妈丑..不过来是可以看到SysTick共有4个寄存器.下面的图盗自别人的博客的, = =  但是链接没法给出,说是禁止URL 真蛋疼




注意看上面的CTRL寄存器的CLKSOURCE位(时钟源位),它有两个选择,一个是内核时钟源FLCK(72MHz),一个是外部时钟源HCLK,这里应该是

分频以后的了,所以应该是HCLK/8(9MHz);注意这里,这里选不同的值,重装寄存器里的值也是不同的.到下面配置的时候再说说.

好,那么我们来解释下9000的固定校准值是怎么来的:

我们知道,我们设定一个计数,那么每次计数器减到0,时间经过了:系统时钟周期 *计数器初值.我们使用72M作为系统时钟,那么每次计数器减1所用的时间是1/72M计数器的初值如果是72000,那么每次计数器减到0,时间经过(1/72M)*72000= 0.001(简单理解:用72M的时钟频率,即1s计数72M=72000000次,那1ms计数72000次,所以计数值为72000,那么它的固定校准值是怎么来的呢..其实我也不知道的,可能和8分频有关系吧.. = = 实在不知道..官方系统库中也找不到关于它的设置 - - 可能是我蠢..

让我们来看看这些寄存器的配置:

系统库core_cm3.h中

static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            /* Reload value impossible */
                                                               
  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;      /* set reload register */
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);  /* set Priority for Cortex-M0 System Interrupts */
  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 Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos         16                                             /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk         (1ul << SysTick_CTRL_COUNTFLAG_Pos)            /*!< SysTick CTRL: COUNTFLAG Mask */

#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */

#define SysTick_CTRL_TICKINT_Pos            1                                             /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)              /*!< SysTick CTRL: TICKINT Mask */

#define SysTick_CTRL_ENABLE_Pos             0                                             /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)               /*!< SysTick CTRL: ENABLE Mask */

/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos             0                                             /*!< SysTick LOAD: RELOAD Position */
#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        /*!< SysTick LOAD: RELOAD Mask */

/* SysTick Current Register Definitions */
#define SysTick_VAL_CURRENT_Pos             0                                             /*!< SysTick VAL: CURRENT Position */
#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick VAL: CURRENT Mask */
代码上说得很明白了~简单的抓一个来解释下吧.. 就抓CTRL吧.. 从上面的寄存器图上可以看到,它只需要配置4个位,即:16、2、1、0位,其它的保留不变不用鸟

#define SysTick_CTRL_CLKSOURCE_Pos          2                                             /*!< SysTick CTRL: CLKSOURCE Position */

#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)            /*!< SysTick CTRL: CLKSOURCE Mask */

ul是unsigned long 型, 这两行代码的意思是1左移2位,也就是将2这位置1,这里就是选择了内核时钟源FCLK(72MHz),所以我们要把计数初值设置为72000,这样才能

产生1ms的基准时钟哦~ 当然,如果这里将1改为0,那么就要将计数初值设为9000了~ 哟西~~

好吧~ 其它的就慢慢对着瞧吧.. 剩下的就是写例子了~ 下篇吧. 有点累了!