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

【经验分享】STM32---系统滴答定时器(systick)应用

[复制链接]
STMCU小助手 发布时间:2022-5-24 10:21
1.systick介绍, ~" Y$ |: ~# u/ p, i1 W

! G4 @. e# _  m/ [     Systick就是一个定时器而已,只是它放在了NVIC中,主要的目的是为了给操作系统提供一个硬件上的中断(号称滴答中断)。滴答中断?这里来简单地解释一下。操作系统进行运转的时候,也会有“心跳”。它会根据“心跳”的节拍来工作,把整个时间段分成很多小小的时间片,每个任务每次只能运行一个“时间片”的时间长度就得退出给别的任务运行,这样可以确保任何一个任务都不会霸占整个系统不放。或者把每个定时器周期的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。 只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。
; X) G- ?8 G6 F% w& q
. A$ [0 h+ ~; L) G     知道systick在系统中的地位后,我们来了解systick的实现。这里只是举例说明systick的使用。它有四个寄存器,笔者把它列出来:
$ h0 \' `' y% }) a+ D, J0 S& c! r" ~8 X6 Q
    SysTick->CTRL,        --控制和状态寄存器
: l* ~0 s6 J& ~9 {! l( T% ^" R( j
' \6 I4 _$ ?1 m1 `8 L    SysTick->LOAD,        --重装载寄存器
% v% A. R. I0 N  k  T& h- K
% j, V# J. O* z; L- ^    SysTick->VAL,          --当前值寄存器
8 O; t7 K% e* p
; ^6 n2 z  y! k; Q; k7 B   SysTick->CALIB,        --校准值寄存器   
+ ?/ k1 R0 r8 h6 @9 h4 D' t% F+ _3 L; r2 f0 I. H& m7 ?
1345388072_8448.jpg
& H/ ?, r6 s1 M. G! u% l; g, }1 \6 t! F3 F. K6 D
1345388045_7722.jpg , \: S; L( {& Q, `" n( t

( W% i5 @9 X+ a2 K3 i 1345388109_7290.jpg * }% ^1 w' X6 C4 @, [, d

' t& E% G9 H# I& U+ ?" Y: u( y, m 1345388134_2995.jpg " V7 F, Y% z9 c: N
' F: \6 `: I" g. ^. H- y! z
2.systick编程
) r- p- W! t3 Y
% @# G9 d5 Z4 F$ C4 [) ^    现在我们想通过Systick定时器做一个精确的延迟函数,比如让LED精确延迟1秒钟闪亮一次。& P7 G/ }. ]- z8 M
* q/ ~6 k$ \' u9 R$ P
    思路:利用systick定时器为递减计数器,设定初值并使能它后,它会每个1系统时钟周期计数器减,计数到 0时,SysTick计数器自动重装初值并继续计数,同时触发中断。0 A& V, v! [: J$ P" Y1 s
2 W! [& M7 k& o- o3 [+ I, F
那么每次计数器减到0,时间经过了:系统时钟周期 *计数器初值。我们使用72M作为系统时钟,那么每次计数器减1所用的时间是1/72M,计数器的初值如果是72000,那么每次计数器减到0,时间经过(1/72M)*72000= 0.001,即1ms。(简单理解:用72M的时钟频率,即1s计数72M=72000000次,那1ms计数72000次,所以计数值为72000) 9 Z. {: q6 b% R0 _4 I: w1 Y8 \$ l; f; J
) V. I5 O2 R5 E& B/ K# d* k# X/ @
+ ?  @) c  X" r8 h. C$ z
3 g3 Q$ `& C  r0 q% S
首先,我们需要有一个72M的systick系统时钟,那么,使用下面这个时钟OK就 !  P2 x- C/ f! p$ n1 }9 U: k

; d% W* b. \# c) s    SystemInit();
% g2 A! `, S1 ~) Q
# U. ~2 p7 Y: s5 E    这个函数可以让主频运行到72M。可以把它作为systick的时钟源。( T: |) e2 L! ?9 |: {! h( {

$ `: x# O3 j5 `) I9 [* {    接着开始配置systick,实际上配置systick的严格过程如下:1 \( w$ J6 q$ E

! X# L' y0 b! g' m. N9 |    1、调用SysTick_CounterCmd()       --失能SysTick计数器3 ?* L" d& c; P2 b2 R( x" w6 |% A

4 P& G4 Q: G8 q2 W: G' v    2、调用SysTick_ITConfig()          --失能SysTick中断1 m: d, ?, c2 l* k

9 ?( D9 [9 ?# X6 X6 }2 C    3、调用SysTick_CLKSourceConfig()  --设置SysTick时钟源。0 Y# _* L$ @8 B
2 c; B. P9 y# n1 U% }
    4、调用SysTick_SetReload()         --设置SysTick重装载值。
8 o. @4 C) ?% i8 X) m) I. ]$ G+ a1 p  m' \! k4 V
    5、调用SysTick_ITConfig()          --使能SysTick中断
$ r, A) G' S3 z" W% ?6 S; G
3 e  \$ [3 A& a  f    6、调用SysTick_CounterCmd()       --开启SysTick计数器                                                      ' C3 j. A1 E2 Y6 s
/ O. Y5 |5 L4 `; M0 I' a
    这里大家一定要注意,必须使得当前寄存器的值VAL等于0!
: X$ f9 J7 F+ v9 [% {/ V: [" v: h* u- i6 c3 d
    SysTick->VAL  = (0x00);只有当VAL值为0时,计数器自动重载RELOAD。
# c& B3 b+ A* N, K
" f! A3 a, q' L! U接下来就可以直接调用Delay();函数进行延迟了。延迟函数的实现中,要注意的是,全局变量TimingDelay必须使用volatile,否则可能会被编译器优化。4 f4 p* P5 r6 u5 g' d6 ~
3 T; \* o: `/ V4 @: o9 F
下面我们来做一下程序分析:/ W0 g9 [$ ^0 Y7 Z% E# ~1 F; b' ~5 f

! b: s' T. c2 D# v. J(1)系统时钟进配置

6 I7 @; ?9 k( T- u: j! t3 [' S" i( s9 F) r. A9 W6 p5 P
首先我们对系统时钟进行了配置并且SetSysClock(void)函数使用72M作为系统时钟;
0 c" k+ l9 P  e: ^! u, d4 ~7 u; y, L( J
为了方面看清代码我选择截图:
  r. B$ W! D9 V( u# O$ x
3 G4 W! v) r  T2 V" C3 e( {( E$ j 1345388271_9008.jpg ; ^5 {; T- o! V& q4 A  z2 X# A3 |

) B' |* N. C! r 1345388291_8358.jpg ; I: J. |9 f& F" Z' j% x
+ q% d$ |' ]' I  f6 X# [9 Z- f
(2)先来看看主函数  C5 W/ ^. L6 H+ P$ f% P  ~
) H, M+ @' p' R) i( y
  1. int main(void)
    - s2 G( ?7 z6 K5 C$ @' |

  2. 3 @8 \$ L+ w' ]5 X/ c, R1 P
  3. {            unsigned char i=0;8 |% h- u6 ~" i4 d( i. z6 Q6 v

  4. : b7 |* b/ F5 K4 _& s6 L
  5.         unsigned char a[] = "abncdee";) T1 W. w; _1 _( O

  6. . M: U2 v( G5 w9 d; q4 i+ d; e
  7. / t4 X. ?% d& w' @! ]* g

  8. & ^" g& A8 g, ]. H
  9.         SystemInit1();//系统初始化7 c8 V7 b5 l) e0 ]6 ], S

  10. % ~0 d/ b# F; f/ a1 m

  11. ( `7 K' D/ f/ W7 f4 }4 S) v! B+ A
  12. ( Q% E- s% `7 ]
  13.        if (SysTick_Config(72000))  //1ms响应一次中断1 J( r6 c( ?& O. Q8 s
  14. / g7 s5 m" }/ m/ `) t3 N
  15.         {
    : G: ]% E' d+ G. p

  16. + S7 T, @2 }* l5 l# W' r/ C
  17.             /* Capture error */
    , Y: C. Y% ]  r& J# d
  18. 6 A, Q* b* Y4 u# e# b4 _. G
  19.                  while (1);
    2 r1 L7 v6 n9 W
  20. ' m& a4 z( S0 j' ?5 N
  21.         } $ K9 J0 a$ M* {) W* m; y

  22. 6 J0 ]/ l: G2 F6 }& y
  23.         /*解析:因为要求是每500ms往中位机发数据一件事,所以放在while语句中,* e# E" T9 H# f; s
  24. 3 T0 Y, `& N2 n% G( }) K
  25. *送据+延时可以完成相当于中断的效果;
    0 f7 r/ ~1 x: F6 G; R: |
  26. : s0 J6 ~$ n3 @) U: n
  27.                *若是多任务中,其中一个任务需要中断,这把这个任务放在中断函数中调用;, q* t# F4 X1 f, m+ I* @. [( F9 r

  28. 9 b1 B! ~  b' x# }4 C
  29.                */" ]5 e- b2 l7 ^- k* v+ |' J+ T  g

  30. 3 O& e0 ?+ `" r: |+ c7 o- y
  31.         while (1)0 S2 a, A" K( z1 d/ e" |  H

  32. 7 \: q+ N( ~" y  J1 U& s
  33.         {0 {. Q+ @( C/ F5 A
  34. 5 }7 Z0 _& R4 O7 z$ K& }
  35.              //测试代码:测试定时器功能,通过延时来测试
    % A/ q( T% L/ c, f) [
  36. " j6 b  z1 f+ v# y+ L: i

  37. . ?% e5 ?; k& ]" G$ K: W

  38. 0 c) C; f% q! Q5 [6 Z0 z
  39.              GPIO_SetBits(GPIOC, GPIO_Pin_6);      //V66 b# I5 E8 u# f, j. b, ?# ~+ L8 n

  40. 8 X* R: R; _. z0 n8 M- U
  41.              Delay(50);2 }; d6 W$ z/ N2 n) Y# i  b% u

  42.   o8 C: i. }, I0 U, G* i0 {
  43.              GPIO_ResetBits(GPIOC, GPIO_Pin_6);         //V6
    $ F& Z3 {8 s  x6 C- m5 {8 v
  44. ! V% B# D/ Q9 D; F
  45.              Delay(50);) w. K5 s* J: a7 B

  46. 1 [% p0 ]9 ?/ O! l1 o

  47. % |. U8 K  H; j8 W

  48. % V# P& z; O2 U* T* [
  49.             //功能1代码:每500ms发送数据
    $ o" [% A2 G4 I( z+ g1 F& L, O

  50. ! Z9 J0 z( S  j
  51.                /*
    0 L: k1 K1 L3 d; Q; l
  52. : t% l* k+ l1 ~2 d, d* I, T9 ]9 q
  53.                       UART2_TX485_Puts("123450");
    8 z! [7 K4 x: r1 v) P' X0 r
  54. . n! O7 C7 d% b
  55.                       Delay(500);
    * {: H. X) j' s( N5 y$ }" J
  56. ; P( i5 w, x! P4 _" Y& R  |
  57.            */
    - b4 N) o8 z6 K' i

  58. 9 T* U9 Q' B8 q" H+ G
  59.             //功能2代码:上位发特定指令,中位机执行相应操作
    4 q9 D7 G, m, M9 [1 V! N
  60. " j, y4 e8 f) M, O. |
  61.               //     RS485_Test();
    . k) |; ?( ~+ F- c/ q( G7 g8 ~. ^
  62. 8 a9 N1 V& y" C9 g4 w: o* t# U
  63.               }     $ H6 Z7 \4 z' t- u

  64. ) J  g- i1 K& F" |: I9 m, R
  65. }
复制代码
4 `8 }4 s& ~- w% E& J( d4 C1 _0 B
, @* s; w& I( e! C
(3)系统滴答定时器的配置--主角登场:
4 c8 @$ C: G0 f% @+ |6 e. Z
3 n  q, E2 n; g2 L2 E# Z7 J主函数中: SysTick_Config(72000) ;滴答定时器的参数是72000即计数720007 |/ g: U) J$ R; ^  k8 n

1 t7 g# W/ ?, ^(因为我们使用72M的时钟频率,即1s计数72M=72000000次,那1ms计数72000次,所以计数值为72000)
: B4 P4 z) S$ B# ^1 F& D2 W+ i2 E9 z! f7 X. f  d
在文件Core_cm3.h中
! ?  E  x- |+ V
4 A5 |+ u8 x% g, o+ K; BSysTick_Config函数的具体实现如下:
0 L9 z: _9 b: p2 D8 g; p. }5 K/ E$ i5 k  N3 l  |) ^
  1. static __INLINE uint32_t SysTick_Config(uint32_t ticks)
    : ~) B7 n  W- f( b! }
  2. / i# Z- ?/ q+ Z/ _. X# Z
  3. { : \4 L% ^; L* g, X0 z+ U. i* W9 N
  4. + D  ]9 D6 c  R. B/ w
  5.     if (ticks>SYSTICK_MAXCOUNT)  " x) R* a, v  _. T, G5 y

  6. ! n1 @# l5 _4 v" }% R  w; L2 j
  7.      return (1);      /* Reload value impossible */* E6 \5 v, r5 G( D! C4 C* }. {# _  v

  8. 7 {8 \" J0 Y* X0 N
  9.     SysTick->LOAD = (ticks & SYSTICK_MAXCOUNT) - 1;//systick重装载值寄存器   /* set reload register */5 \: o) i& x( D( M

  10. 6 B& u' ]/ A5 M
  11.     NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */7 N0 W9 @* \9 G# o4 Q& @4 G

  12. 3 F2 Q6 [" O  }* O3 U2 e
  13.     SysTick->VAL = (0x00);  //systick当前值寄存器                              
    3 k# L; V7 G/ T+ N( i
  14. 8 h. h' Q" u9 `
  15.    /* Load the SysTick Counter Value */3 n7 ~% O: j; v' c- ?9 @3 g
  16.    SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<<SYSTICK_ENABLE) | (1<<SYSTICK_TICKINT);//使能IRQ(普通中断)和系器         return(0);      /* Function successful */
    8 R9 q$ L9 g4 b$ d  k% k2 `
  17. 3 V1 j0 \; z/ f6 |
  18. }         
复制代码

, _, E& m: ]; f  P6 H                            " q* E; B) P. h+ a- ~
我们来看一下这句代码:SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<<SYSTICK_ENABLE) | (1<<SYSTICK_TICKINT); 这是使能IRQ(普通中断)和系统定时器,为什么要使能中断和系统定时器呢?
% `6 A+ \7 Z2 m1 y8 `# W
7 b9 T4 U: A7 i下面我们来看一下stm32f10x_it.h文件中:
8 ?0 c! F6 O0 \: G/ w& Y, c( B! [+ w; w5 [, r/ i- F
找到滴答定时器中断函数:SysTickHandler()
2 w+ e1 R! X2 L7 M" Y: R- |; H/ F1 N* D8 n
void SysTickHandler(void)
' t7 ?- I2 L) Y' H7 Q: @. y5 h, w+ z3 N' H- _
{
4 E1 O' s4 \, G0 P$ Y
1 l! P3 n2 m* j; x    TimingDelay_Decrement();
0 \8 y2 [/ \6 \5 C; b+ _4 |5 A
5 ^. r# [2 Q+ [( L1 {}- N! H. W/ z- V) R  [: T

! C+ N0 H8 f3 X0 n( l0 F& c* I- @3 b从上文我们通过装载的计数值72000知道每1ms发生一次中断,在中断函数中调用一个函数TimingDelay_Decrement();-----即每1ms发生中断时就调用到此函数;  v- R4 t4 _/ B- |# E
5 C& G6 t+ U; t% a
下面我们来看看TimingDelay_Decrement();在干些什么?
0 i! F: n1 W. c2 }; N1 j6 m: E3 d! i) d  i6 k9 A' ]6 t$ s
  1. /*****************************************************************
    ( R1 r3 F/ p3 L# T1 z

  2. $ F* d& l7 r# H# p' g8 B
  3. *函数名称:TimingDelay_Decrement* V( V3 \+ G5 @: \% O

  4. 1 W; {3 n& [# q% A1 c/ p
  5. *功能描述:中断里调用此函数,即没发生一次中断,此函数被调用,此函数里     3 }) b- O6 g! K6 x6 i( Z: w
  6. 9 P9 V& T, s/ K8 q
  7. *          的变量TimingDelay 相当于减法计数器* j0 E/ X) y) \# M% A
  8. / V' V2 E1 T/ u; b! V& e" k
  9. * 6 b3 B& s2 C. X$ e: t) {4 r
  10. 0 a+ [$ F( @( H, a8 I; H" S
  11. *输入参数:无
    / V; h/ S* h+ I, E+ Q3 q: \( a

  12. ( d3 [# V6 g8 W. M- u
  13. *返回值:无, w1 Q1 a, A% f; s- R
  14. 0 r3 N0 w- g" o; {, S  W4 `
  15. *其他说明:无5 S0 k/ j' r) U5 n; H  ~9 ]/ [2 g6 G
  16. & H% J7 S8 g8 @  M; u6 }
  17. *当前版本:v1.0
    9 P* J: G6 [/ z% ^

  18. 4 o: l" D% E+ o- e, D
  19. *作    者: 梁尹宣4 o0 d/ \! z# ^( h! w/ e. a
  20. " R5 W1 a* N% B4 f) J' \" M
  21. *完成日期:2012年8月3日' L' Z+ g% x8 h5 I3 j+ a

  22. ; Q  b3 z! C2 V, y5 M" u5 |( J
  23. *修改日期      版本号      修改人      修改内容
    4 k* U, O: f) [
  24. 6 V1 q8 [1 c/ O; t2 g* K2 _! l
  25. *-----------------------------------------------------------------
    - p2 _: }6 ?  ^

  26. , s2 d3 m* H6 B4 N
  27. *0 V* `- m5 }: I/ {6 z7 _
  28. 7 ?+ `. K; g/ p9 Q$ d/ ?( `% I
  29. ******************************************************************/' ?9 o  b! k" f7 P  h

  30. 5 i$ @5 w; D( W

  31. 7 Q1 W0 J9 ?/ X" f9 d% O" ?* @
  32. 9 k% N: Y& g  X1 p) a
  33. void TimingDelay_Decrement(void)  : P  E% n' E% k1 J4 N% K& [

  34.   c/ g  I- q) D) E4 f- v
  35. {  : p3 Y7 k& w; x. F
  36. - o) w+ T5 j# M4 d% ]
  37. . o  s' ~) c) N4 f/ X3 d

  38. ! k) a4 t5 u& Q2 C
  39.   if (TimingDelay != 0x00)  . V" M" G( F) W# a- X

  40. 2 U& v5 i( `3 G# }- l
  41.   {   
    ' c0 _4 T% H' `; d4 O0 ^! L

  42. 8 }! y% N7 ?. u5 G4 |4 O4 \
  43.     TimingDelay--;  
    + J! ]* Z- a9 a7 E3 z
  44. / b# l: B1 M; y6 E
  45.   }
    + ~  M9 K9 n- j  J( X
  46. 5 R% G. V" s: J. {. }# ]
  47. }  " K0 f' \0 O& y
  48. $ G7 o# A/ S9 ^% ^* L1 U% N
  49. 我们看了TimingDelay的定义,又看了还有哪些函数调用到这个变量,如下:: R7 i1 P. {: c% i9 P( K
  50. % W7 M: e0 h/ O, h* L7 b2 Y
  51. /*****************************************************************
      g& }! v; N( S0 K3 `# b& g
  52. 9 k+ ?4 w' |' R( [
  53. *                                        全局变量
    * |" m& q8 _* ~, F/ e$ R
  54. . G/ S1 M- W1 n( K4 W) E7 z
  55. ******************************************************************/" `6 T+ B# k! U: `

  56. : y  q- {$ d& Z! ]2 Y2 y

  57. 4 A) u+ x+ e7 N. o1 @: n( j$ ~9 r
  58. 5 Z3 s. {3 @; n8 M9 l
  59. static __IO uint32_t TimingDelay=0;
    1 v; W6 E* L; N+ u8 S2 H. q

  60. + x' d* @, m4 Z0 `8 [9 E. h

  61. + u+ s, q2 D3 m4 u0 y9 ~

  62. $ [% i2 t& @) R- F" W
  63. /*****************************************************************
    * u% s% m  B# S- b4 G. A

  64. * B9 M5 A; g6 G3 b6 p1 V
  65. *函数名称:    Delay
    ' M9 w: I9 ~% x& g

  66. / n+ A- D+ u: E  }+ `! h3 A2 @2 e
  67. *功能描述:    利用系统时钟计数器递减达到延时功能
    & T: s& I) E# j. ^
  68. . s" l% K4 s6 [
  69. *
    9 @) {* F# _2 k/ q

  70. 6 c# h  t8 x- s5 i) g
  71. *输入参数:nTime :需要延的时毫秒数! z% r- [" g& Q5 I; L5 ?
  72. ; p3 e( d: s" K# Q' J% G
  73. *返回值:无% N$ L3 t2 q+ M* i& G
  74. % c- O! X, m) S" N* I
  75. *其他说明:无! ^0 Z* H( X2 \% t
  76. ) L% }( |0 I  U9 y
  77. *当前版本:v1.0. o6 i3 ]9 N+ b" w6 R* `% ~$ }

  78. ' ~" d1 @5 }8 c
  79. *作    者: 梁尹宣
    % Q" t9 L1 J2 w3 A% w% B, C
  80. " K$ F& ?$ q% P. @: k4 h" X
  81. *完成日期:2012年8月3日
    5 r. p( E# i+ q! j* q' Y
  82. ! v* A+ @7 g1 ?/ h' w! [& g* ^
  83. *修改日期      版本号      修改人      修改内容
    7 B9 F" L5 D3 U. h
  84. , K. q- @, |+ h# h+ e3 d  ]' c) }
  85. *-----------------------------------------------------------------. @/ Z" W  u! l' a6 n; {, u  _
  86. : n: S" H: x9 {! L1 S1 G' i' A
  87. *
    9 k( s; B: |. n2 c: o* L
  88. . C$ m" Q2 v& f$ {2 f; H. W4 L
  89. ******************************************************************/
    ; v  D- R+ |& B# O

  90.   G2 F0 b3 m" U9 E) U# A

  91. 8 c  d; T% w1 d8 ~9 B' s

  92. 3 b2 o: e8 O, L( O
  93. void Delay(__IO uint32_t nTime)//delay被调用时,nTime=500
    . \  D/ B; U: b+ x5 x

  94. , b& g1 t; G" \
  95. { , }+ u0 M6 y- D% r7 R' P
  96. 0 c) V( n" c6 h! d
  97.   TimingDelay = nTime;' g( S/ B6 M5 w% ^8 L  n% q
  98. & E2 h. b' y" N7 K% J
  99. & Z9 N, O( Z5 ^8 ?9 T- {9 Y
  100. ( P: V# m7 w% [, O) J6 R
  101.   while(TimingDelay != 0);
    # q# U9 G9 j5 {' {

  102. * @- r" {& f/ G" O( [
  103. }
    5 l4 r1 s9 M) y- H( s
复制代码

0 P8 L3 c% G" i* k) k2 b* T) J- [通过上面几个函数我们知道了,在调用Delay(500)即nTime=500;在后在Delay()函数中TimingDelay =nTime;(即TimingDelay=500是它的初始值),再TimingDelay_Decrement(void)函数的作用就是把TimingDelay- -;每毫秒进行递减直到减到0为止;这样就起到一个延时的作用;
2 F7 V' T0 O7 K. d2 p# i0 l& C2 S& ~3 K9 K
现在我们做出来的Delay(1),就是1毫秒延迟。Delay(1000)就是1秒。8 _) D, a) O1 N0 Q  S# u: K
5 _- \3 P4 H6 d
  我们来画个图,方便这几个函数间关系的理解:
9 w; U! {+ r3 d* \: d) [% {" e& H. _3 {! O( v1 N1 c8 |) C: w
1345388401_3109.jpg 5 K+ Q; a# v2 Z9 ]* U' ]  Z
8 z( F" J' d3 c9 q+ |+ P
我们在返回到主函数main()中看这几条语句:红色标注de
/ Y+ s' j. C6 O, @. E! X; J% e& a- k- D1 i3 u3 P
  1. while (1)2 z+ U. i+ j: Y- }; ~  Q; t; a8 g$ {4 q
  2. 2 J" g. l: d1 L6 k& h8 t  E
  3.         {$ b/ h8 K1 b0 _5 U& o6 E0 S

  4. ! p2 f4 ^/ f* i% p% A2 c/ l4 N4 {+ f
  5.              //测试代码:测试定时器功能,通过延时来测试$ O, B  I/ P: A5 z! W4 t1 R  [

  6. ; l( L7 p' Z3 F! t
  7.              GPIO_SetBits(GPIOC, GPIO_Pin_6);      //V6
    0 R' [5 k0 a- v4 j7 o' z/ z) B1 G

  8. $ Q9 o! U# O0 U3 E& p
  9.              Delay(500);9 @2 o, h! d; H0 q0 j, r

  10. - |* y9 ^+ F$ L0 @& ]' q
  11.              GPIO_ResetBits(GPIOC, GPIO_Pin_6);         //V6 * A+ m" B& T6 \; w2 D0 z. `

  12. 1 d; ]) l" b9 G# w7 v  |# c
  13.              Delay(500);
    " g' b% a& ]% Z: Z* U

  14. 7 ?: c- s8 G" b2 U9 D& d6 q
  15. 5 B7 s, \% J# U
  16. ) p9 ^4 E$ n- n6 t* Q9 ^
  17.             //功能1代码:每500ms发送数据6 R% k* Q! @8 v# Z/ N8 s
  18. 5 m. j4 J( ^( |
  19.                /*
    3 X  _0 z/ E# a& ^) A$ O8 t( b) M

  20. - z8 h2 h# v3 ^% a( Q! V6 r5 [
  21.                       UART2_TX485_Puts("123450");  r, Y7 w( P+ z7 c

  22. . B$ V, ^3 U  s3 ?" K
  23.                       Delay(500);, N  w  \* ?) h& n: P) ~
  24. : r* J7 s6 E; G7 }+ a
  25.            */
    # J2 ]' W1 T+ S4 Z( D; w

  26. 1 C/ C6 y5 O* N  Q$ X- {
  27.             //功能2代码:上位发特定指令,中位机执行相应操作* I9 Y1 [; l8 s* ^4 r
  28. + q' i. Q6 J, O; U* j; y
  29.               //     RS485_Test();; z- Y; ~8 m- \. Y; x5 O
  30.   E1 o5 f6 `5 j) B4 E
  31.               }     
复制代码

. [6 @# y+ Z) n* b4 E0 {经过上面系统定时器的分析我们知道Delay(500);是延时500ms ;那么LED就是每隔500ms闪烁一次;+ m6 M3 b, V2 R9 G
: E6 {) F- `1 f6 G/ A) K
上面有关系统滴答定时器的应用讲解基本完毕!' \5 m! b3 [  Q8 |, J- m; d
/ ~9 a% F+ R0 P7 ?+ x
有关SysTick编译后的源代码包,(其实客官细心的话一经发现上面代码含有485通讯代码,
$ n6 F5 i3 T- }
$ x6 y& B- w* v$ A9 k3 g' |  Q! J+ W9 I; _+ N; Q. A
下面我们来看看一下参考资料的问题,一边对上面我写的博客有更深入的理解:+ `) B/ O5 |+ t9 c

# Z3 h, p- p3 H- O: |% c& Y) @; f《Cortex-M3权威指南》4 {9 |6 ~/ f( |+ }5 Q

3 a2 |# Q% J0 s- N& [& t# Y《Cortex-M3 Technical Reference Manual》
% {7 h! y/ _9 J* r: E
/ `9 U9 k9 }0 O+ W/ ]Q:什么是SYSTick定时器?

4 Y# T/ O0 P5 m4 u) |/ I$ k7 y0 _- H" p
SysTick 是一个24位的倒计数定时器,当计到0时,将从RELOAD寄存器中自动重装载定时初值。只要不把它在SysTick控制及状态寄存器中的使能位清除,就永不停息。
* E; `- n& @. u
! h9 D& k/ V* I( ?Q:为什么要设置SysTick定时器?
) t. P4 ]; c/ q" \" d/ X

, F) A3 P/ P3 A* i% B+ E(1)产生操作系统的时钟节拍* ?7 R5 Q3 e( F$ J; }

* v4 W! s  l5 _4 c" t/ ZSysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
+ c* q4 [1 m7 J6 Q% _# V5 J& I( J" F" Y  q5 q  y: W5 z
(2)便于不同处理器之间程序移植。
3 D8 o* ~7 y* c4 G& O$ O1 a+ y# l6 Q; b3 m$ R4 K* o
Cortex‐M3处理器内部包含了一个简单的定时器。因为所有的CM3芯片都带有这个定时器,软件在不同 CM3器件间的移植工作得以化简。该定时器的时钟源可以是内部时钟(FCLK,CM3上的自由运行时钟),或者是外部时钟( CM3处理器上的STCLK信号)。
: P  V, O. k( X1 H
$ Y' @( E; G7 x# w* D" T, V, E不过,STCLK的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可能会大不相同,你需要检视芯片的器件手册来决定选择什么作为时钟源。SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。它使操作系统和其它系统软件在CM3器件间的移植变得简单多了,因为在所有CM3产品间对其处理都是相同的。0 @" |' `" p. V1 r$ r
! A# k5 ~! b6 i1 Q( J: E4 g
(3)作为一个闹铃测量时间。3 }7 l0 U' j9 Q$ |1 S

" T- |: O6 Q- nSysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。
( V5 R) m5 M3 Z  ]6 w7 b
  N  C: C/ ~0 J! Q6 b: zQ:Systick如何运行?
" u! }  ^+ v' V4 p4 ~9 f; h
* v- ^* n& k6 D9 j# G$ j2 J首先设置计数器时钟源,CTRL->CLKSOURCE(控制寄存器)。设置重载值(RELOAD寄存器),清空计数寄存器VAL(就是下图的CURRENT)。置CTRL->ENABLE位开始计时。
9 A& u$ R' X* ^5 d- ^" n
2 _2 h- @* m& C/ Q' R. t如果是中断则允许Systick中断,在中断例程中处理。如采用查询模式则不断读取控制寄存器的COUNTFLAG标志位,判断是否计时至零。或者采取下列一种方法
9 R" S' a1 C: P% {$ L3 x4 A. V" R4 O! s' A1 t  m
当SysTick定时器从1计到0时,它将把COUNTFLAG位置位;而下述方法可以清零之:7 }5 C2 u0 U  `" r. C: f

2 K* m- n/ U4 Y, Y1. 读取SysTick控制及状态寄存器(STCSR)
* Z% |: n( s' u( f* s$ t! a$ ?; a2 \( X% n' o3 [3 P  f& v7 g% K, M
2. 往SysTick当前值寄存器(STCVR)中写任何数据- M) t' o- q# b" p
& I2 T+ d' h* D9 m2 u8 a; X
只有当VAL值为0时,计数器自动重载RELOAD。
0 I+ H  a8 y3 R% l. H2 s& s4 ?
7 y- n  T" C; c* [3 E0 V" zQ:如何使用SysTicks作为系统时钟?
! ], @* r: ]  @8 U0 U, ]5 H
, n5 q& C. D; P, `" L, J/ e7 [SysTick 的最大使命,就是定期地产生异常请求,作为系统的时基。OS都需要这种“滴答”来推动任务和时间的管理。如欲使能SysTick异常,则把STCSR.TICKINT置位。另外,如果向量表被重定位到SRAM中,还需要为SysTick异常建立向量,提供其服务例程的入口地址。1 _- K7 d. x6 J% e/ M& H

% I: Y" x0 m' M5 [5 o  S; \- h) [$ O- _, G
收藏 评论0 发布时间:2022-5-24 10:21

举报

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