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

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

[复制链接]
STMCU小助手 发布时间:2022-7-6 14:36
一、SysTick系统滴答定时器+ R6 ~5 k, W% D( @3 Y/ O9 @
SysTick是一个24位定时器,属于Cortex-M4内核中的一个外设,类似NVIC。6 w; ]5 }' G- Z% Z
+ s  g9 x  a& n* k. h
一个周期定时器,用于提供时间基准,多为操作系统所使用,常用于对时间要求严格的情况,意义是很重要的
7 V. l. O" \1 s4 N! a) E$ w: o4 t
SysTick定时器一次最多可以计数2^24(24bit)个时钟脉冲,这个脉冲计数值保存在当前计数值寄存器STK_VAL(Systick current value register)中,只能向下计数,也就是倒计数。" G9 d: h, K1 r9 M1 ]' E( r( l
& @7 P& J$ y+ r
每接收到一个时钟脉冲(CPU主频),STK_VAL的值就会向下减1,当减到0时,硬件会自动将重装载寄存器STK_LOAD(可以设定,跟STK_VAL初始值相等)中保存的数值加载到STK_VAL,使其重新计数,并且,系统滴答定时器就产生一次中断,以此循环往复,只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息
& q, f, a4 E% R: l1 E
$ F' V7 M3 ?& c! Z3 Y5 cSystick相关寄存器
+ v+ s; K. B! [" Y9 p+ _5 n6 G# M' `
6G)86_27MR1RGKTB$)WLQHF.png / a4 Y3 E0 R3 N8 d* i5 |6 l
~KI21TGVTKZ87`6~PA3ZZSO.png
# e% [$ P* {1 }4 F4 d, h# l+ C# Z3 k, J" ?1 }$ U3 h( ]
若VAL中的数值为 80,脉冲频率为 80MHz,则VAL由 80 减到 0 所需要的时间为80/80MHz=1us,并且当减到 0 时会触发中断(相当于 1us 定时器),同时 LOAD 的值也会重新载入到VAL中
% B, G, u5 t. s2 D/ x# ^7 c& ^5 l- @
( I: D! n. j8 t+ ]STM32CubeMX系统时钟的配置' c. R! J# N  w* u% U( a8 S

3 ^- C6 h+ w0 N
( H% C+ c- h' {( t& i; P) x在 STM32CubeMX 中配置好时钟树后,时钟频率会输入到 Cortex System timer内核时钟 。所以, SysTick 的脉冲频率来自于此0 {* }% {1 V6 v5 O' m3 B

& G+ ?( j9 q/ m; T9 ^- H二、SysTick系统定时器原理
1 M2 ]- E  ]; x1 e5 q/ i; c在HAL_Init()(HAL_Init–>HAL_InitTick–>HAL_SYSTICK_Config–>SysTick_Config) 使用SysTick作为时基源,并配置1ms定时(重置后的默认时钟为 HSI)。但是 HSI 为内部时钟,而我们使用的是外部时钟,这里的1ms定时是不精准的& i! Y: v- T" S$ t" ^. F/ D9 z
6 K- o- k* n% \2 @/ m! b$ j& }
  1. /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is HSI) */
    " i+ ~, K; q/ j
  2.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
    6 z( s) i: M8 N% T; T
  3.   {
    * Y$ x! X( g% \9 f
  4.     status = HAL_ERROR;
    * x8 J% O7 _7 J9 g1 d1 S
  5.   }
复制代码

- n: }' l  u5 v精准的1ms定时在系统定时器配置函数SysTick_Config() 在core_cm4.h头文件里面" O, M0 q1 R: K

; s5 H$ Q- J" q2 k  j7 L9 L( a
  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)5 b/ M( B) W" i1 `1 P
  2. {; h5 a3 Z: r0 i8 }9 `
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)1 c* I1 V. M  [7 j0 V& i" \; J
  4.   {2 t/ }6 R" G) v; G8 e$ Y( Z& k8 L  p7 q
  5.     return (1UL);                                                   /* Reload value impossible */7 j/ M; N7 _9 ~0 s& _
  6.   }
    ' X  c; d& E+ c* p' ?1 t5 S
  7. . S4 m5 l% P6 V3 e
  8.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */6 D6 p6 W' ]. k! W5 a
  9.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
    " w1 B' E2 c4 w) z: @: u# p
  10.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
    6 ?9 p/ M0 v1 L3 {( a3 B& {+ O2 @
  11.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
    : ~0 T- ^- V  z5 {5 {; J
  12.                    SysTick_CTRL_TICKINT_Msk   |% ]: i5 H$ `, a
  13.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */, ^) n& C/ f: J4 P6 L: I6 ~  T
  14.   return (0UL);                                                     /* Function successful */0 z; P. ^  z/ _( K
  15. }
复制代码

