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

STM32 SYSTICK详解

[复制链接]
行色匆匆 发布时间:2017-12-25 22:11
转载什么是SYSTICK:
; g1 i' s2 |5 y6 V5 p这是一个24位的系统节拍定时器system tick timer,SysTick,具有自动重载和溢出中断功能,所有基于Cortex_M3处理器的微控制器都可以由这个定时器获得一定的时间间隔。  i( g8 E$ h9 B
作用:. L5 z* a' t/ x% K; h
在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。要解决这个问题,可以使用实时操作系统(RTOS).8 y# ~3 {+ Z( @
因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。
  l& s3 Z, H7 b( s) S2 j* _- v- y/ O5 d微控制器的定时器资源一般比较丰富,比如STM32存在8个定时器,为啥还要再提供一个SYSTICK?原因就是所有基于ARM Cortex_M3内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。而使用RTOS的第一项工作往往就是将其移植到开发人员的硬件平台上,由于SYSTICK的存在无疑降低了移植的难度。
- r& ?) I  n1 X
2 [! X2 s: h0 c4 V) h/ Q  SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。
8 ~5 q* n% I1 B4 A+ P& K7 ?7 `8 d要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。1 @) M5 u* p$ k$ q4 Y
8 O& E9 c8 B. |3 }/ e4 w6 `
时钟的选择:
) _, l5 ]* q5 p+ S! [/ w1 p. q8 B用户可以在位于Cortex_M3处理器系统控制单元中的系统节拍定时器控制和状态寄存器(SysTick control and status register ,SCSR)选择systick 时钟源。如将SCSR中的CLKSOURCE位置位,SysTick会在CPU频率下运行;而将CLKSOUCE位清除则SysTick会以CPU主频的1/8频率运行。( t# r/ j5 {9 l/ x! ]0 D, r$ D/ P
3.5版本的库函数与以往的有所区别
1 M% Y' E5 @% u不存在stm32f10x_systick.c文件,故原来的一些函数也不存在,比如SysTick_SetReload(u32 reload);SysTick_ITConfig(FunctionalState NewState);等/ w, J; V% D6 n6 ~
  D2 R  h( P" ?! K9 Z/ g
在3.5版本的库函数中与systick相关的函数只有两个! |% Y! x5 J/ P6 x
第一个,SysTick_Config(uint32_t ticks),在core_cm3.h头文件中进行定义的。
3 _7 L! F! D9 `* O2 M/ {9 Q1 N第二个,void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),在misc.c文件中定义的。
$ ?. S4 B/ ?& p' T" ~
1 d! y* c# L9 d0 XSysTick_Config(uint32_t ticks),在core_cm3.h
0 Y' C* G9 @% s主要的作用:
8 V" }( \# R6 T$ Y( x7 G2 \1、初始化systick
' t, |: b8 _7 H, W+ o! i2、打开systick
- j$ C& V) c2 v! }( O4 n5 j0 ]. ]3、打开systick的中断并设置优先级
2 Y* R# t) L% Q+ y$ l4、返回一个0代表成功或1代表失败
& y5 o' N& _$ a6 e+ d0 O6 M; `注意:
( H8 m0 a  q# h* N/ F- G: VUint32_t ticks  即为重装值,
3 c; `+ @1 j: B这个函数默认使用的时钟源是AHB,即不分频。8 z, q6 D$ t! @3 D% I$ t
要想分频,调用void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),( ^5 w( w2 E1 b3 n8 r5 }; C- A
但是要注意函数调用的次序,先SysTick_Config(uint32_t ticks)," d& F/ q0 d" ?) w; w9 m3 Q; v
后SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)8 u6 C7 `$ k4 m! [& B

$ V/ R8 Z' T& H8 i/ }6 k
0 U% L6 o3 a& o: f4 x- I5 v- d! x$ M

0 ?8 e/ a0 U1 Z/ d/ {# ^函数说明:
" b2 i8 ]5 N- c$ h7 i
1 @* j9 _% @( E& P/**6 B, a" ~* I2 c3 }  I
* @brief  Initialize and start the SysTick counter and its interrupt.8 s' e  B& ?8 z& m- l
*
7 ~, y! b9 o( G  d& T8 d7 H* @param   ticks   number of ticks between two interrupts
. [. A) a4 G0 G1 H* @return  1 = failed, 0 = successful$ A' V* \; a: }3 ?( n4 S) f8 M
*
& k5 q# i: C: _9 W8 U- i4 {* Initialise the system tick timer and its interrupt and start the
5 z8 c% H8 e3 Z' u, n) e* system tick timer / counter in free running mode to generate  `& ~! N" D# P7 \9 S
* periodical interrupts.
9 n- V4 M+ H* A. P+ _*/) i! G+ L2 h. L7 p
static __INLINE uint32_t SysTick_Config(uint32_t ticks)* u# p' ^" V8 }  W- }% c
{& {& M8 S7 H/ S& M* Y, M
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            ' X. i0 d& g$ H2 z8 E, [3 }8 n2 V
  /* Reload value impossible */重装载值必须小于0XFF FFFF,为什么,这是一个24位的递减计数器。
' j3 J# b9 n6 W1 ~6 Y
& i* |2 q  M7 V  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;$ c& T; y$ S8 w
     /* set reload register */设置重装载值,SysTick_LOAD_RELOAD_Msk定义见后面
& s/ W) }0 V2 O9 N8 J  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
+ h* Q* P) T9 F: C* A" r# |/* set Priority for Cortex-M0 System Interrupts */
$ g5 @4 M+ C, ]! y2 _, X/ P4 n  SysTick->VAL   = 0;
3 P" t% u8 A- I- q4 @  /* Load the SysTick Counter Value */' u' Y" Q8 N& ]% A
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
* A- l1 |8 c/ s( w! K                   SysTick_CTRL_TICKINT_Msk   |# o2 g5 B( v- m! B: r) A1 {, n
                   SysTick_CTRL_ENABLE_Msk;                  
$ d; P6 h6 ^% c' l0 s/* Enable SysTick IRQ and SysTick Timer */
+ K/ i4 p" t7 w: n& t( I  return (0);
. F# C% r7 t# ?# d# h  /* Function successful */. x$ c9 Q( S: g3 t* R' M
}
) z- G+ t$ C' l+ S' `6 g( k#endif
( z) I3 N2 M1 V9 U( s与systick相关的寄存器定义
  e4 c7 N9 o4 K2 X  M/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
+ O0 O. R4 O3 Q* p1 Y  memory mapped structure for SysTick& K+ D  o4 p% E+ f9 U
  @{' ~4 t  `5 J; d
*/
$ u0 L  ^/ s+ L7 K. [typedef struct
* K- U9 y3 x4 K# s3 Y! r$ g& h{
- s: P# g' O; t- v2 b  __IO uint32_t CTRL; /*!< Offset: 0x00  SysTick Control and Status Register */
  G/ }) X9 i3 l  __IO uint32_t LOAD; /*!< Offset: 0x04  SysTick Reload Value Register       */
; n8 T0 F* N. ~& Z' ]  __IO uint32_t VAL; /*!< Offset: 0x08  SysTick Current Value Register      */9 I3 ~, F- h9 @. a5 ^9 {% ^
  __I  uint32_t CALIB; /*!< Offset: 0x0C  SysTick Calibration Register        */- `% X" r7 S4 A
} SysTick_Type;
8 l- p& O" F& B( p1 \4 g5 T9 j2 M5 k0 ~, D
与systick寄存器相关的寄存器及位的定义3 y6 g& h! D: j2 h4 r; l* H  Z

# D. C% K7 q& I  k' j- l: }6 v/* SysTick Control / Status Register Definitions */控制/状态寄存器2 v2 M, X+ Z! V/ W- a
#define  SysTick_CTRL_COUNTFLAG_Pos  16      /*!< SysTick CTRL: COUNTFLAG Position */: t, `& y& H# l
#define SysTick_CTRL_COUNTFLAG_Msk         (1ul << SysTick_CTRL_COUNTFLAG_Pos)         5 \1 H" Q$ x  {  E0 ]6 s! M# y. v% l
/*!< SysTick CTRL: COUNTFLAG Mask */ 溢出标志位/ Y6 ~8 f1 R$ |+ Q7 ~0 B4 Z

& F8 U+ k! V9 o6 Q#define SysTick_CTRL_CLKSOURCE_Pos   2       /*!< SysTick CTRL: CLKSOURCE Position */
' L# a; [3 d( H+ t: E1 L#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)  9 A: Y: q4 ?. p7 L* f
/*!< SysTick CTRL: CLKSOURCE Mask */时钟源选择位,0=外部时钟;1=内核时钟
& T8 }9 n2 s* h  m5 l" K) U) U2 W
#define SysTick_CTRL_TICKINT_Pos      1        /*!< SysTick CTRL: TICKINT Position */: s! s) y3 J+ ]% u3 ~4 s
#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)         
' K: d: i0 p8 B; j+ V0 d/*!< SysTick CTRL: TICKINT Mask */异常请求位% L) c0 Y- n5 |) N* G& c
" r4 l; b) `" }. j. C# V! }
#define SysTick_CTRL_ENABLE_Pos             0       /*!< SysTick CTRL: ENABLE Position */! p4 D% H; k  m2 r+ n3 j' N/ }; q
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)               ' i! g2 Q7 N  F( x7 p# `7 {" R7 U
/*!< SysTick CTRL: ENABLE Mask */使能位
6 H1 w& [- L+ Y' ?- z" `" B3 ~/ A5 \8 `1 H! g- E2 W  Y
/* SysTick Reload Register Definitions */
) O4 r/ z, A5 s( z3 V& M1 _#define SysTick_LOAD_RELOAD_Pos             0    /*!< SysTick LOAD: RELOAD Position */
5 {8 u9 d' t+ x/ O1 T$ H$ V#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        
6 Z) D2 S5 y4 }! s/*!< SysTick LOAD: RELOAD Mask */' C; v- u: |; D) e
* D$ {- {! U) \& I% M5 l; p! h3 Z
/* SysTick Current Register Definitions */5 s5 ]6 `+ \  z: p" X+ ^; Z
#define SysTick_VAL_CURRENT_Pos             0       /*!< SysTick VAL: CURRENT Position */4 w7 r0 o; p6 l! m! I
#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        , I  R# c) ~- }9 s
/*!< SysTick VAL: CURRENT Mask */, T9 C: d8 @  d7 R2 y3 ]' `
" m( v# S( t# P" h- ^
/* SysTick Calibration Register Definitions */$ \5 n5 W" w2 p1 Q8 J2 {0 E' c9 T- {
#define SysTick_CALIB_NOREF_Pos            31      /*!< SysTick CALIB: NOREF Position */
  A# m/ g2 G' ^$ a: ~% l, [. j#define SysTick_CALIB_NOREF_Msk            (1ul << SysTick_CALIB_NOREF_Pos)              
