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

【经验分享】STM32 SysTick定时器

[复制链接]
STMCU小助手 发布时间:2022-6-11 21:08
01. SysTick定时器概述
" J; w3 w9 ?. ~& a2 e# TSysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。: e0 j$ G, t- y* F# j
6 m% ~0 |4 [0 Y, Y1 X$ h5 @
Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
3 C  Z' j( q4 ~7 ?% H7 E! W7 E
2 U4 r  U* H$ I# W" ]  A7 O02. SysTick定时器寄存器描述
# p; g$ ]2 c/ F6 S( [& f0 T& ^SysTick控制及状态寄存器(地址:0xE000_E010)! M# f) I* q5 ^" a' W: }) g

8 {5 d! V9 q: ^1 e XOXG[EB1]FJW]D{{5V)0BPL.png
: G+ O' W4 _: m9 V& Y0 R" Y6 t! k
$ }! |. d1 a# `) T8 V8 N4 _SysTick重装载数值寄存器(地址:0xE000_E014); v0 c8 L0 w! T4 O. ?
/ [) E# n5 M( W
20200830102443823.png % m* V' _" o$ S" G
: h$ M8 E2 J. W
SysTick当前数值寄存器(地址:0xE000_E018)
) ?, o- J. j4 U, [- _0 o. P% }
7 |8 |( F0 s2 i) p3 _) l9 p7 X0 X7 r 20200830102451227.png
2 Y4 _7 Q3 ~- v9 s) ?& m8 I7 j( o6 I* B+ U! E$ G
SysTick校准数值寄存器(地址:0xE000_E01C)
* n8 \/ n4 j2 z. i$ R
0 _# q# U+ u  p$ c( O/ D8 A4 P! J VY_K(VW~3_EQM2O6IILW7I7.png 5 I( |: r5 N  |) F4 G3 _% F
- _# w4 z. [" w2 ], u* d
03. 相关函数实现" J, F" ~5 d% m9 `" u9 B+ p4 ^
core_cm4.h文件& o% R+ Y/ f# d
2 S# j4 ^3 ]6 s/ a: C
  1. /** \brief  System Tick Configuration3 k& n, h1 b0 h7 L' _  C7 U

  2. " `4 q7 f* v) I1 w4 f3 ]' S
  3.     The function initializes the System Timer and its interrupt, and starts the System Tick Timer.& i! Q0 j* H. ^& ^9 n
  4.     Counter is in free running mode to generate periodic interrupts.
    3 A/ G, N/ g( e& s, n6 Z

  5. 7 H1 m4 d6 T- U4 X* }; a6 [* F9 |& ~
  6.     \param [in]  ticks  Number of ticks between two interrupts.
      K: O2 u0 ^4 T2 d* w
  7. # ^( D% C0 @$ V' }: |
  8.     \return          0  Function succeeded.
    ! u2 h) \% S( `% D
  9.     \return          1  Function failed.
    + b4 K% D. a0 p7 i' Y0 B1 w

  10. 2 l& I( y) U2 T; t
  11.     \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
    8 ]# ]# K6 Y% ~
  12.     function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>+ [) _2 Y3 c3 E, n+ I
  13.     must contain a vendor-specific implementation of this function.5 {1 s8 y7 i" F1 h

  14. , G3 C  ?" s. m% b
  15. */3 d+ Y$ w5 \+ @, A
  16. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
    * S8 x( h$ c) j) ]
  17. {+ N  F8 u% l8 A
  18.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    /* Reload value impossible */1 k: d: ]/ S+ v/ {
  19. " v: q2 @" B) U3 W$ N2 M. \1 ?
  20.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */; l. Q* }! U0 w' M7 x
  21.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */9 Q3 j/ Y2 Z4 \$ m- q" I8 X
  22.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */0 q2 d8 g; W( f" O+ `* s
  23.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |, x+ T; b8 v) d3 \
  24.                    SysTick_CTRL_TICKINT_Msk   |/ Y' B# W9 ~( n1 X+ _
  25.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
    " x1 |" g' g& {; R
  26.   return (0UL);                                                     /* Function successful */- J* d; p0 f/ P( u; j$ @- M
  27. }
