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

STM32 SYSTICK详解

[复制链接]
行色匆匆 发布时间:2017-12-25 22:11
转载什么是SYSTICK:
: A/ f3 n8 ?9 D4 I8 I* N$ ~$ d这是一个24位的系统节拍定时器system tick timer,SysTick,具有自动重载和溢出中断功能,所有基于Cortex_M3处理器的微控制器都可以由这个定时器获得一定的时间间隔。
# x! t& |" s9 _& g: N* e( [作用:7 z8 x, o- J+ g
在单任务引用程序中,因为其架构就决定了它执行任务的串行性,这就引出一个问题:当某个任务出现问题时,就会牵连到后续的任务,进而导致整个系统崩溃。要解决这个问题,可以使用实时操作系统(RTOS).8 [) g4 H7 K, v7 o( x# ]- C
因为RTOS以并行的架构处理任务,单一任务的崩溃并不会牵连到整个系统。这样用户出于可靠性的考虑可能就会基于RTOS来设计自己的应用程序。这样SYSTICK存在的意义就是提供必要的时钟节拍,为RTOS的任务调度提供一个有节奏的“心跳”。/ u8 n; B0 ~8 T6 L+ a5 N. C
微控制器的定时器资源一般比较丰富,比如STM32存在8个定时器,为啥还要再提供一个SYSTICK?原因就是所有基于ARM Cortex_M3内核的控制器都带有SysTick定时器,这样就方便了程序在不同的器件之间的移植。而使用RTOS的第一项工作往往就是将其移植到开发人员的硬件平台上,由于SYSTICK的存在无疑降低了移植的难度。
6 }% N7 S9 ^7 f+ r, n
7 E* W7 F1 u( A5 ]( t* Y  SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。
( N5 y) M. B6 m要注意的是,当处理器在调试期间被喊停(halt)时,则SysTick定时器亦将暂停运作。
" _6 u7 X4 b' ]
1 p- _; k* E7 i2 n; v8 t( w时钟的选择:
& k1 O( l2 A; w1 a0 s% C) M! Q" K用户可以在位于Cortex_M3处理器系统控制单元中的系统节拍定时器控制和状态寄存器(SysTick control and status register ,SCSR)选择systick 时钟源。如将SCSR中的CLKSOURCE位置位,SysTick会在CPU频率下运行;而将CLKSOUCE位清除则SysTick会以CPU主频的1/8频率运行。5 ]" o: B& F3 f
3.5版本的库函数与以往的有所区别0 @0 J- w+ w$ O0 l, Y) ?; y- s9 E; }& M
不存在stm32f10x_systick.c文件,故原来的一些函数也不存在,比如SysTick_SetReload(u32 reload);SysTick_ITConfig(FunctionalState NewState);等
7 q  j$ e+ b5 _9 T1 T. c( Y# o* q& K# B' X8 z" ~! q+ W: ]8 Z
在3.5版本的库函数中与systick相关的函数只有两个
2 Z5 s2 X1 k6 E1 y+ v' ?. z第一个,SysTick_Config(uint32_t ticks),在core_cm3.h头文件中进行定义的。
% @% w8 d$ O. M第二个,void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),在misc.c文件中定义的。2 J3 i0 C1 z7 P. P+ [

% a6 L2 v1 J6 X" ^; A$ ]4 g2 O7 a. TSysTick_Config(uint32_t ticks),在core_cm3.h
- ]: m3 x3 {- W; T/ W主要的作用:# L& t" F1 j$ {. S* f" h' G2 O. h) l1 ]
1、初始化systick7 d, v6 Y! ?' @- ~6 n
2、打开systick6 Y% F$ a, s  B( C0 L% f
3、打开systick的中断并设置优先级  h" W8 L2 a* c9 }& \
4、返回一个0代表成功或1代表失败
9 v  O4 G, A6 ]4 g* s/ n6 }7 @注意:
. _" {$ I9 D# n+ M: [Uint32_t ticks  即为重装值,
  G2 Z& d" }$ H9 k4 k& N这个函数默认使用的时钟源是AHB,即不分频。
