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

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

[复制链接]
kkhkbb 发布时间:2018-3-6 14:53
本帖最后由 kkhkbb 于 2018-3-19 09:11 编辑
# L5 D" q3 P) {* t5 e6 R6 b: m
7 u0 R5 n- @! q# A0 h2 t. R
一、 概述
1、 时钟系统简介
(1)STM32时钟源分以下五类:
  • 高速内部时钟(HSI):RC振荡器,精度不高。
  • 高速外部时钟(HSE):可接石英/陶瓷谐振器或者接外部时钟源。
  • 低速内部时钟(LSI):RC振荡器,提供低功耗时钟。应用如WDG。
  • 低速外部时钟(LSE):接外部低频率石英晶体。应用如RTC。
  • 常闭不带复位:锁相环倍环输出(PLL):其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频倍数可调,但是其最大输出频率受限数值因芯片型号而异。
    3 H# Y3 a- K% J$ W$ h! ?3 Y1 ~3 O8 n# a9 Q7 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                         
3 g$ n( Z) v4 `! a- l           图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的格式
+ x# R: g- h: i/ A* ^# L5 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可用;& R! m* t: s: A
1:HCLK不可用。
SKEW 0:校准值是准确的10ms;
; \6 u: d* h* g6 G& l$ o1:校准值不是准确的10ms。
TENMS 该值是10ms定时的重装值。其值取决于SKEW,它可以是精确的10ms,也可以是接近10ms的值。如果该值为0,则表示无法使用校准功能,这很可能是因为时钟是系统的一个未知输入或者时钟可以动态调节。
           表4_1寄存器STK_CALRB的格式
二、实验原理- K0 t- U7 B) n+ o
     通过STM32的三个GPIO口驱动三色LED的三个通道;设定GPIO为推挽输出;采用灌电流的方式与LED连接,输出高电平LED灭,输出低电平LED亮。通过系统定时器实现1s定时,每秒变换一次LED颜色。. g) v& Q4 T: M3 e  q
微信图片_20180306143629.png 6 R, y. F% K$ D* k  X/ z
             图4_4 驱动示意图
三、源代码
1.主函数
  1. /*
    8 R8 O, l, k' ]
  2. * Name                : main
    ! k- n  L, x2 V
  3. * Description         : ---
    ( l+ @. ~7 ~1 o
  4. * Author              : ysloveivy.; L- b$ N: x: k5 r* S, \6 @9 [
  5. *8 t" a# O. ?. t7 M
  6. * History2 X1 z' Z, h0 R' [0 q- ~* w
  7. * --------------------6 y, n7 O* V  b4 `
  8. * Rev                 : 0.00
    1 H6 Z3 b/ s4 U
  9. * Date                : 11/21/2015& Z, e9 |8 H* k  Z) g; z1 f  _2 P
  10. *   J! F9 J1 N. m# I! B
  11. * create.
    1 C" A: _6 ?9 Y' l, E
  12. * --------------------$ q( P1 K  p4 L2 J
  13. */
      \$ ^5 }2 V" t- Y, i
  14. int main(void)
    * K# h, G: a9 ]* m2 p% }- m
  15. {
    7 B4 D, W* i. V
  16.         static int work_status = 0;
    4 s2 h) }/ `$ K/ w
  17.         led.initialize();8 I3 ]- `7 `& r7 i& C
  18.         systick.initialize();
    ) K, l5 w6 @& {- F$ @
  19.         //每隔一秒三色灯进行交替循环闪烁8 Q' {8 o' y$ C0 C& ?4 g( W% L0 ^
  20.         while(1){
    & q! ~1 c0 }5 t7 _. ^
  21. if(systick.second_flag == 1){ //每隔一秒标志位置1,执行一次2 k5 C2 Y3 {. S  @. H2 N
  22.                         systick.second_flag = 0;8 g/ `8 Z2 O+ A
  23.                         work_status += 1;
    - q! q  |9 b% F: X
  24.                         if(work_status > 2)work_status = 0;
    6 C/ j4 b0 B  X8 \, K8 H" i
  25.                 }
    ) G5 s$ `2 e" i6 ?+ \0 K3 Q, [
  26.                 switch (work_status){0 C* W% f( u4 z* ~( m
  27.                         case 0 :; }) e) r1 Q2 F4 ~$ a# E
  28.                                 LED_RED_ON;8 ^. O) `2 G  ]. I# E1 X8 G
  29.                                 LED_GREEN_OFF;* b& W6 c! w6 F8 `: c  Q8 Y
  30.                                 LED_BLUE_OFF;5 ?: Z# R2 z0 m3 @: ]( L+ V8 V6 D1 _4 Z
  31.                                 break;5 y  t3 A9 w" {+ @) Y: E
  32. ( q5 V- q3 J( R, u6 X
  33.                         case 1 :
    ! H& u5 a$ Z8 }  s8 A" f' _
  34.                                 LED_RED_OFF;" i% F* k% J5 I% w4 \7 R
  35.                                 LED_GREEN_ON;& l1 @8 T' U% Z- {
  36.                                 LED_BLUE_OFF;
    - Y9 ]$ d+ o+ Z; Z
  37.                                 break;+ c2 I, d2 [1 }7 G
  38. 0 l( q4 a0 c) I9 \
  39.                         case 2:
    ; u) w: C6 _$ g& F
  40.                                 LED_RED_OFF;5 C3 P$ w5 h) ^2 r# ^  O
  41.                                 LED_GREEN_OFF;5 A. ~3 g5 @, ]+ S) w2 A
  42.                                 LED_BLUE_ON;, F. u0 R8 D  W: E! j
  43.                                 break;
    7 S8 x  y: U& u/ U& t

  44. ) w+ g; C# c4 Z6 `
  45.                         default:
