SysTick时钟,俗称“嘀嗒定时器”,它能按固定的时间产生一次中断,通常是多长时间产生一次中断呢?官方给出的一个时间是1ms
那么,它是怎么准确的产生1ms的呢.. 先来看看这家伙在时钟树的哪里吧
它是由HCLK/8得到的,也就是:72MHz/8=9MHz。
我们还能在STM32手册上找到这么一句话:系统嘀嗒校准值固定位9000,当系统嘀嗒时钟设为9MHz,产生1ms时间基准.
让我们来看看9000是怎么来的,这里要看下SysTick寄存器的配置了:
可以看到SysTick共有4个寄存器.
注意看上面的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了~ 哟西~~