( U) b, j) _  c( [" ^% m' }/ K9 i* l, D要想分频,调用void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource),$ A/ i1 [! w# T; q' D% k7 V5 m$ U: J7 `
但是要注意函数调用的次序,先SysTick_Config(uint32_t ticks),
4 y, b' y( z: W* L& ^6 ?后SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
  C6 P0 {+ ^" B) m7 r' h# x7 s' _( U9 g6 V+ b' b

# a. P* H9 _# l5 ?9 D
4 }- Z2 i+ {& a$ r' q" r: Q$ R; k5 G5 S. \1 N. ]# q0 ~
函数说明:# t+ K$ I  o& U
, e6 U7 X% U9 e9 r7 V5 l
/**
% u% p- s$ u  C* @brief  Initialize and start the SysTick counter and its interrupt." T5 ]. _" o7 l
*2 |8 T8 u$ w% |5 W
* @param   ticks   number of ticks between two interrupts
% M' Q% D, T' J# l" @4 V/ @8 v* d* @return  1 = failed, 0 = successful
( H+ Y% C7 n' _1 E: Y4 v# v7 U*8 q4 b6 @6 w, D4 u) v
* Initialise the system tick timer and its interrupt and start the
6 H) t8 w4 q; B* ]* system tick timer / counter in free running mode to generate, j& f/ V1 e. x# _
* periodical interrupts.3 E% W: u( L0 w! n5 A7 w- Z6 z7 S% g
*/
& p) q, j3 X9 Z' Rstatic __INLINE uint32_t SysTick_Config(uint32_t ticks)6 Q% |7 s8 V  T) n7 U2 q" @4 x
{) s6 X7 q% p6 H2 _* N" p# C6 H8 y
  if (ticks > SysTick_LOAD_RELOAD_Msk)  return (1);            $ C+ Q' e# ?* S) W* ~- {; @  [
  /* Reload value impossible */重装载值必须小于0XFF FFFF,为什么,这是一个24位的递减计数器。2 a4 |5 r2 Y2 g5 T$ T

( k+ C! Q, a/ N0 j5 q" u% {) w. M  SysTick->LOAD  = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;
+ K5 M6 C5 T; ~8 o     /* set reload register */设置重装载值,SysTick_LOAD_RELOAD_Msk定义见后面
- A) W; S. U4 D$ t7 f! j  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
& M+ z  D, ?# E/* set Priority for Cortex-M0 System Interrupts */
' h/ u4 W. B- P5 J; D4 w  SysTick->VAL   = 0;
, I& Q- _+ B3 S6 ]  /* Load the SysTick Counter Value */& t  e& I2 _& E
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
+ P. L  S& a& K! {                   SysTick_CTRL_TICKINT_Msk   |
) {% z  s+ S9 K5 H1 `                   SysTick_CTRL_ENABLE_Msk;                  
( q' `% w# X% E; k& M- P5 i/* Enable SysTick IRQ and SysTick Timer */
% p* C' W( O$ V# O0 w$ L. W* _/ ?  return (0);" h8 g: h: ~3 C
  /* Function successful */
5 |; c9 z3 D3 I8 F. {}
) w  ^' S3 @" s; H' s0 R7 S. @#endif5 G) P5 e8 l, {7 d5 ?- u! X0 t
与systick相关的寄存器定义
7 {1 c$ V6 B. W; c: S7 O" Y/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
! R8 \1 F# H1 [9 w4 i# V  memory mapped structure for SysTick8 ]7 H# l7 h- `/ }5 B
  @{
6 c6 P! q8 o8 O) L7 u/ d; R*/* d  Y3 t8 b) s; z$ C
typedef struct- V- i; Q1 h% k% G0 Z# ^
{) ^& A  E/ N# I  k. r% D
  __IO uint32_t CTRL; /*!< Offset: 0x00  SysTick Control and Status Register */+ [3 A! ?* X" J) q* ~" H
  __IO uint32_t LOAD; /*!< Offset: 0x04  SysTick Reload Value Register       */4 x# {' U& b3 A" c
  __IO uint32_t VAL; /*!< Offset: 0x08  SysTick Current Value Register      */
. e: K1 P/ g1 P  __I  uint32_t CALIB; /*!< Offset: 0x0C  SysTick Calibration Register        */2 z. `' e. |& e5 W
} SysTick_Type;
' k! |7 s. l! D" s
8 T' H  z% ]! \( o: D& R) Q与systick寄存器相关的寄存器及位的定义
: E/ v) D" \0 D9 g% x9 X9 \5 \" A0 B* K) D7 K# I/ w
/* SysTick Control / Status Register Definitions */控制/状态寄存器$ x  h  |* E! }0 X7 S' V
#define  SysTick_CTRL_COUNTFLAG_Pos  16      /*!< SysTick CTRL: COUNTFLAG Position */
+ {$ I, @0 {! e6 ?5 I1 |1 L1 D5 _5 i#define SysTick_CTRL_COUNTFLAG_Msk         (1ul << SysTick_CTRL_COUNTFLAG_Pos)         + d- v, @. x- P
/*!< SysTick CTRL: COUNTFLAG Mask */ 溢出标志位, \" E2 I* e& n4 Q' K+ y

# x3 }  v3 d! h2 y' M, M5 q#define SysTick_CTRL_CLKSOURCE_Pos   2       /*!< SysTick CTRL: CLKSOURCE Position */
4 H0 F% b' E: a0 h+ X9 H6 G) o#define SysTick_CTRL_CLKSOURCE_Msk         (1ul << SysTick_CTRL_CLKSOURCE_Pos)  
4 d# Z! N; r3 f: ~4 n* u1 S0 c/*!< SysTick CTRL: CLKSOURCE Mask */时钟源选择位,0=外部时钟;1=内核时钟+ e! Z7 t: V8 b5 c  \# N" m2 ^5 X

+ G$ b! y5 {7 c$ o6 B9 Z, _#define SysTick_CTRL_TICKINT_Pos      1        /*!< SysTick CTRL: TICKINT Position */
8 ]. T# O: U$ @# l/ @#define SysTick_CTRL_TICKINT_Msk           (1ul << SysTick_CTRL_TICKINT_Pos)         : r4 Z' R( {- P% D7 I4 E
/*!< SysTick CTRL: TICKINT Mask */异常请求位5 V" u. L  w0 v. V0 y& x

. c$ A; U& D: T3 K' q#define SysTick_CTRL_ENABLE_Pos             0       /*!< SysTick CTRL: ENABLE Position */, n1 d5 C6 K& g& M$ K! q
#define SysTick_CTRL_ENABLE_Msk            (1ul << SysTick_CTRL_ENABLE_Pos)               * R- Z2 m* V' t- Q
/*!< SysTick CTRL: ENABLE Mask */使能位
) z5 J6 Q7 H4 N  t# z, I) r8 R; v3 k7 C% l5 R
/* SysTick Reload Register Definitions */
0 @; N3 t3 U: l: p/ D& r#define SysTick_LOAD_RELOAD_Pos             0    /*!< SysTick LOAD: RELOAD Position */
5 J  A! z1 L. ~" ]  o#define SysTick_LOAD_RELOAD_Msk            (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos)        + A% f. U& g6 e8 y# }9 `
/*!< SysTick LOAD: RELOAD Mask */
4 W5 E- W. `0 ?. S( j  K4 N% n
- ?& B, T# U: k/* SysTick Current Register Definitions */3 s* L1 ?) H0 A5 l
#define SysTick_VAL_CURRENT_Pos             0       /*!< SysTick VAL: CURRENT Position */1 ]" \, s; F2 L0 _0 d( |1 Y; Y
#define SysTick_VAL_CURRENT_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        5 n! s1 S; N6 i! u1 p: `
/*!< SysTick VAL: CURRENT Mask */
8 D+ Q; o6 Q& G. v" h2 L2 ^
1 P/ ?7 B3 @; R4 C3 ^/* SysTick Calibration Register Definitions */
# |# e# `  p: O+ \7 Y; i( H#define SysTick_CALIB_NOREF_Pos            31      /*!< SysTick CALIB: NOREF Position */
. x, K0 q) k3 n* q, p+ }5 Y! s#define SysTick_CALIB_NOREF_Msk            (1ul << SysTick_CALIB_NOREF_Pos)              
6 F8 O2 d; i4 J% q2 d/*!< SysTick CALIB: NOREF Mask */
; e6 M/ ?" S8 y* p
! R4 I4 |, C; j  W  ~& N3 O. p#define SysTick_CALIB_SKEW_Pos             30       /*!< SysTick CALIB: SKEW Position */2 X) h; B0 P0 r# A
#define SysTick_CALIB_SKEW_Msk             (1ul << SysTick_CALIB_SKEW_Pos)               + `$ H# i" M! f5 b/ Q
/*!< SysTick CALIB: SKEW Mask */0 Q5 Y: v' D' n* h! n

  t8 v* ?" `# D9 u#define SysTick_CALIB_TENMS_Pos             0       /*!< SysTick CALIB: TENMS Position */+ b2 |5 Q  i$ X
#define SysTick_CALIB_TENMS_Msk            (0xFFFFFFul << SysTick_VAL_CURRENT_Pos)        /*!< SysTick CALIB: TENMS Mask */9 K2 d+ N  o. V% z- c
/*@}*/ /* end of group CMSIS_CM3_SysTick */* _' x3 N6 |$ M6 Q- C$ t+ u" X2 u! q

3 c5 q" b% i- B* M$ a' E; Z与systick相关的寄存器的说明
& h# P$ r: a. v/ N% I: |* }4 D  n% r1 Q5 l

8 a( |3 |# c( L" ?# W* g+ N
4 Y" i6 {7 @4 ]/ f) F
) `, S' B- }1 i2 |) w$ T: x4 f3 p  k% K

; K. v) ?2 b0 F: uvoid SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
# {: I( D' f4 _作用:
8 f5 W9 f, e0 ?) W$ p" e选择systick的时钟源,AHB时钟或AHB的8分频& p) H* @, |0 m, g: y$ ]: [
默认使用的是AHB时钟,即72MHz
' B/ Q6 b/ ?, t# E! P1 ^0 s8 c" j* S6 y
函数说明:" N9 a* D* d5 B
/**$ j  W# l/ ~& u' R3 G
  * @brief  Configures the SysTick clock source.
. P4 T4 y3 d& ~1 ~& L9 ~& Y+ p  * @param  SysTick_CLKSource: specifies the SysTick clock source.
! o- B& j" U: l) S% _1 l  *   This parameter can be one of the following values:* {+ K  C& f7 Y1 \  Y( I
  *     @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.% }8 @6 v0 L5 o' _7 Y( e. s
  *     @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
) E: u1 M# c% H7 T& D  * @retval None) r) s$ R3 J; q# w# a! o0 V, i6 V
  */
- R2 u; W' e$ T7 ~9 G( f$ avoid SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
1 ~+ `+ M8 h8 x4 \{7 a" t! C( ~4 P: l! z* b/ q
  /* Check the parameters */) R  b3 ]. Z  n) e* _8 ]
  assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));- r) _8 b- s  W+ l$ J6 x" I
  if (SysTick_CLKSource == SysTick_CLKSource_HCLK)* R: E& U7 b& u; }1 q
  {  V" {; y+ n  E  U0 O
    SysTick->CTRL |= SysTick_CLKSource_HCLK;* L: }8 u, _2 A- a- F
  }. w, S" X* |$ i! ~6 D* R
  else: X8 A& t6 N3 V4 y5 [
  {
6 l, ^, y2 T- ^1 R    SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
$ T% F5 P! w/ ^4 ~  }
7 y! `% T; O$ F/ Q* x}0 u8 U# ^# `9 ?$ Z* c
5 I; q3 |7 N. l. s
3 m/ O% r, t! z. t' p2 {6 c
Systick时钟源的定义:0 c6 O: m! h2 V# q0 }
/** @defgroup SysTick_clock_source  m5 S; b* p% j4 \( \5 J2 X/ I+ c
  * @{
7 [+ ~+ t3 B& Q9 o4 _& ^$ O1 `' v  */7 C3 {- |4 G, K$ O+ y9 P
5 e& O9 r8 E' c+ b2 c- s
#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)//将控制状态寄存器的第二位置0,即用外部时钟源
2 D, @8 z# l/ a! ~# U#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)//将控制状态寄存器的第二位置1,即用内核时钟4 R5 I3 F1 M' M9 C% L* K! G
#define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \
9 i5 U/ V' P/ s& i( F                                       ((SOURCE) == SysTick_CLKSource_HCLK_Div8))
, i1 t' b& w  }" D7 k! R
: @; U4 I' o! tSystick定时时间的设定:
) [8 ]: I* r/ g: ?# b7 `: t% L1 ]4 N2 @1 @
重装载值=systick 时钟频率(Hz)X想要的定时时间(S)
7 C/ [- i. j  |% G如:时钟频率为:AHB的8分频;AHB=72MHz那么systick的时钟频率为72/8MHz=9MHz;要定时1秒,则
4 \9 Q4 u+ J# E- D: T% g重装载值=9000000X1=9000000;4 ^( B+ B* V8 ]1 G; V8 m& r4 D
定时10毫秒
6 _0 I% g, L, |6 y) m: ]重状态值=9000000X0.01=90000. `3 [2 l' y/ I- z( C5 c: R6 S5 O( d
Systick的中断处理函数,
; L$ v" a; c; Q7 @" g7 C4 \在startup_stm32f10x_hd.s启动文件中有定义。
2 u5 x( l3 G3 f0 f2 ?$ L' ?DCD     SysTick_Handler            ; SysTick Handler
# ~: l+ B' f& b0 s4 {/ s' F根据需要直接编写中断处理函数即可:
' Z: v6 V, p5 J- }$ _4 H4 jVoid SysTick_Handler (void)3 x3 h+ D3 @( ?' C1 M
{ ;}
4 R2 z9 a4 C- U7 r注意:: f1 W( W9 f, w7 k) f! Z
如果在工程中,加入了stm32f10x_it.c,而又在主函数中编写中断函数,则会报错。: j! q9 @' G9 N
9 o) H$ ?! a6 R, Q  N" u
因为在stm32f10x_it.c文件中,也有这个中断函数的声明,只是内容是空的。
0 f8 [5 y1 ?+ U8 J9 S/**
. D. M9 A4 ~1 C8 w+ Q  }, m* O5 W6 Q$ T  * @brief  This function handles SysTick Handler.
0 R; T+ Y  ]& P8 w7 \  H. I! F  * @param  None( M; `* N' {5 r! r2 K& D2 p
  * @retval None
