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

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

[复制链接]
kkhkbb 发布时间:2018-3-6 14:53
本帖最后由 kkhkbb 于 2018-3-19 09:11 编辑
/ Z: U& U$ I, K
9 y6 \- d# E9 j+ @6 c$ r  ]
一、 概述
1、 时钟系统简介
(1)STM32时钟源分以下五类:
  • 高速内部时钟(HSI):RC振荡器,精度不高。
  • 高速外部时钟(HSE):可接石英/陶瓷谐振器或者接外部时钟源。
  • 低速内部时钟(LSI):RC振荡器,提供低功耗时钟。应用如WDG。
  • 低速外部时钟(LSE):接外部低频率石英晶体。应用如RTC。
  • 常闭不带复位:锁相环倍环输出(PLL):其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频倍数可调,但是其最大输出频率受限数值因芯片型号而异。
    7 `1 b/ f) N* R/ Y$ e# ]3 p
(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                         
' v4 v  J/ ~$ R7 G           图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的格式
) F3 d9 {; W! f' H
(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可用;
' w# H3 b3 E$ R3 g& [. g1:HCLK不可用。
SKEW 0:校准值是准确的10ms;
# s# b7 g0 H' M% F7 k+ G1:校准值不是准确的10ms。
TENMS 该值是10ms定时的重装值。其值取决于SKEW,它可以是精确的10ms,也可以是接近10ms的值。如果该值为0,则表示无法使用校准功能,这很可能是因为时钟是系统的一个未知输入或者时钟可以动态调节。
           表4_1寄存器STK_CALRB的格式
二、实验原理3 V; `& F9 W( ]2 ?3 K
     通过STM32的三个GPIO口驱动三色LED的三个通道;设定GPIO为推挽输出;采用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮。通过系统定时器实现1s定时,每秒变换一次LED颜色。
# w" n3 m5 V+ \% H; H 微信图片_20180306143629.png - W7 c* F0 k0 X
             图4_4 驱动示意图
三、源代码
1.主函数
  1. /*
    ! s1 [) @0 N) x6 c& L1 Q
  2. * Name                : main
    * q6 A0 ~8 q$ i4 }, ]% c
  3. * Description         : ---
    5 N2 m! r1 }9 _: @5 L2 I
  4. * Author              : ysloveivy.! J3 k8 O" B: K9 S  p
  5. *
    " h9 H0 c6 c5 ~: R* h/ V
  6. * History# i1 A2 P; q- X* t8 H
  7. * --------------------
    . f% R! ^, h7 r# G
  8. * Rev                 : 0.00
    - e0 Z- e9 `+ S- A
  9. * Date                : 11/21/2015
    & \: l! s1 x; l- {
  10. * + [5 s- O* I( _. F2 W
  11. * create.* J- F5 u, J. A& v; m9 _+ m
  12. * --------------------
    / G9 L3 Q8 q7 P4 f" Z, u5 @* S
  13. */0 N! _3 |  r: B' b/ B: }
  14. int main(void)3 E2 k+ X# h* v  i+ `
  15. {$ B, Z, _3 e/ s
  16.         static int work_status = 0;
    1 V, N. j" S. X7 S/ Q
  17.         led.initialize();
      E- d1 a+ w3 O0 A) A/ c& N3 N. F
  18.         systick.initialize();
    " k/ [0 e8 J. K# q2 U+ [$ A0 w* T
  19.         //每隔一秒三色灯进行交替循环闪烁
    6 N, g6 H8 N5 S9 d/ l
  20.         while(1){
    " y& H5 A2 x- c) B& `
  21. if(systick.second_flag == 1){ //每隔一秒标志位置1,执行一次$ L# A+ v  q  |+ T$ {; d0 A  [
  22.                         systick.second_flag = 0;/ C) H# }" h# J9 k2 j3 Y# N
  23.                         work_status += 1;' _2 z; T9 C7 p
  24.                         if(work_status > 2)work_status = 0;
    6 f' Z* K; H3 w5 H# \: Q9 V. M5 ]
  25.                 }
    $ T9 V2 U9 E2 u9 L
  26.                 switch (work_status){
    5 t/ T4 b0 Y0 C$ q# ]1 C( l. d
  27.                         case 0 :
    ) m$ C( Y) D3 X9 h( Y. G* k
  28.                                 LED_RED_ON;" r3 E' F$ n8 R( u$ q) R! S' |
  29.                                 LED_GREEN_OFF;& N0 h! D& L3 A! I5 }/ c" F
  30.                                 LED_BLUE_OFF;0 A' x& U% I+ V3 i$ a9 j1 |
  31.                                 break;
    * U$ E5 V1 ^+ o  p
  32. 5 I9 m1 S9 H: x) k' ~- x
  33.                         case 1 :
    ) j# F" \" ?$ k
  34.                                 LED_RED_OFF;
    $ v8 X9 A$ H1 m5 G8 ]3 c9 C
  35.                                 LED_GREEN_ON;
    9 J9 k# f) e/ [  @
  36.                                 LED_BLUE_OFF;) h. N% j, @6 q5 B5 w6 M" H: t
  37.                                 break;7 L7 Q3 S/ i) q* S
  38. : f& K6 s5 c  u' R9 S5 g
  39.                         case 2:, V+ ~9 U, x$ p" O* F  o
  40.                                 LED_RED_OFF;
    : k9 i& a# Z, {7 j
  41.                                 LED_GREEN_OFF;
    7 b$ }& K. i& T5 m2 I$ _. a
  42.                                 LED_BLUE_ON;
    % R  h! n' S$ ~9 {  d( ?* @
  43.                                 break;6 \' B8 k! n2 f

  44. 4 ?) @7 E. A! V2 j  g" D8 u  w
  45.                         default:
