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

【零基础学习STM32】第五讲:SYSTICK定时器实验——定时点...

[复制链接]
kkhkbb 发布时间:2018-3-6 14:53
本帖最后由 kkhkbb 于 2018-3-19 09:11 编辑
$ ^% C4 }' B1 E' t2 O' _7 H% W1 t. H$ h; L
一、 概述
1、 时钟系统简介
(1)STM32时钟源分以下五类:
  • 高速内部时钟(HSI):RC振荡器,精度不高。
  • 高速外部时钟(HSE):可接石英/陶瓷谐振器或者接外部时钟源。
  • 低速内部时钟(LSI):RC振荡器,提供低功耗时钟。应用如WDG。
  • 低速外部时钟(LSE):接外部低频率石英晶体。应用如RTC。
  • 常闭不带复位:锁相环倍环输出(PLL):其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频倍数可调,但是其最大输出频率受限数值因芯片型号而异。9 K$ j) p7 E, v. e$ C: \% e
(2)系统时钟SYSCLK可来源于:HSI振荡器时钟、HSE振荡器时钟、PLL时钟。
2、SYTICK简介
     在STM32中,SysTick是内核CM4中的一个24位的递减计数器,也称系统嘀答定时器。SysTick的最大使命,就是定期地产生异常请求,作为系统的时基。操作系统需要这种“滴答”来推动任务和时间的管理。
     SysTick在设定初值并开启后,每经一个系统时钟周期,计数值减1,计数到0时,将从重载寄存器中自动重新装载定时初值并继续计数,同时内部的COUNTFLAG标志位置1,触发中断(中断允许情况下),中断响应属于NVIC异常,异常号为15,Systick中断优先级可设置。
3、SYTICK寄存器控制
     STM32内部有4个寄存器控制SysTick定时器。分别为:控制寄存器STK_CSR、重载寄存器STK_LOAD、当前值寄存器STK_VAL和校准值寄存器STK_CALRB。下面分别对这4个寄存器做详细介绍。
(1)控制寄存器STK_CSR(地址:0xE000E010)
       控制寄存器STK_CSR中有4个bit具有意义,其内容如图4_0、表4_0所示:
    784b0304d5f54e0978959d5fda1c0d8.png                         9 h0 G5 C# t; O1 U; p& V. B1 f$ J
           图4_0 控制寄存器STK_CSR的格式
ENABLE(位0) Systick使能位。
0:关闭Systick功能;
1:开启Systick功能。
TICKINT(位1) Systick中断使能位。
0:关闭Systick中断;
1:开启Systick中断,systick倒数到零时产生systick异常中断。
CLKSOURCE(位2) Systick时钟源选择位。
0:使用HCLK/8作为Systick时钟(外部时钟);
1:使用HCLK作为Systick时钟(内核时钟)。
COUNTFLAG(位16) Systick计数比较标志,如果在上次读取本寄存器后,SysTick已经数到了0,则该位为1。如果读取该位,该位将自动清零。
           表4_0  控制寄存器STK_CSR的格式6 J/ K) J. a9 J5 F) E6 \: O
(2)重载寄存器STK_LOAD(地址:0xE000E014)
微信图片_20180306142932.png
             图4_1 重载寄存器STK_LOAD的格式
     重载寄存器STK_LOAD为24位的寄存器(0:23有效),最大计数0xFFFFFF。SysTick定时器递减至0时,重载寄存器中的值就会被重新装载,继续开始递减计数。
(3)当前值寄存器STK_VAL(地址:0xE000E018)
微信图片_20180306143229.png
            图4_2 当前值寄存器STK_VAL的格式
     当前值寄存器STK_VAL为24位的寄存器,读取时返回当前计数的值,写它则使之清零,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG标志。
(4)校准值寄存器STK_CALRB(地址:0xE000E01C)
微信图片_20180306143432.png
         图4_3 校准值值寄存器STK_CALRB的格式