复制代码

# A1 x' G( u" C: Zmisc.c文件
8 v# t1 P( i, L- `% @: _3 t  F- o/ R2 b& A+ g
  1. /**( B9 i( a: t! l  |4 f- Q* y6 M0 s
  2.   * @brief  Configures the SysTick clock source.
    ! _+ y4 e1 @$ @) e* a0 Y
  3.   * @param  SysTick_CLKSource: specifies the SysTick clock source.5 v$ K/ E5 k9 u
  4.   *   This parameter can be one of the following values:* m1 C3 K/ K& \: ~: b* K" v
  5.   *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.) O. t' B0 b8 \" m- ?; I3 r
  6.   *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source., N* y+ j6 B/ G4 K
  7.   * @retval None
    4 W- s7 D$ A6 ^! w' _
  8.   */! T7 T2 s  R' B" H: D- a( b4 g
  9. void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)4 R9 C* [& Y: k/ u
  10. {$ R7 `# _3 ]/ O. Z, `4 A( j
  11.   /* Check the parameters */
    * I3 k0 `  e0 J
  12.   assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));# w9 n& {& a( ]& S0 R' \0 E+ Z/ ?* z
  13.   if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
    ! O5 g) F6 K% P5 V$ p: q2 A
  14.   {" S; M4 A) R! d- N6 k0 B" r
  15.     SysTick->CTRL |= SysTick_CLKSource_HCLK;
    % L3 V( b9 S- D. N. C
  16.   }
      W/ A, F, C! K' ]+ A6 ~/ m
  17.   else
    3 q* Z& n) I0 v& G
  18.   {8 W$ F0 A4 k7 N9 d9 y- N
  19.     SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;0 C( d! N; a9 c) j
  20.   }/ j1 t1 s& [/ B/ N! l
  21. }
复制代码
: c: e" U" _3 A3 o
04. 延时函数实现. Y) Q9 Y& D' n8 [
delay.h文件
" O& u& S) t8 ~  }1 L( I2 k) M: c; }3 |8 }; w) l
  1. #ifndef __DELAY_H' a# ]8 b6 P; N; Z
  2. #define __DELAY_H                            # `# }# q# p* r0 E% b
  3. #include <sys.h>         
    $ [0 x2 ^. o" p% Y  a
  4. & R/ [8 @6 V- I: ^5 L; ]' h7 c
  5. void delay_init(u8 SYSCLK);. W4 j. F! O3 q, k2 q$ I
  6. void delay_ms(u16 nms);& G: r  Q( g' Z' p( A
  7. void delay_us(u32 nus);' m- \  f9 r$ t; h3 ]  M4 V. _

  8. " s2 H5 D5 S, M( K
  9. #endif
复制代码

2 D# B1 ~# o& u' G6 [9 odelay.c文件) q1 t" j# H' _9 L
+ t4 p! w) t9 I/ e( \5 @
  1. static u8  fac_us=0;                                                        //us延时倍乘数                           3 o2 @% E& f7 B7 g
  2. static u16 fac_ms=0;                                                        //ms延时倍乘数,在os下,代表每个节拍的ms数
    0 |; ]/ [( T  t- X: n0 L/ b

  3. # H+ |. x1 h5 [; b# f
  4. //初始化延迟函数2 z# s9 {0 o3 K4 C! j6 ]
  5. //当使用OS的时候,此函数会初始化OS的时钟节拍4 i$ u) s3 A1 h: n
  6. //SYSTICK的时钟固定为AHB时钟的1/8
    ! B% w7 b  P) n" t$ ]' y# L0 r
  7. //SYSCLK:系统时钟频率
    & w% e, \& ^! z" a# W5 g- F% p8 r
  8. void delay_init(u8 SYSCLK)
    6 Q9 q4 j# W! y8 r# N) }% j
  9. {
    5 C/ ]2 V* w: F

  10. 0 c1 B4 u# |6 P, x9 v" E: J* C
  11.          SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    : ?- m- `0 c: ]2 N
  12.         fac_us=SYSCLK/8;                                                //不论是否使用OS,fac_us都需要使用7 t& p% H% ~% g/ {& P

  13. % Q1 l- N6 {' E4 L- |
  14.         fac_ms=(u16)fac_us*1000;                                //非OS下,代表每个ms需要的systick时钟数   0 e$ h( f( y! v- I0 M" w
  15. }                $ o8 c% Y: X4 k. v8 Y2 O

  16. 8 j" x3 w- {, c6 [, X
  17. //延时nus
    - {1 C! `0 E# |4 g6 z- n
  18. //nus为要延时的us数.        4 {8 m- r1 o0 O1 m2 D, }
  19. //注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)$ m; d8 ~$ D: E  s# o( c1 @
  20. void delay_us(u32 nus)
    / ~: X! w- ^! |& r4 {: Q4 @9 Z% P
  21. {                / w. a. I- j* B" o
  22.         u32 temp;                     % M. ~( m0 W7 t  @' @. @
  23.         SysTick->LOAD=nus*fac_us;                                 //时间加载                           
    7 r( [* _' k% y) P
  24.         SysTick->VAL=0x00;                                        //清空计数器  h" Y* z: n" z* U3 Z
  25.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数          : X$ i" m8 K2 i, \1 \. D
  26.         do2 V: l/ `& o1 T
  27.         {# R* ~0 h5 C" o" c$ A  i# ?4 S* _
  28.                 temp=SysTick->CTRL;8 {! |: K7 `1 N8 L8 |9 \
  29.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   ; O6 U# u  p! `+ W$ V
  30.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
    6 B: C+ P2 J8 W  D1 U: H
  31.         SysTick->VAL =0X00;                                       //清空计数器 4 k! t1 U' ?; g1 T, I- X
  32. }: b! y4 ^. X7 q% C7 g% H% Y

  33. . C8 S$ @, ]: G' p2 P  v* s5 `
  34. //延时nms
    . p/ r' M( C8 ?. Y1 @" Q! U" x
  35. //注意nms的范围* S$ T7 p9 v- d6 _( W' _
  36. //SysTick->LOAD为24位寄存器,所以,最大延时为:
    # o# l: b' ?+ e9 _& T6 z
  37. //nms<=0xffffff*8*1000/SYSCLK( M" ^/ p, h4 E. b
  38. //SYSCLK单位为Hz,nms单位为ms
    % \! N, D. A6 s# A; A6 j8 v
  39. //对168M条件下,nms<=798ms $ ~' |2 A' m2 j& ?$ |/ O2 T5 L& t
  40. void delay_xms(u16 nms)
    7 I* p$ o+ s. {! g
  41. {                                     3 Z+ K% C1 ?' n) G
  42.         u32 temp;                  
    5 Q0 h9 ^, V2 U$ a
  43.         SysTick->LOAD=(u32)nms*fac_ms;                        //时间加载(SysTick->LOAD为24bit)
    ( J/ S$ a, e+ _) }7 o; t
  44.         SysTick->VAL =0x00;                                   //清空计数器! f! v) S' A; J
  45.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数
    4 t5 `- U, X5 C' f7 c9 y) V# e6 {( o
  46.         do
    7 a3 D$ a0 m0 o5 p7 z3 }2 o6 P; f6 F* d
  47.         {
    & \9 P+ e: c5 I4 H. E# p- ~, C3 o
  48.                 temp=SysTick->CTRL;' Z% j/ y( a! @1 r
  49.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
    , t" p  j0 L" i# y; K
  50.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器3 k* g$ M9 A& d: F" e
  51.         SysTick->VAL =0X00;                                       //清空计数器                     
    0 a( E. n" S) _5 M( a3 V
  52. } 6 i! [8 E  D% i# U

  53.   U( }5 {+ q0 k% w" i2 I. O# Z9 M: F
  54. //延时nms 4 U% u0 j$ u5 s' K$ G) {8 M1 `2 k
  55. //nms:0~65535
    5 v+ V& w0 p( t% R6 N( L$ I+ h
  56. void delay_ms(u16 nms)( |* X* S6 ^7 P, W: B, N
  57. {                  
    ; a9 X% ^; K9 }9 Z" @0 z8 p5 w
  58.         u8 repeat=nms/540;                                                //这里用540,是考虑到某些客户可能超频使用,+ N/ F) Y* N9 A
  59.                                                                                         //比如超频到248M的时候,delay_xms最大只能延时541ms左右了
    $ C$ \" w( P& X+ v; R1 J4 K4 P
  60.         u16 remain=nms%540;7 _! Z* Q6 @4 a) I9 X( Q
  61.         while(repeat)" h  c9 X* }0 u0 u7 x: z
  62.         {% i( M8 ^3 K2 ~2 Z% s& q/ j
  63.                 delay_xms(540);  {) D/ j# ^( ^. n2 ~6 `
  64.                 repeat--;- x7 k" ]8 ^; k/ X8 ]$ _
  65.         }
    : W, I! i" h% O
  66.         if(remain)delay_xms(remain);2 A4 c4 T7 Z9 \
  67. }
复制代码
  ~" Z$ E' l( F3 F9 R( `
05. 应用示例& V" P( p+ q: L8 j" O0 q
用中断的方式实现delay延时7 m  }- e: X- T% D
+ @4 P/ m8 ]/ M3 O
  1. static __IO uint32_t TimingDelay;: A" h5 @+ K0 n. \7 G
  2. void Delay(__IO uint32_t nTime)
    / L+ X3 R  H3 o. A& G  [
  3. { & m' ^( s1 J0 e/ z
  4.    TimingDelay = nTime;6 X$ T0 I1 q9 y8 l1 Z5 p+ v
  5.    while(TimingDelay != 0);' Y( S- v" @7 N6 `2 M; j
  6. }
    " U/ m% Z- p8 d0 x
  7. void SysTick_Handler(void)
    : z! e+ o1 m4 ?( Z( u; n. v. w4 X
  8. {
    / \2 M* q& V$ Z" V: K7 r1 }
  9.     if (TimingDelay != 0x00) 0 `- H5 U# T9 \, w
  10.      {
    8 a5 _% A# j  ?. _# p. q3 e
  11.        TimingDelay--;
    8 Z; m. @4 e) a0 h; O- h0 y8 Z
  12.      }
    8 S. X* K5 A' W# b
  13. }
    $ G) a3 ~+ f+ N! V* M2 n
  14. int main(void)
    1 x% b2 X0 V2 [/ h+ K& R" ]
  15. {  …- |$ z% J, D$ O1 t+ K5 r, m
  16.     if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms; j2 Q) U/ T1 d
  17.      {# i- l8 I* J7 C: C$ Z
  18.      while (1);6 O$ F" e1 _6 A; `( x+ j
  19.      }7 F9 Q9 g$ ~4 N) Z  R
  20.     while(1)
    ! @$ p) G' S, h4 Z3 M. j5 B
  21.      { Delay(200);//2ms  Z) ?1 J: s' o% w6 G
  22.      … ! A* K( [$ ]8 @; P7 E
  23.      }6 L# S1 a9 E& N" ?* r
  24. }
复制代码

6 N* ~, i, t$ R. E1 `6 K) Q4 n3 m; _/ v* @( N2 `
/ @( S5 [# k; W+ i6 }
赞 收藏 评论0 发布时间:2022-6-11 21:08

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版