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

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

[复制链接]
kkhkbb 发布时间:2018-3-6 14:53
本帖最后由 kkhkbb 于 2018-3-19 09:11 编辑
) X+ h' r) n0 w7 V& }9 g
+ ]) ]+ V8 g; i8 ~& F; d5 k! I/ b
一、 概述
1、 时钟系统简介
(1)STM32时钟源分以下五类:
  • 高速内部时钟(HSI):RC振荡器,精度不高。
  • 高速外部时钟(HSE):可接石英/陶瓷谐振器或者接外部时钟源。
  • 低速内部时钟(LSI):RC振荡器,提供低功耗时钟。应用如WDG。
  • 低速外部时钟(LSE):接外部低频率石英晶体。应用如RTC。
  • 常闭不带复位:锁相环倍环输出(PLL):其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频倍数可调,但是其最大输出频率受限数值因芯片型号而异。  N0 C- t2 @) N1 [+ z: ^
(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                         
. s" D% ?) S+ \" X           图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的格式
1 @1 A/ t. s4 `/ v9 s& B( D
(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可用;
7 p, p; h4 C6 u( g7 H8 B1:HCLK不可用。
SKEW 0:校准值是准确的10ms;/ f' C! Z; A: a* H
1:校准值不是准确的10ms。
TENMS 该值是10ms定时的重装值。其值取决于SKEW,它可以是精确的10ms,也可以是接近10ms的值。如果该值为0,则表示无法使用校准功能,这很可能是因为时钟是系统的一个未知输入或者时钟可以动态调节。
           表4_1寄存器STK_CALRB的格式
二、实验原理
# K! |" q# g. P" w: {     通过STM32的三个GPIO口驱动三色LED的三个通道;设定GPIO为推挽输出;采用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮。通过系统定时器实现1s定时,每秒变换一次LED颜色。' k- l' W$ ~2 ^  N" B- v& \
微信图片_20180306143629.png
' @. d$ U6 M( H9 h9 t: S2 `+ h- N
             图4_4 驱动示意图
三、源代码
1.主函数
  1. /*
    # H2 j* z" E& J+ }
  2. * Name                : main
    . f' T/ R8 F# O
  3. * Description         : ---
    ) U5 N/ A! S- P8 r
  4. * Author              : ysloveivy.: q3 \8 X8 b5 J3 @/ `) r! I  |2 S# l/ n
  5. *# Q; Z' q3 ]+ H
  6. * History
    # Z0 ~7 p4 U& S0 [
  7. * --------------------1 H# @7 _8 g6 l5 F
  8. * Rev                 : 0.00' @7 I  N! s7 [& m  ~3 D. i
  9. * Date                : 11/21/20155 C% Y% R+ ^: I+ `1 f
  10. *
    : X) x+ C1 ]  x& f! l2 h$ G
  11. * create.
    1 Q+ n- Y& }1 }# L
  12. * --------------------
    ! d0 A3 l9 I0 o% Y/ W2 [
  13. */6 Y" j8 w* s  L' Z7 v) i6 A" Y
  14. int main(void)
      m& H& l- e, O3 z. J
  15. {
    0 m# D6 U, a/ H
  16.         static int work_status = 0;
    3 Z( E. Z& r8 x( `' p- d
  17.         led.initialize();
    4 w, C5 K% \: l; D3 C% a
  18.         systick.initialize();' J2 l; H4 {* X- H; ^1 _5 f
  19.         //每隔一秒三色灯进行交替循环闪烁
    3 K! E' t+ @3 ?* g
  20.         while(1){
    9 z1 I  a1 z" [" g7 ^9 A: R) b
  21. if(systick.second_flag == 1){ //每隔一秒标志位置1,执行一次' @  b7 k' L8 }
  22.                         systick.second_flag = 0;
    7 E+ w, b3 Q/ N! F! A. O
  23.                         work_status += 1;
    - ]; C1 Y8 P& m, l' L- A
  24.                         if(work_status > 2)work_status = 0;
    1 h/ k6 p7 T4 ~6 \
  25.                 }) C6 d' J8 g3 m- H
  26.                 switch (work_status){
    + ~! B* w+ [+ S* m
  27.                         case 0 :
    % {) c# j7 ^) d4 Y, o4 p3 S4 H
  28.                                 LED_RED_ON;
    6 @* G& P4 I7 C1 E5 H& Y
  29.                                 LED_GREEN_OFF;
    # H/ D& E3 {1 F" _: [* @) t7 e& n
  30.                                 LED_BLUE_OFF;7 @, t2 k. D" r( T" A" Q% j2 s
  31.                                 break;5 T% @2 |( g# I+ j3 E5 I& w! Z3 n
  32. * O' C$ X5 ^5 s0 H( s* Q4 E1 g
  33.                         case 1 :$ E6 Z. Y$ Q# y9 b( O, r
  34.                                 LED_RED_OFF;
    ( g% h9 P: B* r- F0 D- }8 ]6 s' [2 ]3 a7 {
  35.                                 LED_GREEN_ON;
    0 D% n7 h9 s' Y: z
  36.                                 LED_BLUE_OFF;
    & S9 M6 r! A. l) }
  37.                                 break;
    , d: p. ?+ ~1 ]& }

  38. " |2 H/ U" i2 g0 R
  39.                         case 2:/ g  b5 o+ C9 U, X4 l
  40.                                 LED_RED_OFF;
    " _% Q- B  F: y- M% G* ^
  41.                                 LED_GREEN_OFF;) {; ?( n7 z+ K* ^7 Z9 Q" g
  42.                                 LED_BLUE_ON;
    % h6 @2 Y: x( |. r  e
  43.                                 break;
    9 E3 X% V! x* F; u/ u
  44. ; @6 M$ T* }# Q& Q. t/ T1 Y$ e
  45.                         default:
复制代码
2.Systick初始化
   以下是Systick初始化及中断设置函数,主要实现定标志位的时1s,改变一次标志位,使用LED显色状态变换一次。
  1. /*# Z3 p" j8 H2 L. g. B: d9 Z, k
  2. * Name               : initialize+ |( W6 n+ s) t
  3. * Description        : ---
    4 L! @' l( k5 ^) _' Q- i/ F1 Y
  4. * Author             : ysloveivy.. p5 S6 {0 H; h! r5 Z" W2 }
  5. *
    ' N' ?, A; G2 U
  6. * History
    1 T$ o6 F* j+ q8 }
  7. * -------------------
    1 r* v5 V. G* Z- y7 q3 Q' q
  8. * Rev                : 0.00
    / e- Z$ E2 o# c% {6 T' T6 T
  9. * Date               : 11/21/2015/ {+ G$ ^) _* y; ]1 G! u1 t
  10. *
    : J0 ?6 t- S8 K" K) Y0 I
  11. * create.9 b% O, Q/ @$ `4 H
  12. * -------------------
    : |. q: R7 y+ B) t
  13. */
    5 x" Z% D0 B( h5 A' |. F
  14. static int initialize(void)
    # Q8 J0 G/ H, d2 E
  15. {! g" l7 L" W- z# C+ k9 b
  16.         //定时1ms
    ; p/ }0 _. p$ j! O
  17.         if(SysTick_Config(SystemCoreClock / 1000)){! |2 Q3 V# B: W$ j, @- g& c" }
  18.                 while(1);
    8 H  k# i: \, ]+ C* F. S5 Z3 `
  19.         }2 F' o0 N6 P9 |: ]4 L  o, R
  20.         return 0;# h9 u; U: o( t8 m; T0 I8 Y( V
  21. }
    . i  ~/ U# u! e" {" R
  22. /*
    + M3 e  X/ Y) ?
  23. * Name               : SysTick_Handler
    " A6 N8 ~) g$ }( {- e
  24. * Description        : ---
    ) ]3 O  S0 c. T7 q) C
  25. * Author             : ysloveivy.
    # J2 j% Y. t& R$ u. E( a
  26. * History
    & I9 ^" P. X3 D, w
  27. * -------------------
    1 Z) r4 f3 _: K( }
  28. * Rev                : 0.00
    5 m  _6 n' o. o; Z3 e8 M
  29. * Date               : 11/21/2015
    * ~) B( O& u/ ^: U% z( ]
  30. * ! w: L0 [4 K4 R2 s6 M5 G8 d
  31. * create.* J* Z& Z4 x$ Y* s
  32. * -------------------/ h, q& u" S# b/ n1 C* n: \% T
  33. */' F! d- D$ ~- w! B) k
  34. void SysTick_Handler(void)
    * ^) j( O# f, \- W+ O% T6 W; V
  35. {
    * ]" J) V, ^# ~7 ^( N0 n, E
  36.         static int counter = 0;
    6 E# v7 J% f% O* x2 V% A

  37. 3 s2 l2 ?/ d" @# ]
  38.         if((counter ++ % 1000) == 0){ //每次中断counter自加1,判断是否整秒
    # ^0 o0 r# v2 P& w3 G7 d
  39.                 systick.second_flag = 1;9 t- i4 G* |. K; [1 l! f9 e( L1 Z+ I
  40.         }8 W% L( t# o( L
  41. }
复制代码
3.小知识
   在上面有两个重要的函数
   1.SysTick_Confing(uint32_t ticks)
    该函数的作用是初始化systick,时钟为HCLK(CM3一般为72M,CM4一般为168M),并开启中断。
  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)+ I/ w' z: a4 D2 T
  2. {; s$ E; Y$ Q* K9 _
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)  //大于重载寄存器最大值0xFFFFFF" p- ?) n$ p" {+ |6 d
  4.   {9 V& `* k6 v, y) b
  5. return (1UL);                                //重新加载值不可能,返回错误           . G# c  G+ B- F7 r* e4 G, Z
  6. }6 m( a# H9 F! R. r' q8 U  ~1 |6 }
  7.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);      //计数范围0到ticks-1                  
    - A5 N8 A+ `- {0 r) C; q+ n1 a
  8. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    " R% A( m8 x" Z/ D; G
  9. //设置优先级
    , K, b) u$ s! S( h; H
  10. SysTick->VAL   = 0UL;                              //当前值初始化为0    6 s: Q. u) S- Z3 C$ e6 @
  11.   //接下来设置控制寄存器,以位与的方式实现三个控制位的设置。
    % }5 U8 N( k" o1 p, S( P) e$ z
  12.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | //选择时钟源3 U) U, B9 Q3 e
  13.                       SysTick_CTRL_TICKINT_Msk   |  //开启中断
    % `" z& \2 R- Y" t. M6 N0 G
  14.                       SysTick_CTRL_ENABLE_Msk;      //使能定时器               
    $ k/ [0 _$ ]. ^
  15.   return (0UL);                                       //初始化成功返回         
    ( i: w: V5 T. i
  16. }
复制代码
     回头看看程序中的SysTick_Config(SystemCoreClock / 1000)语句,该函数中的SystemCoreClock为时钟频率已在库函数中宏定义。如在iCore3双核心板ARM的HCLK为168M(每秒168M次计数),则程序中SystemCoreClock / 1000即意味每1ms中断一次。
    2.void SysTick_Handler(void)
    该函数是中断函数,即每次SysTick中断产生时运行一次函数,其在启动文件中已有设置,在驱动文件中使用时无需再次声明。
# t- z8 s4 m) ~
四、 实验现象
     iCore3的双核心板上与ARM相连的三色LED(PCB上标示为ARM·LED),红色、绿色、蓝色每秒交替点亮。
五、 代码包下载链接

3 ?6 J# p6 K8 p
收藏 评论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- j# H! {8 H6 y) n
大佬,这第一讲和第二讲怎么没找到啊  。。

2 j; J$ T7 k" ?4 O- ^9 |2 p3 P" k: I你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
zero99 回答时间:2018-3-8 10:37:48
kkhkbb 发表于 2018-3-7 15:26
( h4 w6 @2 M$ W* y) j你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
% w6 N' F3 F7 }
另外一个也是你啊  

所属标签

相似分享

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