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了~ 哟西~~
|