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

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

[复制链接]
kkhkbb 发布时间:2018-3-6 14:53
本帖最后由 kkhkbb 于 2018-3-19 09:11 编辑 " l' ^9 M* B2 s+ k/ A% F

7 L: j) V- S# V' D- u
一、 概述
1、 时钟系统简介
(1)STM32时钟源分以下五类:
  • 高速内部时钟(HSI):RC振荡器,精度不高。
  • 高速外部时钟(HSE):可接石英/陶瓷谐振器或者接外部时钟源。
  • 低速内部时钟(LSI):RC振荡器,提供低功耗时钟。应用如WDG。
  • 低速外部时钟(LSE):接外部低频率石英晶体。应用如RTC。
  • 常闭不带复位:锁相环倍环输出(PLL):其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频倍数可调,但是其最大输出频率受限数值因芯片型号而异。
    ! I# C3 g: J& g
(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                         
- p( k$ i8 o: @8 o& 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的格式  r9 Y" E4 @& h8 {* 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可用;% I* B! p: Z+ [+ Z
1:HCLK不可用。
SKEW 0:校准值是准确的10ms;
* d( Q1 [/ x* N2 g" O7 a; W( d1:校准值不是准确的10ms。
TENMS 该值是10ms定时的重装值。其值取决于SKEW,它可以是精确的10ms,也可以是接近10ms的值。如果该值为0,则表示无法使用校准功能,这很可能是因为时钟是系统的一个未知输入或者时钟可以动态调节。
           表4_1寄存器STK_CALRB的格式
二、实验原理
7 b5 |; Q; D. h     通过STM32的三个GPIO口驱动三色LED的三个通道;设定GPIO为推挽输出;采用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮。通过系统定时器实现1s定时,每秒变换一次LED颜色。! s- {0 r' }( Y: n
微信图片_20180306143629.png . ~1 q7 C, v7 G0 {' f$ Y
             图4_4 驱动示意图
三、源代码
1.主函数
  1. /*% P( v  G' \/ X$ K
  2. * Name                : main- A9 ~! z  |. d& X7 i  {2 k
  3. * Description         : ---
    + _, b3 a* X" b$ O
  4. * Author              : ysloveivy.. `! A2 p9 t9 q1 _! G1 g& U4 F
  5. *
    + \( ^; b+ l% Y5 `% M2 q4 e& ]0 z
  6. * History
    + W( R6 b8 u+ k* h; d
  7. * --------------------; S7 Y) P, P8 w6 O; f3 @' h
  8. * Rev                 : 0.00; Y1 r1 l9 W% ]% c
  9. * Date                : 11/21/2015% g) S0 z2 x" Y1 H2 e9 E
  10. *
    - |+ y3 A8 Q: m1 I( ^8 H
  11. * create.9 V% F$ Y' a% Y+ e2 ~. y9 P8 T8 F# Q- Z
  12. * --------------------) C6 X/ v  s; P8 L" z2 |
  13. */) {3 u- w6 R2 M+ q! r! l0 r
  14. int main(void)
    2 |4 u/ V. h6 J
  15. {# ]0 ^' M5 f( K& ]
  16.         static int work_status = 0;
    1 \0 \* J1 I& x1 f; X+ ^% d7 e
  17.         led.initialize();( ?; g% k9 c3 W
  18.         systick.initialize();& t2 o  N0 P7 @/ d7 U
  19.         //每隔一秒三色灯进行交替循环闪烁( E2 ^  V1 D$ `5 a( C( b
  20.         while(1){
    4 w# w5 C- ^, j; I
  21. if(systick.second_flag == 1){ //每隔一秒标志位置1,执行一次
    2 q6 y) m, X! c8 {2 K
  22.                         systick.second_flag = 0;1 g( h* v$ l# ]) I2 x0 a
  23.                         work_status += 1;6 H+ K/ w5 s+ Q% _( b& V( b
  24.                         if(work_status > 2)work_status = 0;
    ) S; s' |& |- }+ ?$ R
  25.                 }
    1 L: ?- m( t. N9 k& n0 @( t. e
  26.                 switch (work_status){0 i$ a: @! A# Z0 u
  27.                         case 0 :* C$ N- B6 N- X) A/ B1 _0 s2 ~; N
  28.                                 LED_RED_ON;
    0 M) l& {# m1 A5 w
  29.                                 LED_GREEN_OFF;4 m5 f  \$ X; i" e* f1 E
  30.                                 LED_BLUE_OFF;
    $ f% K9 H" P% ?7 H; \& B" u) o; `
  31.                                 break;
    4 u; }, J% [- ?' b
  32. * n+ ^4 F2 c6 K& i5 }
  33.                         case 1 :/ f: m9 Z: j" P
  34.                                 LED_RED_OFF;
    ; R/ i4 ~5 R& R0 V* n! Q
  35.                                 LED_GREEN_ON;
    0 s1 p6 D  D9 U3 k& p
  36.                                 LED_BLUE_OFF;0 S7 R4 T7 ~3 E
  37.                                 break;
    5 D6 Q/ W5 Y- F9 K2 L: p+ _- C& a* S

  38. $ e3 I! ]$ q4 H. O# c' B; l
  39.                         case 2:- y4 Z% k  Y% x# ^0 ?
  40.                                 LED_RED_OFF;( C" R; h4 Q+ `' {% k0 f
  41.                                 LED_GREEN_OFF;; x9 L5 G9 A' j4 L7 @7 D; J6 t7 [
  42.                                 LED_BLUE_ON;# D2 O  ?, r0 N$ b
  43.                                 break;/ \. J) a4 @* u

  44. 4 y% C9 e$ q5 C' S9 T: O; L. S4 n& W
  45.                         default:
复制代码
2.Systick初始化
   以下是Systick初始化及中断设置函数,主要实现定标志位的时1s,改变一次标志位,使用LED显色状态变换一次。
  1. /*! b4 k1 d) s) P+ b
  2. * Name               : initialize8 b5 C  L2 J% J* O" W
  3. * Description        : ---8 n; D" u; t& a9 Z2 {8 L
  4. * Author             : ysloveivy.# |0 _. A4 r. O; X  v  f, h+ F
  5. *
    ! J$ Q. I3 j6 g0 U- Z9 q
  6. * History1 m6 L7 P; c" Z5 y
  7. * -------------------, N: {) V7 h4 L# G
  8. * Rev                : 0.008 w, v, P2 \- ^0 ~, z8 d- i
  9. * Date               : 11/21/20157 c! c& V0 A3 m$ q4 i
  10. * % N* T  y7 V* G* e# W+ h; }9 z
  11. * create.
    8 W% w- r: l/ V' |4 G4 I
  12. * -------------------
    6 @; f# F$ I: F! ^
  13. */6 H' L5 d4 B9 Z* _2 }/ E/ H; L0 c
  14. static int initialize(void)
      E: I2 S3 A8 X
  15. {
    & h- y- O  U. e1 v2 N+ ?/ S8 N
  16.         //定时1ms0 c( _: s. ~. o4 ?: r" h
  17.         if(SysTick_Config(SystemCoreClock / 1000)){
    5 B7 u6 d6 b0 X, I2 j# _  ^4 b
  18.                 while(1);
    9 G8 v6 O3 ], p/ H' F
  19.         }
    " d- n. F' a- T- b8 l. {! u
  20.         return 0;) o9 q* d) V, V' ^- }
  21. }
    , b1 i9 s4 x* W) r. n8 ^% m9 Z
  22. /*
    3 Y6 S8 z6 b, e5 b  S; U
  23. * Name               : SysTick_Handler2 }' E7 I- D: g
  24. * Description        : ---9 h6 p! ?0 c0 A0 ]
  25. * Author             : ysloveivy.
    # {6 F4 M# a$ R6 ^. |3 k4 \
  26. * History
    " d7 n5 d/ X: U. _# ?/ o5 V8 g
  27. * -------------------; b3 i) ?6 m) f
  28. * Rev                : 0.00
    # E! d6 J& f  e( {6 e
  29. * Date               : 11/21/2015. K6 k* M( D# V
  30. * 5 @$ L, C' j" X8 @1 b* K; c# R/ A
  31. * create.
    6 s+ w! \9 b" |8 V/ W! o. H# m
  32. * -------------------% l+ _% q3 u. s3 K9 M4 o/ J4 i4 a% X
  33. */
    $ U. K, A1 z% d8 P7 E
  34. void SysTick_Handler(void); i: I, Q8 S3 A9 t
  35. {/ k' _1 g4 t1 ~7 x& l7 T
  36.         static int counter = 0;
    0 ~  h( z0 c3 e2 B! H6 ~/ h8 ^

  37. : e3 D5 v8 y$ ]7 @
  38.         if((counter ++ % 1000) == 0){ //每次中断counter自加1,判断是否整秒% d- g( g3 P3 W. s) A' W# o
  39.                 systick.second_flag = 1;6 O' C: o( M4 _' j7 d
  40.         }
    2 T* c# `; g. A
  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# `2 [# u6 {; \( G
  2. {
    8 p9 g! k" e3 U0 D7 a8 |* v
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)  //大于重载寄存器最大值0xFFFFFF
    # _8 H5 T! d$ |( _  r+ Y) L- e
  4.   {/ o- E7 D& V+ F+ D8 P: t
  5. return (1UL);                                //重新加载值不可能,返回错误           3 Z4 [& k/ h+ y; B: d6 _" _
  6. }5 J9 N) ]6 n; M4 q9 y, J
  7.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);      //计数范围0到ticks-1                  * Y% s1 K% c( \$ |8 b! N, Z( s
  8. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    0 m, q) P- O+ k1 J, |" |5 o
  9. //设置优先级9 Q& p, H& v6 Q* O5 W+ t
  10. SysTick->VAL   = 0UL;                              //当前值初始化为0   
    * w/ J8 _5 [7 S0 H
  11.   //接下来设置控制寄存器,以位与的方式实现三个控制位的设置。& q7 {3 I2 r1 [7 l1 x
  12.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | //选择时钟源7 C, }. ]4 `8 @% f3 b. H* |
  13.                       SysTick_CTRL_TICKINT_Msk   |  //开启中断
    0 \$ e7 R  |' q& c; s
  14.                       SysTick_CTRL_ENABLE_Msk;      //使能定时器               1 L- l9 B2 J' q8 g3 I
  15.   return (0UL);                                       //初始化成功返回         
    2 T2 V1 g$ A! `! K
  16. }
复制代码
     回头看看程序中的SysTick_Config(SystemCoreClock / 1000)语句,该函数中的SystemCoreClock为时钟频率已在库函数中宏定义。如在iCore3双核心板ARM的HCLK为168M(每秒168M次计数),则程序中SystemCoreClock / 1000即意味每1ms中断一次。
    2.void SysTick_Handler(void)
    该函数是中断函数,即每次SysTick中断产生时运行一次函数,其在启动文件中已有设置,在驱动文件中使用时无需再次声明。
8 O0 r5 d7 J1 Q  U6 Z" z7 g
四、 实验现象
     iCore3的双核心板上与ARM相连的三色LED(PCB上标示为ARM·LED),红色、绿色、蓝色每秒交替点亮。
五、 代码包下载链接
  h$ @8 v! t8 M, j3 q
收藏 评论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
: v/ ]8 w* Q+ s大佬,这第一讲和第二讲怎么没找到啊  。。

0 y3 z1 B; U* J2 b你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
zero99 回答时间:2018-3-8 10:37:48
kkhkbb 发表于 2018-3-7 15:26; ~) l" C. A3 x% n4 A
你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
" S# K# g! i, \9 F5 H$ m
另外一个也是你啊  

所属标签

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