概念:
SysTick—系统定时器是属于CM3内核中的一个外设,内嵌在NVIC中。系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK,一般我们设置系统时钟SYSCLK等于72M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。
寄存器:
源码分析:
首先,在main函数中的会率先初始化时钟调用HAL_RCC_ClockConfig,在这个函数中,我们主要关注Systick部分,包括更新SystemCoreClock变量,和调用HAL_InitTick配置Systick。这个函数源码如下:
红圈部分函数:HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) ,其中SystemCoreClock为HCLK=72MHz,uwTickFreq默认为1,表示1kHz,所以计算得到:HAL_SYSTICK_Config(72000);
HAL_SYSTICK_Config又调用SysTick_Config这个函数。
在SysTick_Config这个函数中,首先会判断预设的Tick是否会溢出,Systick是24位,2的24次方:16777216,预设的Tick需要小于16777216。然后对寄存器继续赋值操作:我们看到SysTick->CTRL的赋值,时钟源是默认是选择AHB,如果要选择AHB8分频,可以通过HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);该函数的源码:
实现一个极简的微妙us延时
//nus = 1~999
void delay_us(uint32_t nus){
SysTick->VAL = 0X00; //写操作进行清零
uint32_t tt = nus * 72; //1us = 72个计数值
while(SysTick->VAL == 0 || SysTick->LOAD - SysTick->VAL < tt);
}
因为SysTick的装载值最大可以是16777216,而我们的默认装载值是经过1000倍缩小的72000,所以装载值具有很大的修改提升空间,我们自然想到通过SysTick->LOAD 来增大装载值,从而提升延时函数的延时最大值,实现ms级别的延时,但是需要谨慎,因为改变装载值,会改变产生一个SysTick中断的时间,从而影响HAL_Delay函数的准确性,我们可能需要重写该函数,另外即使设置装载值为最大,经过计算16777216/72000 约等于233ms,提升不大,
如果结合时钟源分频,即通过HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);设置八分频,那么原来是1ms计72000个数,就变成8ms计72000个数,即1ms即9000个数,计数区间也会提升不少。我们可以计算得到最大延时是:16777216/9000 约等于1864ms,这个值可以在一些场合还是不满足,可以通过for循环进行重复延时来达到更大的延时,或通过时间摘取法实现(这里不展开)。