NOREF 0:HCLK可用;8 g) x3 M  y$ \+ U( T" v  y1 R
1:HCLK不可用。
SKEW 0:校准值是准确的10ms;
5 N# v2 W- b! z5 l; U: O1:校准值不是准确的10ms。
TENMS 该值是10ms定时的重装值。其值取决于SKEW,它可以是精确的10ms,也可以是接近10ms的值。如果该值为0,则表示无法使用校准功能,这很可能是因为时钟是系统的一个未知输入或者时钟可以动态调节。
           表4_1寄存器STK_CALRB的格式
二、实验原理) M; N$ v; _& a7 h+ _7 J
     通过STM32的三个GPIO口驱动三色LED的三个通道;设定GPIO为推挽输出;采用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮。通过系统定时器实现1s定时,每秒变换一次LED颜色。
' A% b" u6 r7 G: N( y' w- l 微信图片_20180306143629.png
% s. n9 J) l# U
             图4_4 驱动示意图
三、源代码
1.主函数
  1. /*- m- ~: }. T4 S  _: d
  2. * Name                : main
    6 {  \9 W( |7 a6 S- u, @0 O
  3. * Description         : ---
    1 R% y% }0 X9 D- P; z6 O
  4. * Author              : ysloveivy.
      t" _# w9 s7 Q( }
  5. *9 b8 v  l: J0 d' u6 z& B% e
  6. * History
    2 w" E5 R1 B6 _" E, I4 n, }
  7. * --------------------
    - H3 ~' c) L5 {6 ~: G/ X
  8. * Rev                 : 0.00
    . @1 Q  |# p( S& S3 f
  9. * Date                : 11/21/2015; p+ X5 c! I% V
  10. * - Z( g, g2 e. g. W# u1 Q8 _; x: N
  11. * create.3 F+ B8 R( f$ L' S
  12. * --------------------
    , p+ L- j9 M- N/ Z. _
  13. */. @9 }) }3 {! r: {% b# s5 X3 u
  14. int main(void)7 |, k5 O+ ~7 M8 F/ I
  15. {
    6 _- H) `7 T9 {4 `
  16.         static int work_status = 0;
    - [. M# a* |+ i' f
  17.         led.initialize();
    9 H5 Q0 N) y+ d* W: g# d* t7 l
  18.         systick.initialize();
    % U; O$ c* k$ S5 a7 D4 c
  19.         //每隔一秒三色灯进行交替循环闪烁
    ! B8 @! D" W- Y9 R5 e( z: |- H3 v
  20.         while(1){1 l2 K7 A8 Y, D2 a' \/ a& ^
  21. if(systick.second_flag == 1){ //每隔一秒标志位置1,执行一次
    / ^, n# m' r  w
  22.                         systick.second_flag = 0;# w) g" I0 B) ?' P( G5 }7 s$ J/ T
  23.                         work_status += 1;
    9 ~" ]( d* D0 A  V! F
  24.                         if(work_status > 2)work_status = 0;
    0 H- ~7 A$ g- Z- }% Z
  25.                 }' W+ S) x6 E  Y7 A" W& O
  26.                 switch (work_status){1 ?9 A5 ^! a' y
  27.                         case 0 :7 L6 _# K5 a0 u9 D8 {# u
  28.                                 LED_RED_ON;
    & ^0 v# }5 a2 Z; Q4 y
  29.                                 LED_GREEN_OFF;" f& I! z6 a' }0 w! `" A: e
  30.                                 LED_BLUE_OFF;3 [  Z$ T' [! d; \( {6 s( M
  31.                                 break;4 J- L0 b7 I, S' c$ E, g; n( q
  32. 1 G" D4 g& P- x4 }
  33.                         case 1 :
    , z' [- U  T' ~& E. h7 m
  34.                                 LED_RED_OFF;
    - \" z$ l5 C# C( q1 |
  35.                                 LED_GREEN_ON;
    9 k' m3 k6 H9 D: \5 a
  36.                                 LED_BLUE_OFF;: |1 j* `' ]; U8 e- D2 d) n: }1 i1 i
  37.                                 break;
    0 j' I4 N. E  Q, _& m- m4 u, \+ z

  38. ) P) J7 f9 _" s, J8 W
  39.                         case 2:/ X$ D% F+ g* ~" O: t6 X. w0 [6 A4 X9 A
  40.                                 LED_RED_OFF;& z4 m5 }" P: ~1 u
  41.                                 LED_GREEN_OFF;$ }$ R# [% y4 M4 H& R& u
  42.                                 LED_BLUE_ON;
    - K3 L% ], ^. @8 m! B# `! H
  43.                                 break;
    2 T: _1 i# W3 b8 t2 Y

  44. 0 O8 ]1 B* Z! Y
  45.                         default:
复制代码
2.Systick初始化
   以下是Systick初始化及中断设置函数,主要实现定标志位的时1s,改变一次标志位,使用LED显色状态变换一次。
  1. /*6 G4 x* p& q! p, s9 w4 h% x
  2. * Name               : initialize3 F4 t0 F3 ~5 ]3 J
  3. * Description        : ---' C: `; e: e7 X. f  M! T$ Q2 o% J
  4. * Author             : ysloveivy.
    ; |8 b' {- M6 I' z5 t8 x
  5. *$ w  b  ~: ]2 ~3 |
  6. * History8 q; {* M% O  s) \0 v
  7. * -------------------' O3 e, ]1 s1 e8 L% j- H- c  L7 ~
  8. * Rev                : 0.00
    ' V' W% ?/ ^4 ^: W7 `1 d2 a
  9. * Date               : 11/21/2015- f4 u  }1 Q2 K
  10. * - H0 b' A6 h3 ]
  11. * create.! D1 _  g2 m+ b# Q
  12. * -------------------$ E5 B+ u5 G: C: S$ m* ^$ k
  13. */
    & X' [; v% Z" y# `
  14. static int initialize(void)
    2 q9 Z5 o2 E; G3 J3 l! V) Q0 |6 N
  15. {% E2 s# \/ i, @' H
  16.         //定时1ms
    0 q6 M* L6 ?8 h1 o! F' d. c
  17.         if(SysTick_Config(SystemCoreClock / 1000)){
    / d, h2 r" |: e
  18.                 while(1);) O1 n; ?- ~$ y$ ?& T- C6 P! @' }8 |
  19.         }4 l" I& u; G4 [% F5 E. V
  20.         return 0;
    : f3 R* h: {: b
  21. }
    : T3 u0 G: d3 C& r( c7 O
  22. /*
    ( S4 s: Q3 C# P: [7 q% k1 v
  23. * Name               : SysTick_Handler
    ) H0 R- Q: Y; q1 h9 y
  24. * Description        : ---6 W9 [3 s7 s; f, A. b+ x: |, J
  25. * Author             : ysloveivy./ u( a& B4 T9 w; X( z* ]; W# D" Y. T6 ?
  26. * History2 h2 S, Y5 k; V/ R  v5 Y
  27. * -------------------4 ^  N. Q0 u& B
  28. * Rev                : 0.00
    4 R% y( J/ ^# R) O" P2 X( d
  29. * Date               : 11/21/2015
    . v( }! L9 p; d- I9 w
  30. * # D5 m3 Y1 Y3 }
  31. * create.
    1 ~$ v  y2 V/ f
  32. * -------------------5 G/ Y( i6 y3 w2 x5 d$ `
  33. */* V" C# w* I+ N2 b) V' s! X) W7 N
  34. void SysTick_Handler(void)
    6 c7 Y9 R+ m: ^* W; U
  35. {5 K$ J8 Y$ ]* ~6 o
  36.         static int counter = 0;9 ^+ v5 ^# ~% K8 @4 b- c
  37. % m% A- M* K# Z, B  k9 q7 D. t8 w
  38.         if((counter ++ % 1000) == 0){ //每次中断counter自加1,判断是否整秒. l: ^$ Q$ W: d) z
  39.                 systick.second_flag = 1;
    5 k' q0 E- E5 F' s  F% Y
  40.         }
      F# t8 V6 o5 M
  41. }
复制代码
3.小知识
   在上面有两个重要的函数
   1.SysTick_Confing(uint32_t ticks)
    该函数的作用是初始化systick,时钟为HCLK(CM3一般为72M,CM4一般为168M),并开启中断。
  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)/ J" T( ?+ A" N
  2. {
    . Z$ A, R$ g/ Q1 e: P" b
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)  //大于重载寄存器最大值0xFFFFFF
    0 ~5 t$ d- H1 B8 `6 [( N
  4.   {
    & j8 D- r( h$ w% _! t
  5. return (1UL);                                //重新加载值不可能,返回错误           
    & @" Y/ c% K( q. ~7 @
  6. }
    : [" \8 j1 ?- }) X9 I' R8 g7 F1 l
  7.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);      //计数范围0到ticks-1                  7 w) `$ f: D! a" b7 o
  8. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);. q! I' g) n4 i$ e% v1 O
  9. //设置优先级
    0 E2 q! W. i# d" D1 J$ y( |
  10. SysTick->VAL   = 0UL;                              //当前值初始化为0   
    ' ]4 W5 ]/ j8 ~8 b
  11.   //接下来设置控制寄存器,以位与的方式实现三个控制位的设置。
    1 I  b$ E0 e" Z4 k: b' g9 {3 J
  12.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | //选择时钟源4 s5 g. x8 Q/ A6 B' Z- Q
  13.                       SysTick_CTRL_TICKINT_Msk   |  //开启中断
    / x5 |/ E, }6 f; U  V7 O; a% }
  14.                       SysTick_CTRL_ENABLE_Msk;      //使能定时器               / V) ~0 V1 d0 X4 l2 A
  15.   return (0UL);                                       //初始化成功返回          . \; X  u, j% I- Q3 Q& A) s1 D3 S
  16. }
