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

【经验分享】STM32 SysTick定时器

[复制链接]
STMCU小助手 发布时间:2022-3-30 10:00
01. SysTick定时器概述
% ^  F8 U4 R4 V7 l9 ySysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
" T  [$ w# T7 Y$ D
% ~7 x  O/ h! L0 j) w2 j4 \) vSystick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
6 E& z. s7 a. e% q
6 i% t4 l+ D* h: n, h. y- C& k3 U4 ^02. SysTick定时器寄存器描述
  @' X7 N* E4 R$ fSysTick控制及状态寄存器(地址:0xE000_E010)  k* f6 G1 o: H& }' c9 s
8 _6 F+ l( Q3 m/ R
[GWAD%9]}36D0J0}W3WW3.png
2 Q  \  G; C  S; s, K, Q; j+ b8 G0 b0 D, m0 m0 Q
SysTick重装载数值寄存器(地址:0xE000_E014)* s$ s% _/ s1 ~$ f4 j
3 H" [* X8 x" Z
20200830102443823.png
  a* c6 L/ L" _! y( N. k9 M% ]0 j3 [) R2 I1 G
SysTick当前数值寄存器(地址:0xE000_E018)
; F, `! r+ f$ |/ n1 s. u8 j$ K& _5 a- \3 E
20200830102451227.png 5 D# G2 f% X) G9 L( X& ]
' N- I4 c  a' m
SysTick校准数值寄存器(地址:0xE000_E01C). B, z) ]' a& S5 m( B& b: y

; B8 [" t, J: A% F/ V; }5 _/ F G(M%HZ45XFZ0T`43TKPAD.png
; l1 G# t. p, N, p1 y1 {# F& G
7 k/ k; q* f) Y) }9 M: Z. C- v03. 相关函数实现+ }8 B" M( @1 Y# S5 p' z
core_cm4.h文件
) N- X6 U* f9 n% A( z$ ^8 X- r0 h5 m* \. o
  1. /** \brief  System Tick Configuration
    ) m( \3 y  J6 r: a- G, L) {' f

  2. : r- Q5 h4 K9 Q- u' C
  3.     The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
    9 Z* G- y. X" S( Q) K
  4.     Counter is in free running mode to generate periodic interrupts.( `8 y$ o' P8 w! I0 a# {8 h

  5. # [1 a" S/ y% E4 N7 W0 q! h( u
  6.     \param [in]  ticks  Number of ticks between two interrupts.$ u, W% E2 K% s) C
  7. 4 M. v* F3 K+ s' |9 H/ o
  8.     \return          0  Function succeeded., X0 n- L8 e) ~; H: b/ v
  9.     \return          1  Function failed.! m$ j" o5 ]" t% e5 |+ O7 q
  10. - s9 s- p1 k! C; j
  11.     \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
    & m6 e7 U1 A9 f& S
  12.     function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>  l) s6 X9 J4 [
  13.     must contain a vendor-specific implementation of this function.
    % ]. }& `- d3 q7 h) `% K1 B) X
  14. 4 Q  T% M+ v9 f  k
  15. */4 f: I( C! v4 p$ n
  16. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)8 o/ `( c1 w$ ?- U
  17. {
    2 S  U4 ]  p2 r+ @2 L' u
  18.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    /* Reload value impossible */
    ) ]. K, ]/ D; D1 K

  19. % c% U. Y' j8 u3 N
  20.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */$ r+ \' }$ w4 |% ?
  21.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */5 i3 K! W' x% }7 m
  22.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */9 f% \& e7 q0 p5 ~
  23.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |# W8 K+ L7 B  F) Z' P( @9 p
  24.                    SysTick_CTRL_TICKINT_Msk   |4 h) g+ r3 U7 t0 G6 O9 w
  25.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */
    ; o- {# m+ A7 ^
  26.   return (0UL);                                                     /* Function successful */5 v% V) j. _$ P3 K; E5 I+ P  M
  27. }
复制代码
' M" F% n# V5 e" N6 _  f# w
misc.c文件  C$ w3 O' h6 b' b0 L
  1. /**
    7 H- F7 C! z/ Q
  2.   * @brief  Configures the SysTick clock source.3 L3 e" l. i1 i% H8 V, w4 O" e5 X
  3.   * @param  SysTick_CLKSource: specifies the SysTick clock source.
      p& t' R: r! L$ ~
  4.   *   This parameter can be one of the following values:  r5 E; _# @3 c/ A: u
  5.   *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source." G, O) I3 Y9 j6 C8 _; E
  6.   *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source./ w# n  c6 @/ ^
  7.   * @retval None
    6 C4 X6 S5 t& q, w5 [
  8.   */
    5 k7 i! X3 u. j  W& x3 f% X
  9. void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
    3 Q( A% c' o8 [% U
  10. {' Z  w( Y( O/ D' j
  11.   /* Check the parameters */
    ' Y; s4 c0 E9 @+ w6 A
  12.   assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));1 H: D0 H" Z4 I7 n
  13.   if (SysTick_CLKSource == SysTick_CLKSource_HCLK)# C: s$ |5 H7 }/ n0 x' M
  14.   {& u' {) t* a5 }! n7 x
  15.     SysTick->CTRL |= SysTick_CLKSource_HCLK;
    8 D9 d$ \: m' \" v8 ?$ v- j3 P
  16.   }
    & Q/ [, R  c( f  C
  17.   else
    0 S9 `/ b2 b" e( y% {* W  f; A
  18.   {
    2 n$ p0 x' q6 o& P5 S) [
  19.     SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
    2 @$ u: _2 Q  P- \: c1 M# G
  20.   }3 {5 x- J. z4 y+ m" z* D
  21. }2 H4 ?6 F1 }3 |& m1 L" ]+ P
