stm32 SysTick时钟

SysTick定时器被捆绑在NVIC中,用于产生systick异常。在以前,操作系统还有所有使用了时基的系统,都必须一个硬件定时器来产生需要的“滴答”中断,作为整个系统的时基。滴答中断对操作系统尤其重要。例如,操作系统可以为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
Stm32系统嘀嗒校准值固定为9000,当系统嘀嗒时钟设定为9MHz(HCLK/8的最大值) ,产生1ms 时间基准。
9M/9000=1000;1/1000=1MS

(1)CTRL 寄存器`
CTRL 是 SysTick 定时器的控制及状态寄存器。其相应位功能如下:
stm32 SysTick时钟_第1张图片注:CLKSOUTCE 位是用于选择 SysTick 定时器时钟来源,如果该位为 1,表示其时钟是由系统时钟直接提供即 72M。如果为 0,表示其时钟是由系统时钟八分频后提供即 72/8=9M。
(2)LOAD 寄存器
LOAD 是 SysTick 定时器的重装载数值寄存器。其相应位功能如下:
在这里插入图片描述 因为 STM32F1 的 SysTick 定时器是一个 24 位递减计数器,因此重装载寄存器中只使用到了低 24 位,即 bit0-bit23。当系统复位时,其值为 0。
(3)VAL 寄存器VAL 是 SysTick 定时器的当前数值寄存器。其相应位功能如
stm32 SysTick时钟_第2张图片
同样只有 bit0-bit23 有效,复位时值为 0。
(4)CALIB 寄存器
CALIB 是 SysTick 定时器的校准数值寄存器。其相应位功能如下:
stm32 SysTick时钟_第3张图片SysTick 定时器的操作可以分为 4 步:
(1)设置 SysTick 定时器的时钟源。
(2)设置 SysTick 定时器的重装初始值(如果要使用中断的话,就将中断
使能打开)。
(3)清零 SysTick 定时器当前计数器的值。
(4)打开 SysTick 定时器。
SysTick_Init 函数代码如下:

/**************************************************************************
*****
* 函 数 名 : SysTick_Init * 函数功能 : SysTick 初始化,SYSTICK 的时钟固定为 AHB 时钟的 1/8
* 输 入 : SYSCLK:系统时钟频率
* 输 出 : 无
***************************************************************************
****/
void SysTick_Init(u8 SYSCLK)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SYSCLK/8; //SYSCLK的 8分频 保存 1us所需的
计数次数
fac_ms=(u16)fac_us*1000; //每个 ms 需要的 systick 时钟数
}

SysTick_Init 函数形参 SYSCLK 表示的系统时钟大小,默认配置我们使用的系统时钟是 72M,所以调用这个函数时,形参值即为 72。函数内部调用了一个库函数 SysTick_CLKSourceConfig,此函数用来对 SysTick 定时器时钟的选择,我们 使 用 的 SysTick 定 时 器 时 钟 是 系 统 时 钟 的 8 分 频 , 所 以 参 数 是SysTick_CLKSource_HCLK_Div8。如果使用系统时钟作为 SysTick 定时器时钟,那么参数即为 SysTick_CLKSource_HCLK。这个函数在 misc.c 库文件内,
delay_us 函数代码如下:

   /**************************************************************************
    *****
    * 函 数 名 : delay_us * 函数功能 : us 延时,
    * 输 入 : nus:要延时的 us 数
    注 意 :nus 的 值 , 不 要 大 于 798915us( 最 大 值 即
    2^24/fac_us@fac_us=21) * 输 出 : 无
    ***************************************************************************
    ****/
    void delay_us(u32 nus)
    {
    u32 temp;
    SysTick->LOAD=nus*fac_us; //时间加载
    SysTick->VAL=0x00; //清空计数器
    SysTick->CTRL|=0x01 ; //开始倒数
    do
    {
    temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
    SysTick->CTRL&=~0x01; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
    }

①将需要延时多少 us 的计数值加载到 SysTick 的 LOAD 寄存器中,fac_us
值是延时 1us 所需的计数值。
②清空当前计数值寄存器 VAL。
③打开 SysTick 定时器,定时器开始向下递减计数。
④CTRL 寄存器的第 16 位是 SysTick 递减到 0 的标志位,如果递减到 0,此
为置 1,通过读取该位来判断延时是否完成,从而退出 while 循环。
⑤关闭 SysTick 定时器。
⑥清空当前计数值寄存器 VAL。
delay_ms 函数代码如下:

/****************************************************************
***************
* 函 数 名 : delay_ms
* 函数功能 : ms 延时,
* 输 入 : nms:要延时的 ms 数
注意:nms 的值,SysTick->LOAD 为 24 位寄存器,
不要大于 0xffffff*8*1000/SYSCLK
对 72M 条件下,nms<=1864ms
* 输 出 : 无
*****************************************************************
**************/
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; // 时 间 加 载
(SysTick->LOAD 为 24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=0x01 ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~0x01; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}

此函数功能与 delay_us 基本一样,只不过这里是延时 ms。要注意的是,
SysTick 定 时 器 是 24 位 的 , 其 计 数 最 大 值 为 0xffffff , 时 间 为
nms<=0xffffff81000/SYSCLK,SYSCLK 是系统时钟为 72M,所以最大延时为
1864ms。如果需要延时大于 1.864S,可以调用多个 delay_ms 函数即可

你可能感兴趣的:(STM32)