& T: \1 v# h, V) m在这个函数里面进行对系统定时器的寄存器进行配置
9 v5 B5 i. S* A7 m/ ?1 R6 c
! m! w9 M0 F; g) d- O, L. Y  W系统滴答定时器中断服务函数:每隔1ms进入该服务函数
  T1 t/ g1 E5 G7 v5 {3 g, X5 x
8 a+ ?# t+ s" [) M. G6 W8 b注:SysTick系统滴答定时器每1ms产生中断1 R- k7 _1 Q7 V% g2 F( ?- _; C

4 I; c! @) P/ {$ I5 l7 E1 I6 q
  1. /**
    ' W; J1 z' g+ h) r6 M! t
  2.   * @brief This function handles System tick timer.
    ! J+ E! V2 ~- q& J; o/ N6 Q% @$ |
  3.   */0 C  K/ G8 O! u+ v
  4. void SysTick_Handler(void)5 Z; r" S6 _& M! k8 Q& C
  5. {( Q1 Z. c9 d* J* j4 I, d
  6.   /* USER CODE BEGIN SysTick_IRQn 0 */
    : S% f/ J' J( [: ^6 X+ N
  7. / C6 |9 p1 R" \, P, r- y6 q1 A
  8.   /* USER CODE END SysTick_IRQn 0 */! Z4 R; N0 Z. @/ A; q
  9.   HAL_IncTick();
      y8 c) k6 P! i! `1 T; M/ I& e! \
  10.   /* USER CODE BEGIN SysTick_IRQn 1 *// ?: q* ~/ Y4 e6 h: b3 s2 D. \

  11. 4 _. C7 M: t+ a: x3 H, \1 t
  12.   /* USER CODE END SysTick_IRQn 1 */7 g& U5 R' `9 Y, f# c5 @
  13. }$ S( I! g+ c* s, v

  14. ( T1 x7 g1 e# I% b; m6 ]9 e: ]1 z
  15. __weak void HAL_IncTick(void)
    / T+ x) `9 F5 H, i$ H
  16. {
    1 k+ w. }3 b( u: g( v8 {" m) A+ h. h
  17.   uwTick += uwTickFreq; // uwTickFreq = 1
    % V9 `8 n; w' K. l5 E
  18. }8 P" C, l6 H* c
  19. __IO uint32_t uwTick;& g9 }' S3 |" {  {
  20. uint32_t uwTickFreq = HAL_TICK_FREQ_DEFAULT;  /* 1K<span style="background-color: rgb(255, 255, 255);">Hz */</span>
复制代码
0 o. p1 c  n* J, h
在中断服务函数中 uwTick 会每1ms加1, 一直循环,直到溢出达到232(大约要一直运行40几天)
7 p8 Y; C5 k  a3 @
; C8 \4 G9 i) ~uwTick一般用于计数或者延时函数(HAL_Delay()& B0 i$ H" m! i  _0 `( K

; R% s' [$ N% P, e, {
  1. __weak void HAL_Delay(uint32_t Delay)% ?* _' G: G) D  x5 h8 O; ^
  2. {
    % v0 d% @: R" H4 S7 a" Q, ]
  3.   uint32_t tickstart = HAL_GetTick();$ r. L$ k9 c$ E5 U: N" z
  4.   uint32_t wait = Delay;
    ' W) X7 k% R1 E  E6 Z1 E- |

  5. 6 T( E- I/ r' Y* b5 z5 x7 a  y
  6.   /* Add a freq to guarantee minimum wait */  f4 b/ v+ |7 f  Y) O- j
  7.   if (wait < HAL_MAX_DELAY)
    9 t5 _7 q6 g3 c5 Y; h
  8.   {4 T7 i2 t+ |* }! R2 X
  9.     wait += (uint32_t)(uwTickFreq);
    % m! u5 d  t- ~9 V  u
  10.   }
    ) H/ O4 q+ V' f! q8 O
  11. ( C8 L6 j2 p( L$ R+ V
  12.   while ((HAL_GetTick() - tickstart) < wait)
    " y8 a& U( A( C+ \' ~2 O1 x
  13.   {
    : }. q3 o3 L5 J9 H
  14.   }
    # B- s6 j" ^& A7 I. L- w# E
  15. }
    ! c! H" l2 t  e9 j# k7 K
  16. * q- r- q$ J, W; Z
  17. __weak uint32_t HAL_GetTick(void)! Y0 y5 }7 @; k* ?( b
  18. {
    , I; L) W  E& l
  19.   return uwTick;: d: {! e/ Y5 U: }6 f5 `
  20. }
复制代码

+ G: ]5 o# n" B; IHAL_GetTick获取当前uwTick,若传入参数500,tickstart 为 HAL_GetTick() 最初的值(即进入延时时uwTick的值),固定不变。
5 {1 X4 `0 a% e6 s: fHAL_GetTick() 与 tickstart 的差值若小于用户定义的500,则继续循环等待;若超过500,则跳出循环(即跳出HAL_Delay() ),延时结束  E/ o: D  v/ j4 M7 Q

& _- D7 R4 H# F' Q+ q1 T总结
/ O5 g. g* c1 [2 ?2 Z提示:这里对文章进行总结:: ?# D+ F- g' K2 i9 ?, Z! k# C
& W2 e+ l0 z1 x+ D& j
Systick的两大作用:
: |& ?4 v' W8 M1 b1、可以产生精确的延时(HAL_Delay())
3 K; S. ^7 t* P( W8 y5 l% M: B; M2、可以提供给操作系统一个单独的心跳(时钟)节拍(操作系统时基)
) E( B  d4 O5 b' O, M% ]4 g9 k6 r
* {3 J' S' `9 b1 L- O& S
" B! r# w# y: a
* D8 h/ ]. R8 W# m4 F% y+ ^
收藏 评论0 发布时间:2022-7-6 14:36

举报

0个回答

所属标签

相似分享

官网相关资源

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