你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32G4之SysTick系统时钟

[复制链接]
STMCU小助手 发布时间:2022-7-6 14:36
一、SysTick系统滴答定时器
SysTick是一个24位定时器,属于Cortex-M4内核中的一个外设,类似NVIC。

一个周期定时器,用于提供时间基准,多为操作系统所使用,常用于对时间要求严格的情况,意义是很重要的

SysTick定时器一次最多可以计数2^24(24bit)个时钟脉冲,这个脉冲计数值保存在当前计数值寄存器STK_VAL(Systick current value register)中,只能向下计数,也就是倒计数。

每接收到一个时钟脉冲(CPU主频),STK_VAL的值就会向下减1,当减到0时,硬件会自动将重装载寄存器STK_LOAD(可以设定,跟STK_VAL初始值相等)中保存的数值加载到STK_VAL,使其重新计数,并且,系统滴答定时器就产生一次中断,以此循环往复,只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息

Systick相关寄存器

6G)86_27MR1RGKTB$)WLQHF.png
~KI21TGVTKZ87`6~PA3ZZSO.png

若VAL中的数值为 80,脉冲频率为 80MHz,则VAL由 80 减到 0 所需要的时间为80/80MHz=1us,并且当减到 0 时会触发中断(相当于 1us 定时器),同时 LOAD 的值也会重新载入到VAL中

STM32CubeMX系统时钟的配置


在 STM32CubeMX 中配置好时钟树后,时钟频率会输入到 Cortex System timer内核时钟 。所以, SysTick 的脉冲频率来自于此

二、SysTick系统定时器原理
在HAL_Init()(HAL_Init–>HAL_InitTick–>HAL_SYSTICK_Config–>SysTick_Config) 使用SysTick作为时基源,并配置1ms定时(重置后的默认时钟为 HSI)。但是 HSI 为内部时钟,而我们使用的是外部时钟,这里的1ms定时是不精准的

  1. /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  2.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
  3.   {
  4.     status = HAL_ERROR;
  5.   }
复制代码

精准的1ms定时在系统定时器配置函数SysTick_Config() 在core_cm4.h头文件里面

  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
  2. {
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
  4.   {
  5.     return (1UL);                                                   /* Reload value impossible */
  6.   }

  7.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
  8.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
  9.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
  10.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
  11.                    SysTick_CTRL_TICKINT_Msk   |
  12.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
  13.   return (0UL);                                                     /* Function successful */
  14. }
复制代码

在这个函数里面进行对系统定时器的寄存器进行配置

系统滴答定时器中断服务函数:每隔1ms进入该服务函数

注:SysTick系统滴答定时器每1ms产生中断

  1. /**
  2.   * @brief This function handles System tick timer.
  3.   */
  4. void SysTick_Handler(void)
  5. {
  6.   /* USER CODE BEGIN SysTick_IRQn 0 */

  7.   /* USER CODE END SysTick_IRQn 0 */
  8.   HAL_IncTick();
  9.   /* USER CODE BEGIN SysTick_IRQn 1 */

  10.   /* USER CODE END SysTick_IRQn 1 */
  11. }

  12. __weak void HAL_IncTick(void)
  13. {
  14.   uwTick += uwTickFreq; // uwTickFreq = 1
  15. }
  16. __IO uint32_t uwTick;
  17. uint32_t uwTickFreq = HAL_TICK_FREQ_DEFAULT;  /* 1K<span style="background-color: rgb(255, 255, 255);">Hz */</span>
复制代码

在中断服务函数中 uwTick 会每1ms加1, 一直循环,直到溢出达到232(大约要一直运行40几天)

uwTick一般用于计数或者延时函数(HAL_Delay()

  1. __weak void HAL_Delay(uint32_t Delay)
  2. {
  3.   uint32_t tickstart = HAL_GetTick();
  4.   uint32_t wait = Delay;

  5.   /* Add a freq to guarantee minimum wait */
  6.   if (wait < HAL_MAX_DELAY)
  7.   {
  8.     wait += (uint32_t)(uwTickFreq);
  9.   }

  10.   while ((HAL_GetTick() - tickstart) < wait)
  11.   {
  12.   }
  13. }

  14. __weak uint32_t HAL_GetTick(void)
  15. {
  16.   return uwTick;
  17. }
复制代码

HAL_GetTick获取当前uwTick,若传入参数500,tickstart 为 HAL_GetTick() 最初的值(即进入延时时uwTick的值),固定不变。
HAL_GetTick() 与 tickstart 的差值若小于用户定义的500,则继续循环等待;若超过500,则跳出循环(即跳出HAL_Delay() ),延时结束

总结
提示:这里对文章进行总结:

Systick的两大作用:
1、可以产生精确的延时(HAL_Delay())
2、可以提供给操作系统一个单独的心跳(时钟)节拍(操作系统时基)



收藏 评论0 发布时间:2022-7-6 14:36

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版