当前位置:   article > 正文

SysTick——系统定时器(标准库)

系统定时器

1、STM32F4的SYSTick定时器

STM32F4系统定时器SYSTick是属于内核CM4的一个外设,内嵌在NVIC中。所有基于CM4的单片机都具有这个系统定时器,使得软件能够在CM4单片机中可以很容易的移植。

系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。

系统定时器是一个24bit的向下递减的计数器,计数器每计数一次的时间为1/SYSCLK。当重装载数值寄存器的值递减到0时,系统定时器就产生一个中断,以此循环往复。

2、SYSTick的寄存器

SYSTick系统定时器有四个寄存器。在使用SYSTick产生定时时,一般只需要配置前三个寄存器,最后一个校准寄存器不需要使用。

   CTRL              SYSTick控制及状态寄存器

   LOAD             SYSTick重装载数值寄存器

   VAL                 SYSTick当前数值寄存器

   CALIB             SYSTick校准数值寄存器

3、SYSTick配置库函数

(1)库函数解析

SYSTick是属于内核的外设,有关的寄存器定义和库函数都在内核相关的库文件core_cm4.h中。

__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks);

使用固件库编程的时候,我们只需要调用库函数SysTick_Config()即可。

        形参ticks用来设置重装载数值寄存器的值,最大值为2^24 = 16777216。

        返回值  0,设置成功    1,设置失败。

SysTick_Config()库函数主要配置了SYSTick中的三个寄存器:LOAD/VAL/CTRL。其中还调用了NVIC_SetPriority()来配置系统定时器的中断优先级。由于SYSTick属于内核外设,跟普通外设的中断优先级有区别,并没有抢占优先级和子优先级的说法。在STM32F407中,内核外设的中断优先级由内核SCB这个外设的寄存器:SHPPx(x = 1,2,3)来配置。在STM32F407中,只有高四位有效,中断优先级可编程为0~15,只有16个可编程优先级。

        标准库的函数原型:

  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
  2. {
  3. if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }
  4. /* Reload value impossible */
  5. SysTick->LOAD = (uint32_t)(ticks - 1UL);
  6. /* set reload register */
  7. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
  8. /* set Priority for Systick Interrupt */
  9. SysTick->VAL = 0UL;
  10. /* Load the SysTick Counter Value */
  11. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  12. SysTick_CTRL_TICKINT_Msk |
  13. SysTick_CTRL_ENABLE_Msk;
  14. /* Enable SysTick IRQ and SysTick Timer */
  15. return (0UL);
  16. /* Function successful */
  17. }

在系统定时器中,配置优先级为 (1UL « __NVIC_PRIO_BITS) - 1UL),其中宏 __NVIC_PRIO_BITS 为 4,那计算结果就等于 15,可以看出系统定时器此时设置的优先级在内核外设中是最低的。

  1.  #ifndef __NVIC_PRIO_BITS
  2.    #define __NVIC_PRIO_BITS         4
  3.    #warning "__NVIC_PRIO_BITS not defined in device header file; using default!"
  4.  #endif

SYSTick初始化函数由用户自己编写,里面调用了SysTick_Config()这个固件函数,通过设置该函数的形参,就决定了系统定时器经过多少时间就产生一次中断。

  1. void SysTick_Init(void)
  2. {
  3.    if(SysTick_Config(SystemCoreClock/100000)) //10us
  4.   {
  5.        while(1);
  6.   }
  7. }

(2)SYSTick相关计算

SYSTick中断时间计算

SYSTick定时器的计数器是向下递减计数的,计数一次时间 T = 1/AHBCLK

当重载寄存器中的值VALUE减到0的时候,产生中断。

中断一次的时间 T=VALUE/AHBCLK。

如果AHBCLK设置为168MHz,VALUE值设置为168,则中断时间为1us。

VALUE值设置为1680,则中断时间为10us.

VALUE值设置为168000,则中断时间为1ms。

  1. static __IO uint32_t TimingDelay;
  2. void systick_init(void)
  3. {
  4. //初始化SYSTick产生一次中断的时间
  5. while(SysTick_Config(168000)!=0);//1ms产生一次中断
  6. }
  7. //计时程序 nTime*1ms
  8. void Time_us(uint32_t nTime)
  9. {
  10. if(TimingDelay == 0)
  11. {
  12. TimingDelay = nTime;
  13. GPIO_ToggleBits(GPIOF,GPIO_Pin_9);
  14. }
  15. }
  16. //在 SysTick 中断函数 SysTick_Handler()进行计数
  17. void TimingDelay_Decrement(void)
  18. {
  19. if (TimingDelay != 0x00)
  20. {
  21. TimingDelay--;
  22. }
  23. }

3、注意事项

中断服务程序中修改的供其它程序检测的变量需要加volatile(即__IO)。

volatile(即__IO) 告诉编译器变量是随时可能发生变化的,每次使用它的时候必须从变量的地址中读取,因而编译器生成的可执行码会重新变量的地址读取数据。而如果没有使用__IO,编译器优化做法是,由于编译器发现两次从i中读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中,而不是重新从i里面读。

确定系统时钟配置的系统频率SYSCLK或HSECLK。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/942229
推荐阅读
相关标签
  

闽ICP备14008679号