9 ]! q. o7 N9 L7 X+ ^/*!< SysTick CALIB: NOREF Mask */
# o6 c: `, J4 N% B5 y3 k0 ~
8 b# T7 G/ z3 L  Y/ e0 S8 l, P% j$ ?#define SysTick_CALIB_SKEW_Pos             30       /*!< SysTick CALIB: SKEW Position */# C) `; ^+ R9 |5 b) ]
#define SysTick_CALIB_SKEW_Msk             (1ul << SysTick_CALIB_SKEW_Pos)                 I/ y6 I% _5 L' j
/*!< SysTick CALIB: SKEW Mask */
2 E* ^) I* _6 e7 K9 `1 P0 y, p+ o0 t7 j% c
#define SysTick_CALIB_TENMS_Pos             0       /*!< SysTick CALIB: TENMS Position */
0 `: v) \/ H6 ~. m. O#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick CALIB: TENMS Mask */
6 S% E/ h& r3 g. k& R& H3 x2 B/*@}*/ /* end of group CMSIS_CM3_SysTick */
+ [# M6 Q  z8 ?8 p6 n
4 C5 O6 T% B; C, z与systick相关的寄存器的说明
1 j) O# r! u& ]$ n9 h- P8 x# h7 \
8 k! E$ S# g* H/ e  O1 h0 E4 P& B. B6 y! S, E$ g% S
, m( |4 C& q' {

2 \$ F7 n0 v3 A* Z
! x) m" ?, q( A4 U% K2 U
. R+ C( ]: n( m; D- l& W7 tvoid SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
: e' r+ L, ]% |* w' a( I作用:
" s" D1 {$ Y  h选择systick的时钟源,AHB时钟或AHB的8分频
* _& M& @+ w5 [$ }默认使用的是AHB时钟,即72MHz/ {) P% S& L- k9 r7 k
( a  h3 N1 c6 z$ H
函数说明:
- [0 S6 ~% ^4 W/**/ @7 O5 @! R& B- z# R& V! H
  * @brief  Configures the SysTick clock source.0 ]# U9 U4 i" e4 o( |# ]5 n
  * @param  SysTick_CLKSource: specifies the SysTick clock source.$ [2 E7 j2 x" J8 V6 a6 g3 e
  *   This parameter can be one of the following values:4 [$ A$ M! x, p- V/ O( |
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.0 Q/ P; S7 q% w+ [
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.0 r$ b6 R4 N* I) E- }
  * @retval None. @8 W" K+ ]5 L6 Z! f# }
  */1 D% j% u, W, v7 W& A7 Q
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
/ x  f' i+ d$ }2 I; h$ x{- ^, e) ]/ Q+ X( E5 B+ A0 R
  /* Check the parameters */
* p& f0 @1 `8 n( f% R$ ]2 i* f  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));( [. R1 h* ~) C- s
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
/ E$ k/ b/ ^9 [1 S2 B  {# l8 g/ C+ a: |3 b! X1 B3 J" A
    SysTick->CTRL |= SysTick_CLKSource_HCLK;
' ^) P# Y: z4 A" d. s  }; a; c1 R" m$ r2 e
  else4 J5 H: G$ d1 u3 b# p% W
  {
/ ]9 b; @8 M" v$ y" s    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;4 G7 ]7 m0 _# @/ m# V( Q
  }- j. D( c% b3 F% f
}
1 v2 ]3 _* V: [# X- x  t2 `" j3 p7 [8 m& y) G$ N: q
) e  ?; G# n" R+ `$ l
Systick时钟源的定义:
2 g6 T" V7 L1 ?% z/** @defgroup SysTick_clock_source) v; A: R" `. J6 w7 ^' i" l/ M
  * @{
4 f/ o/ W) k3 n# p( V# r  */
% j, }4 ~4 o; Q3 x: B
: k( M. j" j- F$ j#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)//将控制状态寄存器的第二位置0,即用外部时钟源6 E7 H& W6 i- ?  q& h
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)//将控制状态寄存器的第二位置1,即用内核时钟
2 F; g+ L! W' D4 ?6 Z% |; J#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
7 O' H/ e6 x+ O" f                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))  \3 n. P- g% I! n/ M6 r0 J
+ l; e! R+ L) H; a
Systick定时时间的设定:2 b5 O8 w8 X  e+ ^3 @4 |/ @$ Q

% }" L3 w$ g* [* D$ R5 e5 I  s重装载值=systick 时钟频率(Hz)X想要的定时时间(S)# Y4 K, o, t8 M
如:时钟频率为:AHB的8分频;AHB=72MHz那么systick的时钟频率为72/8MHz=9MHz;要定时1秒,则1 [- u4 \. b9 v2 r. N  w( G: k
重装载值=9000000X1=9000000;, _5 ^7 `, ]) b1 C
定时10毫秒
, K6 ?8 w5 ^4 G) j重状态值=9000000X0.01=90000
2 k) ?+ M) t) a9 N5 pSystick的中断处理函数,5 k2 Q3 @9 g- B9 w* R* r- J
在startup_stm32f10x_hd.s启动文件中有定义。
; W2 O0 c& ~: q/ w- p$ {  H$ U' PDCD     SysTick_Handler            ; SysTick Handler1 S* _# x; E' l- h& H8 }/ g
根据需要直接编写中断处理函数即可:- @  l( a/ w$ Y7 V& P
Void SysTick_Handler (void)0 e$ ]4 t3 ]2 p' E
{ ;}. }! i; R$ P: X# i0 g" x! t
注意:
3 v7 Y, P. b5 ^- g+ ^6 D$ u如果在工程中,加入了stm32f10x_it.c,而又在主函数中编写中断函数,则会报错。
# w% _! K7 G0 b* h* I0 J0 b) E
( k7 s$ ^8 G( w3 g' R因为在stm32f10x_it.c文件中,也有这个中断函数的声明,只是内容是空的。
, ~# m6 Q; O# ^8 I: m1 s/**
$ [& a/ W: W: N* o9 a' H0 R) ?  * @brief  This function handles SysTick Handler.
- t6 g% K3 v, X1 `2 H2 y  * @param  None1 G% F; c; W# s$ m. r4 z. ]% f' G
  * @retval None2 v+ a. m! Y4 x
  */# `" [' g! H# j/ i3 p* I0 m
void SysTick_Handler(void)
/ v2 [. Z3 k5 p1 r) V- k5 w{( }2 L% H% w, n+ _; g2 L( R
}- I+ W0 P: y5 J
中断优先级的修改
- V- g2 T5 s% T在调用SysTick_Config(uint32_t ticks)之后,调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)。这个函数在core_cm3.h头文件中。, i# v! s8 ~+ G
具体内容如下:5 x+ h  ~0 @9 V  a5 R
6 t) H  u8 v2 g' I7 L6 _1 S
/**
# N. E9 p* [, _) }* @brief  Set the priority for an interrupt
  O9 I% b- J6 |0 [8 i*
: |8 V! G; {2 x" o* @param  IRQn      The number of the interrupt for set priority5 F" t* E- W4 Y+ {$ ^. r# R8 o
* @param  priority  The priority to set. Y8 V- D) l' N, a
*9 l9 Z" k6 m' a3 B
* Set the priority for the specified interrupt. The interrupt
; a- E' S7 i, ^+ v% w; M& t. ]- G+ O* number can be positive to specify an external (device specific)
" r* j2 b7 q. d$ J5 Y* interrupt, or negative to specify an internal (core) interrupt." s: T( \' C& u* i1 ^
*
. Z. |  b# ?4 y7 U% W* Note: The priority cannot be set for every core interrupt.
7 k+ c, ^( I7 ^( Y. o  N3 C*/$ W! R  T# _4 G

, V! g$ P; O, O1 l# h7 L9 v9 T( W; L' P

4 S$ N, ]3 J: t9 v: o+ `+ ?1 }5 W- w- D5 C' ?+ ]* W( \1 e" F
static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
3 x4 N  s, S+ x# v1 j{' p% n$ }+ {7 u' K' o, I( z
  if(IRQn < 0) {4 b1 q! [" S! X' b# m3 s
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */
5 ?+ G2 \* V9 z) @- [) S. y  else {
  i9 i& q3 n- l. K$ i    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */( f/ b, [! F' b2 U/ \" k
}( i9 ]& d$ K- W+ \. _9 j" {
5 G7 n; N; A6 w; {7 A
+ u( X1 r. k* ]  e
下面以一个实例来说明:* ^" k+ G6 {% @, x7 O
利用systick来实现以1秒的时间间隔,闪亮一个LED指示灯,指示灯接在GPIOA.8,低电平点亮。
% `( a' n0 t5 j' N* E0 e9 B6 t& ?6 q6 t% h. T5 n4 \
#include "stm32f10x.h"+ k9 h1 m; R* e6 k, u: m; K' i3 n
//函数声明
& Q$ R: E% g' [6 n, ^1 e& Lvoid GPIO_Configuration(void);//设置GPIOA.8端口/ t# j' p- {6 a$ S
u32 t;//定义一个全局变量$ S- ]) f& d3 ^4 z
int main(void): L1 F% A7 ]: A* C, E3 @
{
2 H( r# ^( i6 I+ ^5 ?2 ~. v8 ?// SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);6 p2 w- s- w0 f( l
       SysTick_Config(9000000);$ ~( `1 j$ h0 u  J  Y
       SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);) y- `7 I. K/ _( Y4 l
       GPIO_Configuration();
, P5 @. c8 ^' e7 e       while(1);      . g2 |7 R# \5 t. c
}
& p( h* \1 \5 A' D/ K* e9 E. E8 S  Q7 \3 j2 K+ S) D; O
//GPIOA.8设置函数( o" h. [. f$ I/ _
void GPIO_Configuration(void)
5 Q% N- u) y% B1 A  R6 k{6 E* O3 U2 `' A; Y/ p8 x, i4 d3 k
GPIO_InitTypeDef  GPIO_InitStruct;//定义一个端口初始化结构体
. z$ {# W5 B2 o* x+ U) y% M       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开GPIOA口时钟9 l/ A3 d$ S; X: u6 k" b
       GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出
1 W& n/ j2 ~& b6 r       GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置输出频率50M
" B7 @. e& L6 v( Q       GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;//指定第8脚
4 ^! q% _( T# a* ~       GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIOA.8      
- T( n- O0 d, Y" Q6 s       GPIO_SetBits( GPIOA,  GPIO_Pin_8);//置高GPIOA.8,关闭LED
+ c- X& U% \! F) y, L: W& U! t2 j}
1 S& }5 @4 B5 \, K) v8 V//systick中断函数" d+ R4 e- g1 I4 w+ G* y. b* z$ v
void SysTick_Handler(void)
/ x" R* Z4 P8 B9 B{6 V# M0 ]( o# O2 e" U% q
t++;0 z9 `$ Z* ]$ _7 }6 }  w8 Q
       if(t>=1)
" u3 r3 e" U- f; R6 }+ n  d* B6 M       {: W' U: V& h3 W  z% o
              if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1)" Q; \! |% q: R. L0 _* d
              {GPIO_ResetBits( GPIOA, GPIO_Pin_8);}      + M* f+ H9 u* Q3 V" z/ x9 O4 ]
       }
6 }/ f" V0 p0 w  M9 y       if(t>=2)" s/ D/ I+ j' R3 `
       {
9 g& w7 E1 m, h4 i! M$ M              if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==0)7 G4 R; c8 ~; v% U
                     {GPIO_SetBits( GPIOA, GPIO_Pin_8);}) T9 k' E! ~  o' x0 n; Z5 e. ]
                     t=0;& B# h/ `# ^& w& P) u0 a; I% h0 X
       }
