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

【经验分享】STM32 SysTick定时器

[复制链接]
STMCU小助手 发布时间:2022-3-30 10:00
01. SysTick定时器概述
5 ?3 Z" j3 ?" Q2 c& H/ fSysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
% b9 f8 y5 Z" P& Y6 k9 @; u( \# B) w
Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。. U. t# |$ D, [$ n9 h4 I& U

. E) ^/ N+ P* a" T. }. @/ Q+ n! _02. SysTick定时器寄存器描述0 l& O7 K! Y- {' K6 c* y! d; Z
SysTick控制及状态寄存器(地址:0xE000_E010)5 X; j/ m" w9 w
6 u( ~! p7 L1 Z, z" {: b) n
[GWAD%9]}36D0J0}W3WW3.png
5 u5 N* y: f( x3 k6 A
: R; L$ _! r6 ?SysTick重装载数值寄存器(地址:0xE000_E014)4 {2 N/ ]  ]" a! d; k; a

9 A9 P& j, z% q6 ]1 I 20200830102443823.png
: J2 ^4 a3 {) U0 a: c" g
3 v% z9 L$ Z8 X) I3 d, F: a5 Y5 hSysTick当前数值寄存器(地址:0xE000_E018)
( ?1 Z9 \- p6 v" `  \1 |
9 z7 d/ q. w' `8 V3 E9 f* W; L' q 20200830102451227.png " [$ M0 z* D+ A- q0 J1 m5 p, }
3 Q1 g; j+ U  `% }- _
SysTick校准数值寄存器(地址:0xE000_E01C)
/ g2 W( D* `+ B# j3 a* C8 `2 y! |8 @7 }( T
G(M%HZ45XFZ0T`43TKPAD.png 7 g* |$ L4 s- A# d8 m; j
6 V" P6 a! h3 c: o, ~+ L# j6 v- c2 `
03. 相关函数实现
. `" t: ~4 l- f. F5 j. Jcore_cm4.h文件5 M6 l% j3 W3 Q5 o- O
7 G8 g2 \0 C2 I9 u  Y
  1. /** \brief  System Tick Configuration/ N. {  k( w( A

  2. $ l- x3 g1 N1 Y) B
  3.     The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
    & E# p5 ]8 V# A2 r, I1 d. A
  4.     Counter is in free running mode to generate periodic interrupts.
    & n  j( V, @* ^7 G

  5. 1 ]7 W2 Q; t# I! K( }
  6.     \param [in]  ticks  Number of ticks between two interrupts./ y4 c- r. O% ~; Z

  7. ) Q. o, g; ]0 q  ]; |" s
  8.     \return          0  Function succeeded.9 b8 y" Z  X: X5 w
  9.     \return          1  Function failed.
    / m) V+ I0 i& f7 p9 u

  10.   Z' _: q$ g# _4 _. S
  11.     \note     When the variable <b>__Vendor_SysTickConfig</b> is set to 1, then the
    - d5 P" T- x' l! k
  12.     function <b>SysTick_Config</b> is not included. In this case, the file <b><i>device</i>.h</b>+ T# N# E- c9 a. {5 L# C* v
  13.     must contain a vendor-specific implementation of this function.) w5 ~, O9 k9 p. B: c) j6 S& G

  14. : u. H4 s" H( O" k# E
  15. */
    6 n% ?. o- E1 \! E% Z
  16. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)) e3 }5 R$ Y5 M, q% R
  17. {
    1 A' f% Q! m8 A0 [% i
  18.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }    /* Reload value impossible */
    ( d) A, o2 [0 _2 }; K+ y7 e" F2 g
  19. & b' |- N( Q" A
  20.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */
    , U3 Y: K# l: M" \8 m& s! g7 t9 L
  21.   NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
    , y) \3 l7 Y% _4 Z
  22.   SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */
    5 M0 ?( u* v, q% L( [' _
  23.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |  t. r' R) L, T# h" Y
  24.                    SysTick_CTRL_TICKINT_Msk   |. ?$ N/ y- J/ f6 I+ A
  25.                    SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */& ~& N9 \* i5 Z% F5 b
  26.   return (0UL);                                                     /* Function successful */
    ! R9 j9 _, A) a- m7 p: f; P
  27. }
复制代码
4 P8 [$ b& W9 Q3 G
misc.c文件' @5 U; B% u% L% n2 H4 b$ u) [
  1. /**
    - X. T0 a+ r6 y6 j
  2.   * @brief  Configures the SysTick clock source.
    % y' s1 I3 e1 c' g' n
  3.   * @param  SysTick_CLKSource: specifies the SysTick clock source.; }/ s, V* x4 A
  4.   *   This parameter can be one of the following values:
    / x' ]' w" x+ x# C; ]5 N- T
  5.   *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.: q, A: ?. ~. T# J5 H
  6.   *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.# v2 ]6 n0 w( b7 P
  7.   * @retval None
    % e' `; z! l- E/ O0 c6 y
  8.   */
      C  z( b( h, l/ ?0 W/ s
  9. void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
    2 B+ A  a) a1 L2 l7 ?, Q  K) L
  10. {9 ]9 T3 y: c' @
  11.   /* Check the parameters */7 s/ M( O, q( w) y7 {. `. }; F1 g" E
  12.   assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
    " s8 I' F3 l0 Y7 z8 A+ y5 {5 h, X
  13.   if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
    * @8 D' z& g  c
  14.   {
    4 J; M% \! ]0 X1 R8 O7 t4 P2 a3 A
  15.     SysTick->CTRL |= SysTick_CLKSource_HCLK;
    , x4 p6 ^+ b! `; Y6 \
  16.   }/ U/ Q+ j; g; t8 _$ U$ p. B+ X
  17.   else
    % w- e7 P" Y$ E
  18.   {
    9 P9 k$ u3 |, |6 |- b+ J
  19.     SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
    4 A- c+ R& F, R2 u5 a3 A
  20.   }" W" _. i& x- s7 |- Q: I4 }$ G
  21. }5 o5 C( c( S. o1 \/ I2 }% l/ k
复制代码

- y5 R+ e: j" R  @7 K9 h04. 延时函数实现
  o! u! P4 a8 P$ d' s
delay.h文件' q7 T2 E' G% q4 i4 [6 h
( N, y) z' e$ A+ n! I
  1. #ifndef __DELAY_H
    , A1 d" n. i5 _+ Q2 c2 N* t  `
  2. #define __DELAY_H                            : o: u6 I( H0 J. b; j* t" m
  3. #include <sys.h>          % e, O, f3 s: O0 m4 P* U

  4. , j) C0 Y+ ?6 C9 Y: I
  5. void delay_init(u8 SYSCLK);
    ; h* t8 W2 W, X; m/ w
  6. void delay_ms(u16 nms);8 i) R( d# P& t7 w7 K6 n, X
  7. void delay_us(u32 nus);
    ( e8 T1 z/ P- M

  8. " \: K! }  ~( Y  s0 P8 m' z, @2 s
  9. #endif
复制代码

" T3 q7 A- U- j; w  h: Fdelay.c文件
+ ^  m  F, }5 V, p$ s
8 \, P0 o( E  S) r9 _# C1 k& ~
  1. static u8  fac_us=0;                                                        //us延时倍乘数                           
    ! A0 r+ D; D! W
  2. static u16 fac_ms=0;                                                        //ms延时倍乘数,在os下,代表每个节拍的ms数
      I$ p! t* \7 z) L0 R& X" s% R( t
  3. 2 T1 _  m$ ~  |% D3 L. @, u
  4. //初始化延迟函数
    ; ^6 b/ z& I2 N8 B3 }
  5. //当使用OS的时候,此函数会初始化OS的时钟节拍
    3 j6 }% v, b! x0 |
  6. //SYSTICK的时钟固定为AHB时钟的1/8
    " @- m1 {/ ~: I8 M2 v
  7. //SYSCLK:系统时钟频率
    8 J# v% D; A2 E8 W( X& x
  8. void delay_init(u8 SYSCLK)
    " H* T0 I" s( Q2 B/ C5 _
  9. {
      m! e! k) O" D+ q$ g: W
  10. $ p! v+ ?; h' B0 ]7 a
  11.          SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    1 |6 I, [+ `; c5 V$ s
  12.         fac_us=SYSCLK/8;                                                //不论是否使用OS,fac_us都需要使用
    4 d9 |4 D0 a. u& L6 v$ l
  13. ! m- n. W' h9 B! Z5 A% [( o
  14.         fac_ms=(u16)fac_us*1000;                                //非OS下,代表每个ms需要的systick时钟数   
    4 a7 j( V- X; S
  15. }                " Y0 x% H7 ]5 c) _$ ~% o. ?
  16. 8 Y! d/ I- l" \6 }% ?" @
  17. //延时nus
    * B! Q: q& L5 Z" n
  18. //nus为要延时的us数.        
    ) o9 [' f% v3 k* V1 J
  19. //注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)1 J8 o" X) i* @0 c6 z
  20. void delay_us(u32 nus), @: S! X* g0 B, j) U6 ?
  21. {               
    # y2 H2 U/ K, \
  22.         u32 temp;                     ; M" L5 N" k; F% v
  23.         SysTick->LOAD=nus*fac_us;                                 //时间加载                           
      y7 Y5 y! I* b; S
  24.         SysTick->VAL=0x00;                                        //清空计数器# z* ]. }  y. u5 H1 t6 X1 l
  25.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数          ) a; W6 X4 e) m# S
  26.         do
    + \' n' A1 f1 m# J$ M  A. S  i7 E
  27.         {, O6 c% L! G- v2 ?$ |( Z% u
  28.                 temp=SysTick->CTRL;
    0 X. \! @; m9 M6 y& u5 g
  29.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
    & p# a+ u/ b! }5 Y5 X# r
  30.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
    / i5 h: }$ q  e% i- ]
  31.         SysTick->VAL =0X00;                                       //清空计数器 9 \" R' t: f, p- d5 B" l
  32. }7 y" g6 @  o$ ^, _4 g7 L4 \3 c

  33. / ?  A  C' i, L9 {4 i: v* X
  34. //延时nms; K" k, v2 ~! Z. J9 z8 t4 F
  35. //注意nms的范围9 L# F9 l, H1 B' X7 ^. Q1 O
  36. //SysTick->LOAD为24位寄存器,所以,最大延时为:  m( t; ~, C* U8 a8 u+ {
  37. //nms<=0xffffff*8*1000/SYSCLK$ z1 U) f4 n9 @; [9 R. m% ~, m. _
  38. //SYSCLK单位为Hz,nms单位为ms) Q, b: h4 Y" r/ [
  39. //对168M条件下,nms<=798ms 0 O, O+ a" E' @' E; `
  40. void delay_xms(u16 nms); A1 S; x& z& _
  41. {                                     , j  z# @( E" W  K- D
  42.         u32 temp;                  
    1 x( j. `; |- y! W: Q" r" S
  43.         SysTick->LOAD=(u32)nms*fac_ms;                        //时间加载(SysTick->LOAD为24bit)8 z, v2 d: E+ W% l& a
  44.         SysTick->VAL =0x00;                                   //清空计数器
    ( x% z* f' k& E1 J* {
  45.         SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数
    2 Y, u0 y5 }  q' v4 U( H
  46.         do* ~  b* {) d* b! ]6 \
  47.         {
    - v4 K" d: P3 z$ y# S' L  E
  48.                 temp=SysTick->CTRL;' a0 |9 V5 |2 P9 T( X/ C- G
  49.         }while((temp&0x01)&&!(temp&(1<<16)));        //等待时间到达   
    ' f& g& Q- h, k6 v5 `9 q
  50.         SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器5 ?% h; w- Z3 w0 A! Z1 j1 d* a
  51.         SysTick->VAL =0X00;                                       //清空计数器                     
    ; B9 D$ x$ d4 f+ e  w7 b, k, f& P
  52. } 9 j3 H3 k6 N& v0 p$ F- t6 I; m& v
  53. ) Z* i- h/ q; Y8 b; q/ I  J. K
  54. //延时nms / X# \- s1 |' g; I" b; f, A
  55. //nms:0~65535
    ) u3 a' L/ l/ ]9 J7 v5 `
  56. void delay_ms(u16 nms)/ U4 |1 X6 ?$ l0 ~/ N
  57. {                  
    " R) |- b" {1 Z' q0 e
  58.         u8 repeat=nms/540;                                                //这里用540,是考虑到某些客户可能超频使用,- c  ?* ~! ^+ I2 f& b0 b( X# [* ?" @
  59.                                                                                         //比如超频到248M的时候,delay_xms最大只能延时541ms左右了- A! d& k) d- H1 q
  60.         u16 remain=nms%540;
    . _; Y7 U9 m* ~! B' O0 W
  61.         while(repeat)
    3 p% X6 f1 x0 a: O! V
  62.         {
    2 E. n6 F; j& A& h5 t! x% t' }9 M
  63.                 delay_xms(540);
    9 i3 A  A2 `  o! k
  64.                 repeat--;
    1 g  }  H- G$ H9 J
  65.         }
    % N, d9 P( T1 O; I- }
  66.         if(remain)delay_xms(remain);* N! J) j% h) w" i/ C3 p
  67. } ) J" [  P: f' y
复制代码
- ]! @' ]/ K( t3 q) _
05. 应用示例
4 F9 k1 k* K# C3 `4 K" @用中断的方式实现delay延时. t1 X6 {, ?8 r  Z* K- [
5 T' n3 p, Y! {; y
  1. static __IO uint32_t TimingDelay;3 [* E% b2 r9 Z6 B  L0 ~
  2. void Delay(__IO uint32_t nTime)
    0 \( J! w: r- t3 k  L6 P
  3. {
    ; A7 c% r  ?7 ?; a9 \; r
  4.    TimingDelay = nTime;
    4 Q$ J9 p$ U5 K" }8 J
  5.    while(TimingDelay != 0);
    ( u. Z7 J, q9 ]2 \
  6. }. z+ Y& m( R; q& D
  7. void SysTick_Handler(void)
    ! P  B$ ]; ]$ M! i) Y' N8 o
  8. {: P6 w/ U' \- r* O2 |* q* l
  9.     if (TimingDelay != 0x00)
    ( c; I2 q1 P  J; G' U: k( K. M1 L
  10.      { ! c( E7 d7 M  B8 A
  11.        TimingDelay--;
    ; W7 P+ ^, R: p5 O7 Y
  12.      }
    : F. J; G5 f! l# L9 j
  13. }, L" H  h' H! Z% `3 d# V
  14. int main(void)
    ' \' x+ l# k1 S/ h
  15. {  …8 t2 A& I) i" T; j8 G$ _% N
  16.     if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms3 V0 C) ^, a9 ]8 }+ z; I' b  H
  17.      {
    * E* ?8 w; [2 H9 d  a' s
  18.      while (1);
    # _; r% g( u0 m$ Z8 b1 X, A
  19.      }
    6 \+ ^, a5 T& @" G! l* w( Y0 }
  20.     while(1)) D4 Z1 k, G0 e( a+ s( i( h
  21.      { Delay(200);//2ms) Y  r7 N; z* ]. \% t, \
  22.      … 0 X2 j9 S# ?. g- e
  23.      }
    0 t' N; T1 A( N3 J  ~, r
  24. }
复制代码
4 f5 B9 j! `; {" R& s# v* \
赞 收藏 评论0 发布时间:2022-3-30 10:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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