复制代码
2.Systick初始化
   以下是Systick初始化及中断设置函数,主要实现定标志位的时1s,改变一次标志位,使用LED显色状态变换一次。
  1. /*
    2 Q  c& }( m# E. m! K' C
  2. * Name               : initialize
    3 |# X9 H9 {6 `% E
  3. * Description        : ---
    2 d( t8 E. k7 ^7 o5 ]  l( u* W
  4. * Author             : ysloveivy.
    & y8 F. Z% _( h, H4 Z" J  [
  5. *+ j7 z, J  u+ |( o+ f
  6. * History
    ( L' u9 L) R3 k. M  g: q% s5 \$ M
  7. * -------------------
    ! Y% F1 ^* m5 X! X4 n" A
  8. * Rev                : 0.00
    - A) l) [/ @  Q% s
  9. * Date               : 11/21/20152 s; a; G0 \$ V6 l, {" }
  10. *
    ( A% F3 f  L( J  w, |: }
  11. * create.
    " l0 S3 J2 v8 T* e6 C1 @% F% T
  12. * -------------------9 o8 X9 s$ }0 U8 h2 F/ m
  13. */
      [/ |8 P' j' z
  14. static int initialize(void)& s  s* k2 i* p" X4 V9 _# T1 J% j' \: w
  15. {, w8 S, x6 H) l1 ]$ E8 @
  16.         //定时1ms
    : U# i! @7 V' q
  17.         if(SysTick_Config(SystemCoreClock / 1000)){
    / x" ?3 i/ k7 L$ N' G
  18.                 while(1);  G, U9 U& ]7 E
  19.         }1 U; Z* c+ V- D, m# r. f& F
  20.         return 0;
    8 B% Y7 e3 t/ m" ]
  21. }
    " P8 Y8 o& h5 \5 ~8 r: L
  22. /*
    8 Z1 l+ V7 M3 n! g8 a
  23. * Name               : SysTick_Handler
    6 G3 \, N5 J* w& H" p
  24. * Description        : ---/ C$ M6 ~* B* f9 k
  25. * Author             : ysloveivy.
    9 v2 A2 B( i, Z, a( R( C
  26. * History
    5 N1 m; G+ {, \# D" h" U! W' b
  27. * -------------------
    % H& ~# p8 D, O, T! [9 P* F
  28. * Rev                : 0.00
    2 O% ~; F0 }. m/ n8 D4 S5 x
  29. * Date               : 11/21/20159 v+ t" _0 `1 J# J0 f
  30. * 6 l, A1 U0 K# S- ]  `+ K0 i
  31. * create.
    $ g2 l: ?$ o) Z5 z: R' \) ?
  32. * -------------------
    0 |! p; v& v0 o9 Z5 `. M6 P
  33. */& V- c$ W6 _8 s
  34. void SysTick_Handler(void)  }% Y" x2 f4 u" s7 C
  35. {
    ( n# G6 ^' _! _0 U; q- h
  36.         static int counter = 0;, s2 ?1 r8 Q0 r
  37. . t$ {$ }- b% d# ?9 V/ {% M
  38.         if((counter ++ % 1000) == 0){ //每次中断counter自加1,判断是否整秒
    1 d. d7 g2 u. A- o2 v- E
  39.                 systick.second_flag = 1;
    ) d" a- Y( n- g) _' k  W9 c
  40.         }" U' y- d; f' @; S2 R
  41. }
