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

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

[复制链接]
STMCU小助手 发布时间:2022-7-6 14:36
一、SysTick系统滴答定时器9 U1 `2 D" _/ ~. T9 Y
SysTick是一个24位定时器,属于Cortex-M4内核中的一个外设,类似NVIC。
; M3 B$ g/ J' t# ]" j/ s$ x$ ~7 k- O# X" H3 n3 I% u! B) F9 W) w
一个周期定时器,用于提供时间基准,多为操作系统所使用,常用于对时间要求严格的情况,意义是很重要的
5 ?; c( _2 m+ P4 y" ]6 d' U3 S" B6 F2 H$ H: q* P/ t- D* a0 E
SysTick定时器一次最多可以计数2^24(24bit)个时钟脉冲,这个脉冲计数值保存在当前计数值寄存器STK_VAL(Systick current value register)中,只能向下计数,也就是倒计数。
% W/ b9 r4 c$ s; q# u1 Y8 \
3 ~/ J" U8 R& b+ G3 M$ b1 j每接收到一个时钟脉冲(CPU主频),STK_VAL的值就会向下减1,当减到0时,硬件会自动将重装载寄存器STK_LOAD(可以设定,跟STK_VAL初始值相等)中保存的数值加载到STK_VAL,使其重新计数,并且,系统滴答定时器就产生一次中断,以此循环往复,只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息
  p0 m" T- ]/ f2 t9 ~0 b. Z) H9 o. j8 e: K! }
Systick相关寄存器
, M/ R; |/ U# t& q. z" `. G$ r5 r4 m2 \# z3 E
6G)86_27MR1RGKTB$)WLQHF.png 1 M$ E1 Z5 F: Q0 O: e/ g$ s" O
~KI21TGVTKZ87`6~PA3ZZSO.png
$ _/ o* l+ P+ \  d3 y6 z# }' J7 e
* f5 d2 n; T% x8 P* O- O若VAL中的数值为 80,脉冲频率为 80MHz,则VAL由 80 减到 0 所需要的时间为80/80MHz=1us,并且当减到 0 时会触发中断(相当于 1us 定时器),同时 LOAD 的值也会重新载入到VAL中
4 i( Z- Q% p% v, I! D0 T# d
" f4 X; h+ x" P% y9 a8 [STM32CubeMX系统时钟的配置
0 ~' |. l3 J5 b5 F: z( L! C1 ~8 ]/ @

! s* M$ S* d" b. r$ L, u在 STM32CubeMX 中配置好时钟树后,时钟频率会输入到 Cortex System timer内核时钟 。所以, SysTick 的脉冲频率来自于此% c* f8 e4 d, Y9 T) a

# o+ k( ^" ~9 S8 v; b6 T0 Y: r7 J* ~9 E二、SysTick系统定时器原理
8 S( z. |- S0 T0 W; r8 h在HAL_Init()(HAL_Init–>HAL_InitTick–>HAL_SYSTICK_Config–>SysTick_Config) 使用SysTick作为时基源,并配置1ms定时(重置后的默认时钟为 HSI)。但是 HSI 为内部时钟,而我们使用的是外部时钟,这里的1ms定时是不精准的
* z. y) R3 I4 R' V, z; E+ v7 s. D) k
  1. /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is HSI) */
    ( L) ^" [2 \% [5 g) U! \
  2.   if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)5 |6 @! `+ q* Z
  3.   {! C% l9 a" L; B* u3 D% V7 X6 O
  4.     status = HAL_ERROR;
    5 c7 I- M; a" v6 `' f' c" Z
  5.   }
复制代码
7 w& @7 U3 z+ e+ ]$ }1 K* ~
精准的1ms定时在系统定时器配置函数SysTick_Config() 在core_cm4.h头文件里面" O9 @7 x/ y. K+ m