, [. ~/ m! e) G1 H' U  */) y$ c2 \1 F; u6 Q6 H
void SysTick_Handler(void)$ E- g) Y" H5 ]0 f! j* V
{
! u# g- W7 K6 ]. p/ A; w* M/ U% C* y}
( s7 h& s7 d- j) x中断优先级的修改  X% b+ @. i) @! s# q4 _
在调用SysTick_Config(uint32_t ticks)之后,调用 void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)。这个函数在core_cm3.h头文件中。: v3 |5 \; }( ?. T( o8 ?1 _3 o
具体内容如下:
% M3 I  e# }+ L* L! p
) e( M( ]4 M! ~' Y7 {# M8 o1 \! N/**& U( C4 r$ d9 O8 y' _+ S
* @brief  Set the priority for an interrupt' k. S8 ]5 K5 u: X. f
*( B7 ~. K  `( U0 A
* @param  IRQn      The number of the interrupt for set priority
% W" Y7 A+ C+ ^* R: ]* @param  priority  The priority to set
2 ~/ x. [. D: s* O1 t" ?' W*# D: T% G* H) e, Q! l9 E5 Z
* Set the priority for the specified interrupt. The interrupt  k7 K0 L$ D; ~$ l
* number can be positive to specify an external (device specific)
0 v2 N1 H8 f$ A! I) k5 G0 N9 o* interrupt, or negative to specify an internal (core) interrupt.* [+ H0 t) J* V; p0 q+ J
*
/ F0 c1 `; P: ^/ x* Note: The priority cannot be set for every core interrupt.7 i& w1 u: U) ]+ M' G  L: M
*/
1 B4 f+ M' Y. V% c$ o; R! p' a6 K7 L! C1 R  N, Z+ i1 I  I
* y6 s1 c" _, X% D5 F7 x/ S

' z$ @+ t4 A3 ~5 {
# k; `* U4 N3 k- o4 u  Pstatic __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)4 e" @. @( o  x" R) A+ S
{3 J* b" O9 }- @) q( W8 E* |
  if(IRQn < 0) {/ S0 L9 I3 h( O9 s
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */! M( n# b; D* s/ E+ J( S
  else {
! H6 V9 |+ ~% O; D* Q  o    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */5 c2 a2 s- f9 e" ]0 W  L
}8 h1 L1 S8 q9 O$ d! F7 z

: q$ g( i) E& j- m7 z; J7 }* y  x2 q' {& W* F
下面以一个实例来说明:
% c3 ]8 j/ Y% l6 ~* K( L利用systick来实现以1秒的时间间隔,闪亮一个LED指示灯,指示灯接在GPIOA.8,低电平点亮。
  {& e. }. b6 {- W/ H" v- O0 h7 }5 z# `; E
#include "stm32f10x.h"& O; L1 [4 z; K! |7 b
//函数声明! K, v$ w+ l4 y' w
void GPIO_Configuration(void);//设置GPIOA.8端口" X# V6 X4 W& R* T* d
u32 t;//定义一个全局变量  N. y& W( `# E" O0 @
int main(void)$ S$ h2 F, E# C4 J+ X$ T
{
; _! c8 Q& \# A9 H+ [3 |/ ~% l3 x// SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);( w+ L; S! m) {( B! U7 R, R+ d
       SysTick_Config(9000000);
( P  g0 i0 x4 \6 `% P       SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
# r9 o. [6 n% ?# d6 Z; r8 e: |       GPIO_Configuration();
* m1 q5 \4 I6 R9 Y4 L  ]. ]       while(1);      
3 ]9 q9 E( P! x7 {}- {+ E( ^( `9 k' {
+ Y% Y* S& p2 S9 X8 _8 T1 h
//GPIOA.8设置函数# F6 V& l) w: @. G( O" R
void GPIO_Configuration(void)
1 `: M! f: Z. r( S/ f) F3 S# Z{
5 ]6 M7 w" f* Q! ?# f& G' D1 MGPIO_InitTypeDef  GPIO_InitStruct;//定义一个端口初始化结构体" j( j/ L+ e8 b! k- @
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开GPIOA口时钟# g, C# \1 i/ ?9 Y: p- Y% l; m5 P
       GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//设置为推挽输出
2 X5 x7 C6 X3 z: I7 h       GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置输出频率50M0 R" \4 H" z9 U8 k* _
       GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;//指定第8脚' |7 v1 R% r/ T9 B" n5 g8 s+ {
       GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化GPIOA.8      # S9 S- ^; o$ d5 Z* c+ K1 e
       GPIO_SetBits( GPIOA,  GPIO_Pin_8);//置高GPIOA.8,关闭LED
3 L! D  E! B3 m0 `}
2 G( N9 H: K. }7 L* r//systick中断函数* J0 N7 s# z' ~- d0 P# Y3 z
void SysTick_Handler(void)
) t& x. J- J3 w- i" c{' ?! L& O0 A! B5 r( J  R4 j
t++;
* k) ~4 N3 v* \" t5 N       if(t>=1)* X' k3 b) m: E. n# a$ ]. j
       {6 Y0 F7 L+ }: e
              if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1)
0 k+ F) n# _9 T% z& Q, r3 V              {GPIO_ResetBits( GPIOA, GPIO_Pin_8);}      
' m: G3 G2 C( I4 x( b: n       }; [! o! j) l' t/ d+ u8 ]
       if(t>=2)
5 ^4 [7 l# b/ \; B& j       {
3 D; U) e* p& O" ^8 m% X, l' \$ u' h              if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==0)% G/ d9 g$ i3 W! @( I8 r; Z
                     {GPIO_SetBits( GPIOA, GPIO_Pin_8);}' S1 t. ^# I; z) @
                     t=0;7 x# S" ~, C' [# i* A6 ?! U
       }