复制代码
2.Systick初始化
   以下是Systick初始化及中断设置函数,主要实现定标志位的时1s,改变一次标志位,使用LED显色状态变换一次。
  1. /*
    2 K% U5 J2 K0 d0 n" }* B+ w
  2. * Name               : initialize
    # @$ Y5 q  G7 u) K+ L
  3. * Description        : ---! A8 N& T* P; [; j; m
  4. * Author             : ysloveivy.
    1 t: }9 x' B; |+ ~- n
  5. *4 g, V1 G& d# s. ~6 v
  6. * History7 }4 y8 H: P  q8 z8 a
  7. * -------------------
    $ q8 A% e7 n* E: A) d) ]9 v9 }1 {- r% U
  8. * Rev                : 0.00, v- J- V! {# @# r! _8 X
  9. * Date               : 11/21/2015
    * H, ]0 W. e( V  K2 l8 Y1 M
  10. * ' X7 Y4 l8 O3 E$ A; \# ^
  11. * create.
    + p9 z1 J% f) {4 t1 ?9 k8 C
  12. * -------------------* \% o1 o2 C' a' f
  13. */; U" g3 l+ f; D# [1 A' ^
  14. static int initialize(void)
    7 U0 o! b! w" l8 z
  15. {
    1 P: X5 C. D' V; Q
  16.         //定时1ms
    * \/ c* N  Z3 w
  17.         if(SysTick_Config(SystemCoreClock / 1000)){
    / n. m, J& }! p' U
  18.                 while(1);  f$ {( C' t% \2 u, E
  19.         }
    ; e  }/ Z) X+ y5 t
  20.         return 0;
    : x, o; b% x7 [) f4 [7 ?
  21. }
    2 b" y0 w6 \0 u7 q" Z  h
  22. /*6 C" W7 H4 S+ @! T% [5 D
  23. * Name               : SysTick_Handler4 `4 L, ^+ M; C
  24. * Description        : ---, T. M. [3 ^5 v" `% L2 f
  25. * Author             : ysloveivy.) I1 q* v: i0 S* u8 f
  26. * History
    $ f- t+ J- Y; b* m, i  g6 i7 p
  27. * -------------------3 q$ P: i! P. E) I/ w
  28. * Rev                : 0.00
    3 M! Q' D1 o: E; R7 e
  29. * Date               : 11/21/20156 ~# q2 `' i% K5 B% F) i; f
  30. * 4 B& F, R- H' v8 s/ `
  31. * create.( g; h: q5 ]+ S& W# r3 j; o
  32. * -------------------: M7 }" z  c; ?% v5 r; Z4 i1 _3 W
  33. */
    ( ]" F( ^, {* y# Q2 z
  34. void SysTick_Handler(void)' d8 t0 L) }- I- W
  35. {
    7 x3 L* K/ a( `; r
  36.         static int counter = 0;% v" w# |6 ]) I" @/ R( ^

  37. 6 E5 g8 f6 G6 v# K1 ^
  38.         if((counter ++ % 1000) == 0){ //每次中断counter自加1,判断是否整秒
    4 X6 V' M0 h9 o- N1 ]3 u
  39.                 systick.second_flag = 1;
    * P$ v$ J, A3 y
  40.         }) h9 O3 a$ U3 P# @. T( U9 b- c: s
  41. }
复制代码
3.小知识
   在上面有两个重要的函数
   1.SysTick_Confing(uint32_t ticks)
    该函数的作用是初始化systick,时钟为HCLK(CM3一般为72M,CM4一般为168M),并开启中断。
  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)2 n. |& D* J$ j2 o
  2. {7 t1 ~3 @9 ^0 e5 Q
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)  //大于重载寄存器最大值0xFFFFFF
    ' Q5 l" u' m& j7 b3 h( H
  4.   {
    8 E0 u! u; {) r7 A) M
  5. return (1UL);                                //重新加载值不可能,返回错误           ( V$ `5 V5 N% l4 v% R
  6. }
    ! T: F( B9 k8 Q2 w3 ~# t8 ^. m& F! b
  7.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);      //计数范围0到ticks-1                  
    & h, {9 \% S) @% L
  8. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    , X: \, \) Y6 s9 l3 Y; i" N: m$ I
  9. //设置优先级: x# G2 m) P7 D9 V4 ~- D, g
  10. SysTick->VAL   = 0UL;                              //当前值初始化为0   
    . F$ A- m* n* _' m) z1 y
  11.   //接下来设置控制寄存器,以位与的方式实现三个控制位的设置。! O; u8 L3 n+ T  _  w
  12.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | //选择时钟源
    ( w' x; ~" ^7 X, x6 J: h' K! N. r
  13.                       SysTick_CTRL_TICKINT_Msk   |  //开启中断
    " I' r. @, b/ g  X' r" m1 \
  14.                       SysTick_CTRL_ENABLE_Msk;      //使能定时器               
    6 L( e& n; j, ^- D' I/ A4 t
  15.   return (0UL);                                       //初始化成功返回         
    , _) g1 |2 ]' F: \% t
  16. }