! b' @" e0 A0 ]2 ^
  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
    5 T7 k+ Y0 W, e; r! O
  2. {
    6 R$ L2 _  ?: G" E- m# H
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
    / d6 w7 X; ?3 R6 _5 |
  4.   {; e, o7 v) z' [. P7 Q6 U
  5.     return (1UL);                                                   /* Reload value impossible */
    2 D, S+ k1 L. v8 }! T& Q
  6.   }
    6 `$ J8 f  B  B" d6 ]$ T

  7. ( Y8 y* H' R2 \& g5 V. y
  8.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
    # N; [: `1 H+ x* ]
  9.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */( |. l: C0 R4 X9 [
  10.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
    9 h0 P, [; W8 c  U' o6 X! C
  11.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
    ' c8 q1 B* ~2 ?% K" s9 o% G8 Z
  12.                    SysTick_CTRL_TICKINT_Msk   |
    4 G, R) Y. @7 Z
  13.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
    2 E$ V8 A. s" [6 u* W
  14.   return (0UL);                                                     /* Function successful */
    # h5 n2 y0 `5 N
  15. }
复制代码
, p& m+ r6 W) p! o% h
在这个函数里面进行对系统定时器的寄存器进行配置  I2 T% [& C7 `$ q. \

& M! ], v5 x1 w9 G' D系统滴答定时器中断服务函数:每隔1ms进入该服务函数+ B' Y3 Z3 y4 o% K7 O" \

+ }0 D) D& C2 Y; r- s7 m5 d$ y注:SysTick系统滴答定时器每1ms产生中断
, H. h  b- P- p7 g5 C8 K( G) n# ?0 [) M* G: \; A' Z
  1. /**- b# C, a! M  ?. B% I5 \
  2.   * @brief This function handles System tick timer.' H$ x8 t+ A. W, d( X% _
  3.   */
    % K9 X8 M, p1 P/ N* N; r1 q
  4. void SysTick_Handler(void)
    : P2 X& `, W4 F3 D4 H6 f* L7 C
  5. {
    3 o) }8 I, T/ y. T- ~2 ~& X
  6.   /* USER CODE BEGIN SysTick_IRQn 0 */9 g3 p8 C" q8 k) L% \8 O& u7 @

  7. ( N% e0 C# Y. L
  8.   /* USER CODE END SysTick_IRQn 0 */  }( s. w! Q$ `% P' x
  9.   HAL_IncTick();
    3 C0 V; v6 S$ O8 |7 d- z+ I
  10.   /* USER CODE BEGIN SysTick_IRQn 1 */% B8 J- [- R" D4 |5 m: V. ?  h+ Q
  11. ; ~( e6 O% ?: a$ j4 u0 r- @
  12.   /* USER CODE END SysTick_IRQn 1 */
    . h# K' Q+ y, |4 r) U
  13. }8 J9 ^  i6 L- \
  14. 5 i  f5 \* k5 O& E" t
  15. __weak void HAL_IncTick(void)
    - ?0 f9 ?& ^; B3 \' r
  16. {
    - A- D7 i3 |1 d& E0 t' u
  17.   uwTick += uwTickFreq; // uwTickFreq = 1" `1 f$ I5 v# ?" `
  18. }
    8 k$ Q6 f8 j4 T7 |: A! d
  19. __IO uint32_t uwTick;' ?, L6 {$ @) F; }
  20. uint32_t uwTickFreq = HAL_TICK_FREQ_DEFAULT;  /* 1K<span style="background-color: rgb(255, 255, 255);">Hz */</span>
复制代码

9 u+ M. I$ b$ G- {0 f1 e+ U在中断服务函数中 uwTick 会每1ms加1, 一直循环,直到溢出达到232(大约要一直运行40几天)( b9 J4 [5 `% ]1 u6 e4 F. s. o7 U6 c

0 M. Y# h0 D2 _  d, duwTick一般用于计数或者延时函数(HAL_Delay(). e3 }6 Z. k, s' V

3 e# ~" Q+ r  A) m  q9 z5 K2 |5 H
  1. __weak void HAL_Delay(uint32_t Delay)
    / E! P: c, O8 R" ?+ D" n
  2. {
    # J/ e( ]& ]1 l5 Q& S4 N
  3.   uint32_t tickstart = HAL_GetTick();
    ( ~" ~* r1 n3 @  L5 F- {  X
  4.   uint32_t wait = Delay;: i* u3 L5 }9 N: x* D
  5. / \! ?$ W& C9 k3 X
  6.   /* Add a freq to guarantee minimum wait */1 V: R$ B, {/ k8 {3 U
  7.   if (wait < HAL_MAX_DELAY)) H- W* C5 F* w2 k" I( u
  8.   {+ \$ G$ `4 c- U# ?* |! N: S: u
  9.     wait += (uint32_t)(uwTickFreq);
    ( k' r+ }2 _4 R7 M6 F$ e
  10.   }: e- _2 z4 N4 L5 T
  11. 1 P5 F( g7 L* l& o% Z
  12.   while ((HAL_GetTick() - tickstart) < wait)9 t* o) G' B& O' ^, b  Z) c  G) ]& ~
  13.   {
    7 _& n$ i* ?# F% G; A
  14.   }) }* d2 ^& V! {- c4 \9 K0 P2 S
  15. }
    ! O2 ?: j& ~; C2 ^9 D" ]
  16. ! i: J* S2 H8 D
  17. __weak uint32_t HAL_GetTick(void)
    ( w9 ~2 ]2 c' n$ T' d0 |0 l
  18. {
    / a8 Y2 ~4 w1 W$ A  \. F
  19.   return uwTick;
    % K7 H  I; Y& o4 e: N
  20. }
复制代码

) f0 {, Z: I! l8 QHAL_GetTick获取当前uwTick,若传入参数500,tickstart 为 HAL_GetTick() 最初的值(即进入延时时uwTick的值),固定不变。, h  O" l8 s8 a# U! N
HAL_GetTick() 与 tickstart 的差值若小于用户定义的500,则继续循环等待;若超过500,则跳出循环(即跳出HAL_Delay() ),延时结束
5 v% f0 d3 \! w5 t+ n/ x1 h, Z0 \; a: ]
总结9 Q% T- _6 m3 q1 g5 C5 Z( X
提示:这里对文章进行总结:1 ]" D# q4 u3 Z% a9 P
0 T; p. c% u7 ?& C5 J+ i% j
Systick的两大作用:
4 Q7 _6 p) f+ e$ @5 L1 B, s9 d1、可以产生精确的延时(HAL_Delay())
& K6 k9 E( w9 d! L7 `2、可以提供给操作系统一个单独的心跳(时钟)节拍(操作系统时基)
/ |3 k1 S! `7 z( W
' n, a7 U4 h( e$ T! V: w! w8 [
, w) F# f* r! j' M' p0 I1 R) S+ m$ X8 t' k& I5 V9 e
收藏 评论0 发布时间:2022-7-6 14:36

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版