: T" B6 }! g3 Q1 R}% E* x6 z3 `$ ~" `

$ @% i, p8 @! H1 z模拟后的结果1 A. `) v- \1 Q
1、8分频后结果3 Q1 s' a% F* `( J; ^9 i# C5 C2 E

" S& g4 v* z9 f/ O5 }, H+ m! ]) ]" g% Y- O

" a6 L% \7 T$ h) k5 ?' `7 p# G: N0 x% ~$ {2 k

3 M) s& Y% D6 s' q7 |2、直接调用SysTick_Config(9000000);即不分频的结果,间隔为1/8=0.125s7 I4 v8 |  \! K/ B
. P  a% s4 L4 ]1 N% ^
% ~7 J+ Z  a& V/ @# {6 a# Q& m; C* a- t
总结:6 _) c5 W  g; v7 \7 a% d, z
1、要使用systick定时器,只需调用SysTick_Config(uint32_t ticks)函数即可,3 a9 [: N& ?* x* O  M. y
   自动完成了,重装载值的装载,时钟源选择,计数寄存器复位,中断优先级的设置(最低),开中断,开始计数的工作。
3 N  h% y" e9 r2、要修改时钟源调用SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)。
; O& v5 s/ R; x, e2 V- j/ j3、要修改中断优先级调用
; B. ~$ Z# O0 N9 z     void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
% B$ G$ H  j. P. F/ q2 D应用说明:
) x) B2 k$ X$ B( i7 ~1、因systick是一个24位的定时器,故重装值最大值为2的24次方=16 777 215,
6 m) c7 m, z" m* s2 ]   要注意不要超出这个值。  ^! v  W$ m0 |  F
2、systick是cortex_m3的标配,不是外设。故不需要在RCC寄存器组打开他的时钟。2 f, E+ J% m5 t1 W; m
3、每次systick溢出后会置位计数标志位和中断标志位,计数标志位在计数器重装载后被清除,而中断标志位也会随着中断服务程序的响应被清除,所以这两个标志位都不需要手动清除。* {) }+ C* @; N6 }( u! K
4、采用使用库函数的方法,只能采用中断的方法响应定时器计时时间到,如要采用查询的方法,那只能采用设置systick的寄存器的方法,具体操作以后再做分析。
$ L" i+ L) F) N/ J2 ?9 [
收藏 1 评论1 发布时间:2017-12-25 22:11

举报

1个回答
zero99 回答时间:2017-12-26 09:21:45
重复了
  ^$ W  j8 q7 n* d( F' x3 U) a/ `. |% ?1 t7 q2 `2 P% ^2 m
https://www.stmcu.org.cn/module/forum/thread-606435-1-1.html

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版