复制代码
     回头看看程序中的SysTick_Config(SystemCoreClock / 1000)语句,该函数中的SystemCoreClock为时钟频率已在库函数中宏定义。如在iCore3双核心板ARM的HCLK为168M(每秒168M次计数),则程序中SystemCoreClock / 1000即意味每1ms中断一次。
    2.void SysTick_Handler(void)
    该函数是中断函数,即每次SysTick中断产生时运行一次函数,其在启动文件中已有设置,在驱动文件中使用时无需再次声明。
' T6 N5 [% U' o( ?6 @' g& f  z) D$ H; _
四、 实验现象
     iCore3的双核心板上与ARM相连的三色LED(PCB上标示为ARM·LED),红色、绿色、蓝色每秒交替点亮。
五、 代码包下载链接
! `4 h% r4 \6 f8 b, s1 e& t
收藏 评论3 发布时间:2018-3-6 14:53

举报

3个回答
zero99 回答时间:2018-3-7 09:18:31
大佬,这第一讲和第二讲怎么没找到啊  。。
kkhkbb 回答时间:2018-3-7 15:26:29
zero99 发表于 2018-3-7 09:18. q; D* @! [2 v( B
大佬,这第一讲和第二讲怎么没找到啊  。。

& k/ N# j" [' z' C/ U! `' S你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
zero99 回答时间:2018-3-8 10:37:48
kkhkbb 发表于 2018-3-7 15:26
0 N. d' ?; H( K$ L; O, ]$ J0 b1 u你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
8 T& r) {# T9 N* }+ J' @! b: g
另外一个也是你啊  

所属标签

相似分享

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