复制代码
3.小知识
   在上面有两个重要的函数
   1.SysTick_Confing(uint32_t ticks)
    该函数的作用是初始化systick,时钟为HCLK(CM3一般为72M,CM4一般为168M),并开启中断。
  1. __STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)- ~( |+ l0 [9 t% m# F
  2. {
    9 M; i/ W- ^9 L, [+ R
  3.   if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)  //大于重载寄存器最大值0xFFFFFF' B8 l1 \6 m. ~2 K
  4.   {2 t- q2 L% O0 N- P/ O
  5. return (1UL);                                //重新加载值不可能,返回错误           
    " }0 D/ q# E- Z% C6 ?
  6. }( c% K- L6 o& Y* G
  7.   SysTick->LOAD  = (uint32_t)(ticks - 1UL);      //计数范围0到ticks-1                  " l" L' c& H5 g4 L5 U3 s
  8. NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
    9 a# ?/ E1 d9 s8 J! |% g: Z
  9. //设置优先级
    ( a$ K% ^6 v( l3 l9 ?) n0 I
  10. SysTick->VAL   = 0UL;                              //当前值初始化为0    6 a$ v+ P4 ~0 P; K
  11.   //接下来设置控制寄存器,以位与的方式实现三个控制位的设置。
    8 |6 K; K8 @' L  O/ r8 I
  12.   SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk | //选择时钟源0 x) ?; ^" t2 ]+ a
  13.                       SysTick_CTRL_TICKINT_Msk   |  //开启中断
      y$ N) d" {6 q% q' ~: F6 ~6 b
  14.                       SysTick_CTRL_ENABLE_Msk;      //使能定时器               
    : K+ e& g+ I6 e& {* V! n# X0 G
  15.   return (0UL);                                       //初始化成功返回         
    * K' ]' g$ h% F% e& {  J
  16. }
复制代码
     回头看看程序中的SysTick_Config(SystemCoreClock / 1000)语句,该函数中的SystemCoreClock为时钟频率已在库函数中宏定义。如在iCore3双核心板ARM的HCLK为168M(每秒168M次计数),则程序中SystemCoreClock / 1000即意味每1ms中断一次。
    2.void SysTick_Handler(void)
    该函数是中断函数,即每次SysTick中断产生时运行一次函数,其在启动文件中已有设置,在驱动文件中使用时无需再次声明。. r' Q/ m+ h5 v' Z4 u4 i
四、 实验现象
     iCore3的双核心板上与ARM相连的三色LED(PCB上标示为ARM·LED),红色、绿色、蓝色每秒交替点亮。
五、 代码包下载链接
& G( }  G% ]; H
收藏 评论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+ t9 `- @0 l. L; Q
大佬,这第一讲和第二讲怎么没找到啊  。。

8 K2 S: y9 X/ V9 D* _你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。
zero99 回答时间:2018-3-8 10:37:48
kkhkbb 发表于 2018-3-7 15:26
6 p. |) R) A2 d你直接搜索【零基础学习STM32】可以找到我们所有的帖子。。

$ o) {2 A1 I+ v另外一个也是你啊  

所属标签

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