+ Z0 u. N* T' b& ?/ A7 m& P}
$ S8 r) j& q( `, p/ e' J" n( c, O$ m" l9 L  `
模拟后的结果
/ U' {3 T& w: j6 u$ z% S. g+ d& R+ S1、8分频后结果3 z$ n: Z9 h, E+ g) R
( U5 v% W; \7 j5 F, @/ d# x" z6 W

2 E( K1 J) j& E/ F9 Z8 P6 S4 T; f$ F1 k  [# |' F# f
: z6 Y! W( g' z, d
$ A; \8 @4 a$ R2 e6 F5 F" s
2、直接调用SysTick_Config(9000000);即不分频的结果,间隔为1/8=0.125s
* k7 W, {8 E5 K3 G
" `! U8 w# Z6 X+ G, o" F1 D, ]( u$ \8 R% e
总结:
% K) l8 ^) u, T0 t& V1、要使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可,
/ s! t4 ?5 L( g" K* X4 k3 s   自动完成了,重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。
/ {. u  d5 k* T& R. x2、要修改时钟源调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)。5 R$ E9 u6 ~6 @- n, U5 \( E
3、要修改中断优先级调用
( [6 f6 A/ y4 ]5 L6 }9 ^     void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
% ~4 N! S/ d5 r( ^: V+ K3 w# y应用说明:. x2 K2 q6 S4 Z/ e! Z  r' d0 w
1、因systick是一个24位的定时器,故重装值最大值为2的24次方=16 777 215,
6 Y& ~! ~8 I0 b% o7 J1 A7 r   要注意不要超出这个值。
$ ]. t& e# o" r1 V% i; f2、systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。) z/ d9 a& ^# }: M
3、每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。$ z1 |" b  E9 ?
4、采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。, ^2 y) w3 ?- @
收藏 1 评论1 发布时间:2017-12-25 22:11

举报

1个回答
zero99 回答时间:2017-12-26 09:21:45
重复了
" D7 _) v1 j+ @) p8 x4 E5 A" }
' l$ V( d  Z) Uhttps://www.stmcu.org.cn/module/forum/thread-606435-1-1.html

所属标签

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