复制代码
     回头看看程序中的SysTick_Config(SystemCoreClock / 1000)语句,该函数中的SystemCoreClock为时钟频率已在库函数中宏定义。如在iCore3双核心板ARM的HCLK为168M(每秒168M次计数),则程序中SystemCoreClock / 1000即意味每1ms中断一次。
    2.void SysTick_Handler(void)
    该函数是中断函数,即每次SysTick中断产生时运行一次函数,其在启动文件中已有设置,在驱动文件中使用时无需再次声明。
, I- b( F6 x/ h; R3 ~) K& R
四、 实验现象
     iCore3的双核心板上与ARM相连的三色LED(PCB上标示为ARM·LED),红色、绿色、蓝色每秒交替点亮。
五、 代码包下载链接

  A$ k# Z7 U( N) \. @, ]
收藏 评论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
+ L0 @5 P5 Y* A. h4 Z# x: ?大佬,这第一讲和第二讲怎么没找到啊  。。

; G1 k1 C3 k, W2 Q7 v你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
zero99 回答时间:2018-3-8 10:37:48
kkhkbb 发表于 2018-3-7 15:26
) p, R+ `; _5 k0 d( l7 ?* S你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
5 J2 V" M& J; a/ V: @  s
另外一个也是你啊  

所属标签

相似分享

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