复制代码
( k2 ^) B5 f2 s
04. 延时函数实现

: {5 H# ]/ P% G7 |( Z( Tdelay.h文件
9 |. `4 m6 j9 O$ l$ p
4 ~. Y0 x3 W6 u5 ^1 r! `* A# L
  1. #ifndef __DELAY_H
    3 x" `, J& D/ _4 Q& U! R- {/ a' R
  2. #define __DELAY_H                           
    . y& E  H$ t: G1 [4 q& y" S
  3. #include <sys.h>         
    3 g# ^  U& s! g) O$ [) @3 }
  4. 8 @5 Y/ [& W6 x( e/ m6 p* R8 }6 N( s
  5. void delay_init(u8 SYSCLK);! P, _( i, q2 i4 H. K
  6. void delay_ms(u16 nms);
    * j: P3 C' C! W5 x' x/ |
  7. void delay_us(u32 nus);! Z% ~+ B, p! _9 k  c4 V
  8. + _; [: l% z6 m# ?: K9 D' X
  9. #endif
复制代码

: I( n* A/ J- pdelay.c文件0 S1 H3 A: Z# ~7 m) r

  I% f1 s8 E- V( c" y: p7 F
  1. static u8  fac_us=0;                                                        //us延时倍乘数                           
    ( \/ Q! ]$ {5 k, Y* R8 n6 i3 l
  2. static u16 fac_ms=0;                                                        //ms延时倍乘数,在os下,代表每个节拍的ms数+ q# Q7 O- v5 ^- P

  3. 8 |8 t, O" W8 Q: ~
  4. //初始化延迟函数
    / B. r) u) y: [- y# s
  5. //当使用OS的时候,此函数会初始化OS的时钟节拍
    $ K8 ^( z/ u+ M+ h6 H
  6. //SYSTICK的时钟固定为AHB时钟的1/8
    6 L- c$ |" k6 p" D
  7. //SYSCLK:系统时钟频率- {1 x9 y& s! J, B. T" \
  8. void delay_init(u8 SYSCLK)  P' ]; s$ K; c+ x& z8 o
  9. {% r4 m3 B! X; }0 W

  10. , ~9 ~" a2 I8 T# u4 L
  11.          SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    6 J7 S$ O  l1 A4 H$ b5 Q+ y4 k0 R5 a
  12.         fac_us=SYSCLK/8;                                                //不论是否使用OS,fac_us都需要使用
    + Q# F! K( X# J& m5 s3 I& m* m
  13. 3 p9 j$ A: z% p4 Z- h2 w4 Y3 F+ W1 H1 q
  14.         fac_ms=(u16)fac_us*1000;                                //非OS下,代表每个ms需要的systick时钟数   
    1 Q5 C8 \/ r& M3 v2 t7 d! e# `
  15. }                / Q. V( x6 Z  E4 x8 H4 l. J
  16. 1 C7 k# t* R2 ]6 Y
  17. //延时nus
    * n4 ]' C+ L  Y! |
  18. //nus为要延时的us数.        
    # t% B! V- q( @  d
  19. //注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)! ~3 V0 H) ^0 b9 n, O! |8 c
  20. void delay_us(u32 nus)  |, k% E  I. m
  21. {               
    $ h8 [3 n" ]+ J
  22.         u32 temp;                     
    & o: d# C1 {/ f2 O- f2 C* T0 z7 h& X
  23.         SysTick->LOAD=nus*fac_us;                                 //时间加载                           $ Q' S4 k5 h: `+ A1 H  e+ i
  24.         SysTick->VAL=0x00;                                        //清空计数器+ x- F, X8 D7 e, O
  25.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数          ( v; m$ w: l6 m" _3 q! `. C9 }3 n: u% T
  26.         do6 d5 c3 g/ T; x# V/ n
  27.         {
    7 H2 t% ]5 F" A" t, m
  28.                 temp=SysTick->CTRL;# V! i0 Y7 W( u6 ]& j0 e4 q, j
  29.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   $ ~% C! `, X4 x% [7 Z3 i* B
  30.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器7 G# C: \6 q$ ^, u
  31.         SysTick->VAL =0X00;                                       //清空计数器
    + M( U! P8 f8 }: G& [. q
  32. }% c( }7 D4 {) Y' l: q
  33. * s1 z9 H8 L4 X* S. G
  34. //延时nms
    & }, j" w- p0 h7 ~6 [
  35. //注意nms的范围
    ; E4 Q0 n$ z4 K7 z; O
  36. //SysTick->LOAD为24位寄存器,所以,最大延时为:9 m% g# M5 q# ]2 F
  37. //nms<=0xffffff*8*1000/SYSCLK$ R9 W& b' `9 t, |! c
  38. //SYSCLK单位为Hz,nms单位为ms
    % d- r) _3 z! b
  39. //对168M条件下,nms<=798ms , h9 U0 h! {2 u4 i& S1 M8 L
  40. void delay_xms(u16 nms), n& L7 B% u6 O! B/ X6 M! \& ?
  41. {                                     0 x/ C0 H. W) R& d. n4 W4 ^
  42.         u32 temp;                   - S6 ?' K! H2 v) \
  43.         SysTick->LOAD=(u32)nms*fac_ms;                        //时间加载(SysTick->LOAD为24bit)
    + b$ x1 d! j; W: X& C2 W
  44.         SysTick->VAL =0x00;                                   //清空计数器) k& U3 f: c& @6 \0 L
  45.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数 + c8 w7 @; s- \0 z9 V0 `0 ~
  46.         do9 @4 p3 R4 m8 _
  47.         {% z% P- h! p+ m1 G6 O
  48.                 temp=SysTick->CTRL;
    & F$ t; y4 T4 _/ Z0 _
  49.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
    , [' \% ~+ w/ g: S6 R; `/ ^- h
  50.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器) |5 N: D7 C  ^1 W9 W$ o. T) Z
  51.         SysTick->VAL =0X00;                                       //清空计数器                      4 o  L' G- D3 I2 B' x% }+ q
  52. }
    ( G* |. r2 {+ t5 L: @
  53. 0 D, u6 c0 l6 L( a$ b) [# [: [
  54. //延时nms 3 H4 l1 J( I5 y/ Y1 r- r
  55. //nms:0~65535! T% }- e# \' D
  56. void delay_ms(u16 nms)
    . _- S5 C: i1 v2 g8 M* h6 J
  57. {                  
    % Q. K  I' T9 j
  58.         u8 repeat=nms/540;                                                //这里用540,是考虑到某些客户可能超频使用,
    3 h8 \0 z- X* A" {5 A2 q8 {
  59.                                                                                         //比如超频到248M的时候,delay_xms最大只能延时541ms左右了# L) T+ u: f  h7 w3 N
  60.         u16 remain=nms%540;
    " Y& V3 M8 o7 z0 _0 h/ R
  61.         while(repeat)
    - j" ]) |+ g. v+ E
  62.         {
    ! K' y/ O; X" [8 e
  63.                 delay_xms(540);0 O' i$ i: G7 k+ P% Q( }4 Z( M5 R
  64.                 repeat--;
    ) e0 g( ^' c7 B% Z! {* n
  65.         }
    ; X: |$ x0 Q* z/ _& X
  66.         if(remain)delay_xms(remain);
    1 ?; \& y; t; J
  67. }
    . V6 s; @  ^, U: g: D) W
复制代码
7 k( h5 l& \; f' J
05. 应用示例
/ Q# q5 S) b* I用中断的方式实现delay延时
6 M% r( |2 U1 d/ Q" P! ]5 ?, R8 r1 D
  1. static __IO uint32_t TimingDelay;
    / b: c, [; F: o$ c
  2. void Delay(__IO uint32_t nTime)4 m4 U7 k) ]# Y4 D
  3. {
    ; q1 U& B: s" l7 R
  4.    TimingDelay = nTime;
    1 K$ r0 J5 ^/ w& a0 ]
  5.    while(TimingDelay != 0);
    - h2 }/ j0 B4 ^% n& z( M6 G- f! R
  6. }+ x1 m+ W4 f- k4 h
  7. void SysTick_Handler(void)* [3 V/ g' f) F  ]' s( d! G) C4 O
  8. {  e1 G$ V+ T- L) J$ Y0 z! `
  9.     if (TimingDelay != 0x00)
    ! A  h( p2 P; y6 k1 |5 U0 N$ i
  10.      { ( Y/ F2 r; u4 S- y, J3 X
  11.        TimingDelay--;
    " I/ I+ J1 m7 ~  }+ w/ p, S
  12.      }3 i5 g. f/ o4 u" o( N/ b' ^' D! J
  13. }" f% `/ Q: w- o7 G, G( m! |, Q3 H
  14. int main(void)5 P# `, C% }  z' q0 T2 p3 _2 N0 |
  15. {  …7 d# D7 Y* x+ V9 w+ H! s# x
  16.     if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms
    4 w5 b. y5 b# z
  17.      {
    2 {1 y0 W9 T. K- J1 I+ M% F1 V
  18.      while (1);
    * ^8 v" u' T4 |9 y9 v
  19.      }0 \8 A& N7 `1 h6 z
  20.     while(1)
    " P. F' p7 q. l7 F4 g' j+ P
  21.      { Delay(200);//2ms8 u  S! G6 x9 u! k
  22.      … $ l  c% L( \1 G" h' _
  23.      }
    " }1 {" ]9 u$ R* c; K
  24. }
复制代码

; _5 K, `; s, a4 O, D
赞 收藏 评论0 发布时间:2022-3-30 10:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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