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

【安富莱】【RTX操作系统教程】第17章 定时器组

[复制链接]
baiyongbin2009 发布时间:2016-2-2 15:14
第17章    定时器组
    本章节为大家讲解RTX支持的定时器组,或者叫软件定时器,或者叫用户定时器均可。软件定时器的功能比较简单,也容易掌握。被称为定时器组是因为用户可以创建多个定时器,创建的个数是可配置的。
    本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407。
17.1 定时器组介绍
17.2 定时器组API函数
17.3 实验例程说明
17.4      总结

& r5 O6 |5 Y2 c% ]
17.1  定时器组介绍
    RTX提供的定时器功能仅支持单次定时器,也就是用户创建了定时器并启动了定时器后,定时时间到将不再重新执行,此定时器会被删除掉并且就执行一次,下次使用要重新的创建,这个就是单次定时器的含义。另外就是单次定时时间到后会调用定时器的回调函数,用户可以回调函数中加入需要执行的工程代码。
    使用此定时器组注意以下问题:
(1)定时器回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
(2)定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,因为回调函数是在滴答定时器中断中执行的。
(3)RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建。
(4)可以创建的定时器个数可以在RTX配置向导中设置:
17.1.png
7 q8 Z: g1 g3 {. H" t$ N4 X  t* k
赞 收藏 评论4 发布时间:2016-2-2 15:14

举报

4个回答
baiyongbin2009 回答时间:2016-2-2 15:24:32
17.2  定时器组API函数
   使用如下3个函数可以实现RTX的定时器组:
os_tmr_create
os_tmr_kill
os_tmr_call
关于这3个函数的讲解及其使用方法可以看教程第3章3.3小节里面说的参考资料rlarm.chm文件
17.2.png
                              
这里我们重点的说一下函数os_tmr_create和os_tmr_call。
$ W1 a: C1 b; K  x: H0 {
17.2.1  函数os_tmr_create
函数原型:
  1. OS_ID os_tmr_create (
    $ A/ s6 I; s! K8 ~/ d8 y! D
  2.     U16 tcnt,      /* 定时器的时钟节拍个数 */
    # j3 H5 Q% n( T" Q- F
  3.     U16 info );    /* 定时器回调函数的参数,可用于区分不同的定时器 */
复制代码
# ?3 U6 Q- z0 e' Q7 i+ t9 W2 A
函数描述:
函数os_tmr_create用于创建定时器组并启动定时器,定时时间到后调用回调函数os_tmr_call。函数os_tmr_create的第二个参数也会传递给回调函数os_tmr_call用于区分不同的定时器。
    (1)第1个参数填写定时器的时钟节拍个数。范围0-0xFFFF。
    (2)第2个参数填写回调函数的参数,可用于区分不同的定时器。
    (3)定时器创建成功的话会返回定时器的ID标识,失败的话返回NULL。
使用举例:
  1. #include <rtl.h>, [& p6 [& m% e/ J0 Y- n! u, b
  2. $ x3 F! M2 V6 a) |: A
  3. /* 定时器句柄 */! P+ |5 [  e+ r
  4. OS_ID  OneShotTimerID1;- }. @( e; e" `% C0 O( ]% ^' q) D

  5. $ C* T; X6 I7 X" r/ `
  6. __task void task1 (void) {
    9 L* n  F, ?6 h, [+ W2 n( `- P
  7.    ..
    5 H: E8 T  g, u0 R/ K( E- _
  8.   OneShotTimerID1= os_tmr_create (10, 1);2 N; M, v3 B6 D4 o+ w# B
  9.   if (OneShotTimerID1 == NULL) {" @: }0 A! _" N8 Z/ R
  10.     printf ("创建失败\n");
    8 A& P5 M& W7 V4 b5 R
  11.   }( S9 H# h, c, f/ }
  12.    ..
    8 F5 y8 l9 y# y% E1 x* L
  13. }
复制代码

  U/ A9 G+ I- ~( y& Q3 i' |. I" G" n0 z% q. ~0 O
17.2.2 函数os_tmr_call
函数原型:
  1. void os_tmr_call (( l  ?& r. ~) N* a- D4 {/ V
  2.     U16 info );    /*定时器回调函数的参数,可用于区分不同的定时器*/
复制代码

8 m, m6 c' d, x; J
函数描述:
当函数os_tmr_create设置的定时时间到后调用回调函数os_tmr_call。函数os_tmr_create的第二个参数也会传递给回调函数os_tmr_call用于区分不同的定时器。此函数执行完毕后,通过函数os_tmr_create创建的定时器会被删除,下次使用需要重新创建。
(1)此函数的参数不需要用户去添加,系统会自动将函数os_tmr_create第二个参数赋值给这个参数。
使用举例:
  1. #include <rtl.h>
    9 n  g7 Q, Y' A1 {! i
  2. & o+ h5 t9 n3 v5 G* i4 h) B' P
  3. void os_tmr_call (U16 info) {
    5 s) h+ f% I, y3 g, \
  4.   /* 定时器回调函数中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在
    % v+ h3 j! j4 F9 ]2 R/ A
  5.      滴答定时器中断中执行的。
    # [% v, W9 E5 {8 C( t8 y
  6.   */+ C" [. Q* M" }6 l0 f% W+ p
  7.   switch(info), I. |) ^; j6 W( W2 @7 n
  8.   {4 d, K6 ]0 A7 \2 M" [
  9. case 1:          /* 参数为1 */+ h# I; R) w* x. E, V: S  o/ ^
  10.          isr_sem_send (&semaphore);     
    ) `# U) \4 O! T4 s, |" x2 u  Z
  11.          break;- ?! i- C- @4 d  j
  12.          
    + K$ d$ e- ~# O# V' K; D
  13.       case 2:          /* 参数为2 */# l& o; T: p" G5 _3 d* A
  14.         bsp_LedToggle(1);   
    # k* ]1 g$ T  u, [/ Y
  15.         break;# N( g, M: L) p' O0 i3 E
  16.   }% u/ D  ^- f5 N% t. c. ]  z# {
  17. }
复制代码

& G! C. ^5 s* L
6 h( Z; U' J1 i( \0 u$ W$ R
baiyongbin2009 回答时间:2016-2-2 17:28:17
17.3 实验例程说明
; ?  h9 k+ q& [
17.3.1 STM32F103开发板实验
配套例子:
    V4-416_RTX实验_定时器组
实验目的:
    1.     学习RTX的定时器组
    2.     RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建
    3.     定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在滴答定时器中断中执行的。
    4.     回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务AppTaskMsgPro发信号量同步信号。
    3.K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1。
    4.各个任务实现的功能如下:
  AppTaskUserIF任务   :按键消息处理。
  AppTaskLED任务     :LED闪烁。
  AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
  AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:
    RTX配置向导详情如下:
                              
17.3.png
Task Configuration
    Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
    Number of user timers
  范围1 – 250,表示用户定时器个数。
  这里创建了1个用户定时器。
RTX任务调试信息:
17.4.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
17.5.png
RTX初始化:
  1. /*
    4 s3 B4 H* ~0 B/ q7 Y- \) g
  2. *********************************************************************************************************% |' B/ @/ e5 d% ]' C
  3. *    函 数 名: main
    ; d. Q# F2 a! @% ^8 ^# ^
  4. *    功能说明: 标准c程序入口。) i0 F- q) n7 H
  5. *    形    参: 无
    8 q( j  r7 H6 Y8 H. y
  6. *    返 回 值: 无& m, k& D* v: Z
  7. *********************************************************************************************************' T* ~$ P: ]& [* D8 \
  8. */
    ( D& R- v/ f. |; V
  9. int main (void)7 K. u+ y. v2 Q! \$ W4 ]
  10. {   
    ! ~1 `! G- e4 B* ]
  11.      /* 初始化外设 */' K9 F$ u) z0 {
  12.      bsp_Init();
    * ]( P) a" q6 S1 G! j
  13.     ) K$ J" k/ [% L7 }& C1 O3 l# p
  14.      /* 创建启动任务 */
    . P; D. S& C0 ]  t! m$ G9 @2 u
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */- c! ?5 j8 x$ Q; k3 V7 z
  16.                        4,                        /* 任务优先级 */) y1 S2 P8 ^: S4 r" e
  17.                        &AppTaskStartStk,         /* 任务栈 */
    % Q9 g- g" B6 i0 a! ~+ _
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */  e- g4 `! W) z* V+ G& i
  19.      while(1);
    9 k  w: C- b& n
  20. }
复制代码
1 Q* N  L2 K1 b; j
RTX任务创建:
  1. /*
    ! T! E9 ^- o% i
  2. *********************************************************************************************************# e: Q& X6 O( t& f$ ?
  3. *    函 数 名: AppTaskCreate
    7 ]+ r- Y( }* n! {  |6 V
  4. *    功能说明: 创建应用任务% J, D0 `* ^# Y) D* y
  5. *    形    参: 无5 g9 D- f& v  U- @" v- P. q
  6. *    返 回 值: 无6 d: N4 F& B1 v- k. T
  7. *********************************************************************************************************
    . `: l/ ?' W6 ]6 l+ `8 r  }8 U
  8. */
    ) o1 U( C9 y# z+ a, |8 L' u
  9. static void AppTaskCreate (void)
    4 O3 s; Q. l: K0 ]. |# d- b* |1 y  S
  10. {
    0 u0 U2 z$ l, Y: V. w
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    $ d" Z7 F2 e2 V9 d  A. A
  12.                                            1,                         /* 任务优先级 */  Y- D  D. V9 }- N
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */: T6 F3 H# J, L- ~! D, w
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */! C* K9 _  S3 S$ W# a9 a- g
  15.    
    4 D" q2 W9 U0 Q  B- a( H& o* L
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */: x, A) q; L: r. p: [0 `
  17.                                         2,                       /* 任务优先级 */
    ; ]  v! j; [2 W. G0 Q. K! J0 l
  18.                                         &AppTaskLEDStk,          /* 任务栈 */) D$ T) O8 Q) w. U, ~( M2 N
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    8 _- Q( v# B( y% E' ]7 W2 \
  20.    
    , u( y( n% {4 v/ z% u- ]9 @0 |$ H2 q
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */7 g% F7 \  {1 z; y5 e7 ~; X% }. Z
  22.                                            3,                         /* 任务优先级 */7 ?/ G, z6 U) C+ [; X) {
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
    8 G) e; d) D% w
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    : S9 A- P* V! _$ U+ ~9 D$ H
  25. }
复制代码
/ t) f6 g% [% o
创建信号量:
  1. OS_SEM semaphore;
    $ \4 w5 I1 z* \! v, Q

  2. ( O. Y( w- i  n% T4 R8 M
  3. /*
    : \" a2 C, _$ M( ~( Q9 \7 _4 }4 d
  4. *********************************************************************************************************
    : Y' ]% u# V4 k' U1 S
  5. *    函 数 名: AppObjCreate5 N4 D0 p, O+ @( ~
  6. *    功能说明: 创建任务通信机制
    9 T! a/ d/ e% W' }6 E' u3 f
  7. *    形    参: 无& G6 L; K: `: M
  8. *    返 回 值: 无# h$ m5 k% Q0 w+ P2 x3 A; a. y
  9. *********************************************************************************************************
    & O! t" H7 h3 c+ j/ x1 U
  10. */! F$ E% G3 R8 c. }
  11. static void AppObjCreate (void)
    ! G8 m3 J$ }1 y9 Y" U
  12. {. [$ \6 l  T% s- g* M% B
  13.      /* 创建信号量计数值是0, 用于任务同步 */
    ' `! i5 O7 O! h9 O2 m; M/ ]( C' B
  14.      os_sem_init (&semaphore, 0);
    3 [: }' m8 \' c. K
  15.    
    - P0 T6 F( H# ~5 l, H. T0 j
  16. }
复制代码
, Y0 s3 ~5 F2 _) X7 Y% d, K
四个RTX任务的实现,定时器的创建在任务AppTaskUserIF中实现:
  1. /*5 p/ q( k. s6 p7 g
  2. /*
    , @" A" c8 m6 i7 G
  3. *********************************************************************************************************
    # G/ R" Y# _6 @
  4. *    函 数 名: AppTaskUserIF
    8 L, k+ _/ L5 \
  5. *    功能说明: 按键消息处理     
    0 L0 D: ]3 j3 F* N0 H
  6. *    形    参: 无
    1 D! J% S% c$ ~5 O( `
  7. *    返 回 值: 无6 H5 S& p6 S2 ?1 X: o) y8 z- K
  8. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)
    : U% s% ?3 W8 h* m2 d- o
  9. *********************************************************************************************************; u$ A  q! r+ v/ h4 R
  10. */
    ' a4 l! L& c9 j& E7 {' P9 m1 f
  11. __task void AppTaskUserIF(void)1 z$ w' {. \: {1 S& ?
  12. {. d' b0 p/ U$ J2 T
  13.      uint8_t ucKeyCode;
      L" o. J+ q9 G1 d9 S' F# _5 G

  14. ) q, _7 v! }1 Y  s3 |$ T: Q' w* P, @, h
  15.     while(1)
    + H+ t, u  E+ J! S, d% s
  16.     {- U" }% Z4 {$ H/ B* R0 p5 z" x
  17.          ucKeyCode = bsp_GetKey();
    6 O6 l) o8 J3 `/ \; V' I8 k: h
  18.         . V% o% R1 j) X4 y( t2 P# n. X8 u
  19.          if (ucKeyCode != KEY_NONE)
    6 n8 n+ q+ N& x% m( C% k" ?
  20.          {3 h4 C* K7 G& I7 A. x6 g
  21.               switch (ucKeyCode)
      V4 ~6 V* l9 y. m1 }) X
  22.               {
    # P6 r4 `$ ^2 W5 `' ~
  23.                    /* K1键按下,打印调试说明 */) E" N  ]9 E6 N( j5 I) o
  24.                    case KEY_DOWN_K1:
    % D1 a! d( d( r6 b1 k0 E
  25.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");# P1 K; r: `: R$ E7 t' H
  26.                        break;    I; L, C6 M/ ?+ [. r- M
  27.                   
    + r! M5 h1 h9 C6 E+ B
  28.                    /*
    , u. @+ T. i( B1 l, b7 L! M
  29.                       K2键按下,创建单次定时器,定时时间10个系统时钟节拍, 在定时器回调函数中给任务+ B: g; I: j) u7 i% L
  30.                       AppTaskMsgPro发信号量同步信号0 i- T2 S% N7 [7 j
  31.                    */" u! c9 R$ n) @, w) v
  32.                    case KEY_DOWN_K2:
    3 b1 }4 g+ P$ S
  33.                        printf("K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务
    0 p4 q$ }; W0 l4 `6 z& u
  34. AppTaskMsgPro发信号量同步信号\r\n");% y) ]+ V% K" [$ o
  35.                        /*
    4 ~6 T1 A' F, z% k6 s5 T0 C$ t- s8 N# ]- P
  36.                          1. RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建  S5 L! |2 f' B- i- A
  37.                          2. 定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函3 t# V6 b( f' U3 e1 `
  38. 数是在滴答定时器中断中执行的。
    1 {6 N  X/ M! n. I
  39.                          3. 回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
    & {8 u! f: g6 C& ~& |' F) k
  40.                        */
    % \' Z$ g* G0 [1 e8 i7 D
  41.                        OneShotTimerID1 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */
    " k/ b# e% C6 C& S- }
  42.                                                       1);  /* 回调函数的参数,可用于区分不同的定时器 */
    % X% W7 t' Y5 i( p
  43.                       / k8 `' q- H  A2 N0 r5 O6 z
  44.                        if (OneShotTimerID1 == NULL)' a  d/ R' S" O# m5 `
  45.                        {# k9 l2 Y/ {( _$ Y1 r5 m
  46.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */2 q. P! U5 f0 i7 T% B
  47.                        }$ m4 l) S) J2 t7 }+ w" B" A, S; a
  48.                        break;
    ' J6 o2 V( t  e. |" J5 i: x
  49.                      
    6 _2 _; f% u: w& n( |7 o; }
  50.                    case KEY_DOWN_K3:
    0 z) u; F; Z( J- p) l! X
  51.                        printf("K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1\r\n");
    4 d0 a* P! N' M4 ?
  52.                        OneShotTimerID2 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */+ U3 _: p/ r3 v$ G  O% s7 K
  53.                                                        2);  /* 回调函数的参数,可用于区分不同的定时器 */1 c# W" R! r# a2 e
  54.                       1 }/ C# p! M, U4 j; o7 h% O/ Z
  55.                        if (OneShotTimerID2 == NULL)
    0 K, \2 Y3 `+ O  Z1 }$ v! P
  56.                        {0 K+ K  w% n5 @6 F6 y" h+ o# w
  57.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */5 O! ?& ^2 u, H0 I; ]9 G6 a0 w
  58.                        }
    # r8 x3 V  O; [
  59.                        break;
      d  ?: u2 F4 U5 A1 |1 Z

  60. 9 q. `, p( P& }0 \; r- e& T
  61.                    /* 其他的键值不处理 */% i' S: W$ P! A: g
  62.                    default:                    
    + {( @% Y+ T$ d1 I+ @6 _
  63.                        break;
    + s# H& a- g: }+ [7 |" N  g* `
  64.               }
    2 N9 c. \: E. o; T% p: ^! e
  65.          }
    4 [; }8 r  m" ~
  66.         
    ; j& Z! H, W: `" |6 ^# ~, J" X
  67.          os_dly_wait(20);
    ' K* A  J" U9 }2 G( h/ X" x8 Y4 e0 `
  68.      }7 ]2 Y3 Z4 G' D1 y0 }7 A, }0 q- J
  69. }
    , D, @8 I! r, n! }3 B5 c0 d- Q
  70. $ ?, Z2 I7 S; ]4 F
  71. /*: k  R1 S; h7 Y! \) F
  72. *********************************************************************************************************
    # E) }5 l& y$ ?4 b& `" [
  73. *    函 数 名: AppTaskLED- H5 o% S  V& p) n
  74. *    功能说明: LED闪烁。2 Q  Q7 \% U% K# S8 ]
  75. *    形    参: 无# H" g$ c2 w8 O" T. E3 R# c9 U
  76. *    返 回 值: 无* |3 _' X3 P$ ?  h" d
  77. *   优 先 级: 2 ) B, V  d( ]# x6 C
  78. *********************************************************************************************************, z2 {* ^- J* {/ o. W2 O
  79. */; I! l& ]& G# [7 E- @" M$ Y! m  {. J
  80. __task void AppTaskLED(void)0 ?3 f9 C( _* D/ q# k  W- B
  81. {: o* C1 T  Z) Q
  82.      const uint16_t usFrequency = 200; /* 延迟周期 */. B, D0 m1 I6 s: E  e, ?0 y
  83.     : X5 e. h  h. ?$ {5 w
  84.      /* 设置延迟周期 */
    ; V2 }' o6 S) O1 ^+ |1 M
  85.      os_itv_set(usFrequency);
    . O5 h  P- Z; h6 ^: P
  86.     0 v- ?  H# @+ n2 @* u
  87.     while(1)
    % t9 j: z9 ?) y* _5 n0 ^3 w
  88.     {
    1 N$ b# X& [0 e+ K
  89.          bsp_LedToggle(2);- @& N- E& W. K- C* o5 [: u
  90.          bsp_LedToggle(3);
    # G6 S  m2 ^4 K5 O5 |" f8 O
  91. $ X4 `9 ~  ]  N& w
  92.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/
    6 z, _( E# k" I3 M3 Y/ P& x
  93.          os_itv_wait();
    9 m, b1 A; E+ Z% j* g7 ]
  94.     }4 U! @1 R9 y2 o+ s
  95. }7 c: D: t6 |( ]/ [- E# ?6 G

  96. ( j0 F( w) l9 F, H1 ^5 W  N
  97. /*( j  Y" |, l9 I' H
  98. *********************************************************************************************************
    , L/ M  \+ P, G& f& x
  99. *    函 数 名: AppTaskMsgPro
    ! h9 ~+ j" U6 B( h% C! I
  100. *    功能说明: 消息处理,等待RTX定时器发来的信号量同步信号' E- q$ ?# E: B2 b
  101. *    形    参: 无
    9 x6 A9 t: I% ~1 T) W3 f
  102. *    返 回 值: 无
    0 k  H$ ^' G) ?8 a- H
  103. *   优 先 级: 3
    3 G7 `& e/ H* E( p0 X
  104. *********************************************************************************************************
    + g5 T3 K% A+ Z4 O3 V$ }* ^$ W7 i
  105. */5 `; f9 P$ @$ L
  106. __task void AppTaskMsgPro(void)
    6 t- D# E% M* V, e; t# H3 w
  107. {
    # N" c' X3 @& ^) X0 X1 x
  108.      OS_RESULT xResult;
    ) p0 m" M4 y) o# \' |3 v! o
  109.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
    + |1 X0 n* ^/ A$ j' D. C
  110.    
      y* a0 R& d" O3 |9 ?
  111.     while(1)
    + g, m1 a" h" @: l
  112.     {' p$ `7 I2 ]$ J$ B) ~
  113.          xResult = os_sem_wait (&semaphore, usMaxBlockTime);1 D4 O8 L& n/ S0 E, |
  114.         % |! X4 ~- ~) t+ [
  115.          switch (xResult)
    ( t- f. j" q8 x/ b6 W, W
  116.          {
    * w/ M# R7 p- X: A+ H/ y, u$ r
  117.               /* 无需等待接受到信号量同步信号 */
      Q, r6 p$ b, B3 D5 ~
  118.               case OS_R_OK:8 l0 I$ j1 x) v- P
  119.                    printf("无需等待接受到信号量同步信号\r\n");
    & g/ L( e/ C. G$ {( |
  120.                    break;  
    9 i7 V" d6 W; p2 L  o' q2 Q+ Y
  121. * q/ k) O' R* ]8 @& F- u
  122.               /* 信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号 */, I: r+ b) e$ M( N
  123.               case OS_R_SEM:, T! x; C8 i% ^+ [
  124.                    printf("信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号\r\n");
    0 f- f" c2 o. T( Q6 y
  125.                    break;9 t! r7 V' T0 e$ ~
  126. 9 L) p# B4 z$ w# R, ?
  127.               /* 超时 */$ Z' }4 z- ]% _# Q, U( ]( ^
  128.               case OS_R_TMO:
    3 D* _% q) ?0 D- m7 @
  129.                    bsp_LedToggle(4);
    * p( B  [9 M0 c& w* N% j, I
  130.                    break;
    9 H& O1 H. @- t, s- L5 d0 C: q6 ^
  131.              : a8 b. W7 _" Z) [6 [+ m* ]4 i1 a
  132.               /* 其他值不处理 */7 B. [4 _5 m! A4 j% d. j- d
  133.               default:                      ~  C8 E( a9 q$ o+ o" z
  134.                    break;
    , K" E# S  q6 T
  135.          }   ! I- o& M/ C4 J2 c* N' c
  136.     }9 p4 D) E- D' L& _/ z1 F3 O1 l
  137. }
    * g! C1 {; {5 v  B3 K' v8 Y& a5 {) x

  138. 3 X! F& N5 Y, h7 k  c& E: }8 @# ~+ k' O
  139. /*3 j3 o  s/ x4 ?, q
  140. *********************************************************************************************************2 X  |: f( \5 a& L% U& [  h
  141. *    函 数 名: AppTaskStart; v+ e6 D4 [( C0 \/ F
  142. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。; B" i" T  k) m7 D0 Y' }  }7 d! a
  143. *    形    参: 无
    % l) p8 e  i, g8 C
  144. *    返 回 值: 无
    ) l9 r! E: z' m& E; z2 ?
  145. *   优 先 级: 4 . f( Z7 s* k, m1 D) J( v8 _0 ?
  146. ********************************************************************************************************** V( C3 W1 G' [/ i+ i9 l
  147. */7 h8 x! S$ G" d  G  e
  148. __task void AppTaskStart(void)
    ' S$ N' N% i9 R6 Y# {$ M9 t  Q! [, T
  149. {
    $ E0 l1 W/ n$ L. b7 B6 _9 X
  150.      /* 创建任务 */# d7 L, t$ t6 K4 N. S; p- Q$ y
  151.      AppTaskCreate();* @0 [( t" Q; f# e4 c& G1 K
  152.    
      ^9 }& k1 S* `9 y, P
  153.      /* 创建任务通信机制 */& ^" U$ q3 L  d2 e% |
  154.      AppObjCreate();
    ) o. D. F- r+ A6 v9 ^
  155.    
    9 z0 d* A( y3 s; z8 I3 j% T
  156.     while(1)
    : H- D* E0 G! O* u2 w1 X9 d8 z
  157.     {
    * w+ j/ C' E( X1 h( x
  158.          /* 按键扫描 */+ X6 U- I7 F1 s' r: R% d
  159.          bsp_KeyScan();
    & I& Z/ ]+ H$ x* _0 F  i
  160.         os_dly_wait(10);
    3 w" `+ s! J$ M1 |
  161.     }
    ( U& D9 \# B6 J' u' @9 ~) \2 k$ i
  162. }
复制代码
9 ~' s9 i: W, h, f8 R
定时器回调函数的实现,在文件RTX_Conf_CM.c:
  1. /*--------------------------- os_tmr_call -----------------------------------*/, A8 n% a0 q' @, B6 U: I5 E3 C, d
  2. #include "bsp.h"% E/ }8 R5 s  E- O( R1 s! O
  3. extern OS_SEM semaphore;) ~6 o! Y# Q+ c. [
  4. void os_tmr_call (U16 info) {% y5 y! o0 x& }2 B; V
  5.   /* This function is called when the user timer has expired. Parameter   */9 ~3 |3 [* e8 [  ]2 _
  6.   /* 'info' holds the value, defined when the timer was created.          */
    * i8 |  ?, [/ R

  7. 4 y# Z( i7 a; X  ?& w+ J# `
  8.   /* HERE: include optional user code to be executed on timeout. */0 r4 P6 w+ c; }8 W* m: n9 P- `
  9.   /* 定时器回调函数中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在# Z8 U  W3 Z7 [5 v5 @4 N* v! w- m
  10.      滴答定时器中断中执行的。0 U( t) C3 W9 e" A* }, G
  11.   */
    ' s' A# W/ r- F# ?: o
  12.   switch(info)
    . A" x4 S6 x# A  n
  13.   {
    % X$ V& f" p) Q' o1 B" M6 J( _
  14.      case 1:          /* 参数为1 */
    & _& f8 j. G6 d" o" A7 o6 J
  15.       isr_sem_send (&semaphore);     ' m2 Q4 s' h6 J
  16.       break;6 z0 a. G! H8 M9 R  f& v2 {
  17.     * T- ~7 d3 B: Z2 t9 c
  18.      case 2:          /* 参数为2 */, E; e+ `  v, T0 d) a
  19.        bsp_LedToggle(1);   ) R. T8 Y! d$ G" E* F0 ^0 N
  20.       break;
    5 Y; F: H3 z  A+ A) R' E2 R
  21.   }
    ' D! z4 D. r4 w5 A, w7 U
  22. }
复制代码

! N* e: S: t2 I( D) A* h
0 J/ Y& G& c* X( Y
7 `9 q% W; p) C4 ?
baiyongbin2009 回答时间:2016-2-2 17:33:05
17.3.2 STM32F407开发板实验
配套例子:
    V4-416_RTX实验_定时器组
实验目的:
    1.     学习RTX的定时器组。
    2.     RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建。
    3.     定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在滴答定时器中断中执行的。
    4.     回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。
实验内容:
    1.K1按键按下,串口打印。
    2.K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务AppTaskMsgPro发信号量同步信号。
    3.K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1。
    4.各个任务实现的功能如下:
    AppTaskUserIF任务   :按键消息处理。
    AppTaskLED任务     :LED闪烁。
    AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
    AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
RTX配置:  
    RTX配置向导详情如下:
                              
17.6.png
Task Configuration
Number of concurrent running tasks
  允许创建4个任务,实际创建了如下四个任务:
                AppTaskUserIF任务   :按键消息处理。
                AppTaskLED任务     :LED闪烁。
                AppTaskMsgPro任务 :消息处理,等待RTX定时器发来的信号量同步信号。
                AppTaskStart任务    :启动任务,也是最高优先级任务,这里实现按键扫描。
    Number of tasks with user-provided stack
  创建的4个任务都是采用自定义堆栈方式。
    Number of user timers
  范围1 – 250,表示用户定时器个数。
  这里创建了1个用户定时器。
RTX任务调试信息:
17.7.png
程序设计:
任务栈大小分配:
    staticuint64_t AppTaskUserIFStk[512/8];   /* 任务栈 */
    staticuint64_t AppTaskLEDStk[256/8];      /* 任务栈 */
    staticuint64_t AppTaskMsgProStk[512/8];  /* 任务栈 */
    staticuint64_t AppTaskStartStk[512/8];     /* 任务栈 */
    将任务栈定义成uint64_t类型可以保证任务栈是8字节对齐的,8字节对齐的含义就是数组的首地址对8求余等于0。如果不做8字节对齐的话,部分C语言库函数,浮点运算和uint64_t类型数据运算会出问题。
系统栈大小分配:
17.8.png
RTX初始化:
  1. /*/ c. A' A) r5 b
  2. *********************************************************************************************************' Z1 Y, y: C! N( S  J
  3. *    函 数 名: main9 P. j- R' u1 ?) |* d0 A1 T+ C4 ?
  4. *    功能说明: 标准c程序入口。
    ; P3 d9 I$ p) S4 r! k
  5. *    形    参: 无( C/ G! m7 \, B
  6. *    返 回 值: 无
    % I8 E# j: z8 s' ^1 n$ ?% u: f
  7. *********************************************************************************************************
    % m6 u9 E! S, J1 T  d6 {- z( V
  8. */  L. t2 c) o2 q& k1 j9 }% [6 @
  9. int main (void)
    : ]4 ^$ G- x( j
  10. {   , ?! j* D5 j2 Z/ v
  11.      /* 初始化外设 */9 t; g$ D) m! Z6 h2 c6 ^: F2 L6 q
  12.      bsp_Init();
      D; ]6 x; y1 [8 f! P( ]7 J( A
  13.     ) m6 y0 b. g: D/ B! a8 v
  14.      /* 创建启动任务 */
    # ]( d: l& r7 U; b
  15.      os_sys_init_user (AppTaskStart,             /* 任务函数 */) Z3 ?4 y2 m7 m% d, b3 d
  16.                        4,                        /* 任务优先级 */& I! P* _8 c4 R0 Q5 u
  17.                        &AppTaskStartStk,         /* 任务栈 */: I( _5 A  ]  j0 m, y1 l
  18.                        sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */6 \1 k/ R" {* [% @2 L. u* `& z2 O
  19.      while(1);
      {0 O+ V4 V4 {% [, \
  20. }
复制代码
1 M6 n9 R" n1 U% |7 R6 a
RTX任务创建:
  1. /*/ }+ [5 T3 l: [7 T- l+ ]8 l
  2. *********************************************************************************************************
    : c: B# }- n8 @! U7 M. D
  3. *    函 数 名: AppTaskCreate
    # j7 ?; N6 V, R) T% S" J- a
  4. *    功能说明: 创建应用任务
    9 k' Z' _' m' u3 m* F
  5. *    形    参: 无
    . C( p# e) D& {. a  {8 i
  6. *    返 回 值: 无& m9 d+ Z2 {) y& R
  7. *********************************************************************************************************) e4 u9 u% F' e9 e
  8. */" C+ |; T. B' m6 u+ p' Y+ {
  9. static void AppTaskCreate (void); Q8 d1 |6 Z, o- F' z' W& Y4 E6 J
  10. {
    3 Q# ?% O; F; c& [0 k# l. G
  11.      HandleTaskUserIF = os_tsk_create_user(AppTaskUserIF,             /* 任务函数 */
    4 F" l" P; ^  R
  12.                                            1,                         /* 任务优先级 */
    . {" T2 ]* P2 b2 F" G& B6 \+ c
  13.                                            &AppTaskUserIFStk,         /* 任务栈 */! }: r- F- j( \: |: v
  14.                                            sizeof(AppTaskUserIFStk)); /* 任务栈大小,单位字节数 */# N" o; V/ Z. O5 d& o$ H
  15.    
    ; z7 v! C# N% M  @7 z
  16.      HandleTaskLED = os_tsk_create_user(AppTaskLED,              /* 任务函数 */& P  V/ m" k/ A7 `/ Z. r
  17.                                         2,                       /* 任务优先级 */
      l1 K$ B" n6 j$ p) X
  18.                                         &AppTaskLEDStk,          /* 任务栈 */
    ! M5 \& Y) x7 K/ C4 k& w
  19.                                         sizeof(AppTaskLEDStk));  /* 任务栈大小,单位字节数 */
    ' u- ~# a2 L. w; l) f
  20.    
    0 ^) h8 W- i1 `, J( s
  21.      HandleTaskMsgPro = os_tsk_create_user(AppTaskMsgPro,             /* 任务函数 */
    0 R  O) q# s: b( W% O/ a9 O, f
  22.                                            3,                         /* 任务优先级 */  |; j! b+ x" b5 ~# Z
  23.                                            &AppTaskMsgProStk,         /* 任务栈 */
    8 O7 W+ a8 g# b; D
  24.                                            sizeof(AppTaskMsgProStk)); /* 任务栈大小,单位字节数 */
    ! {2 }. m5 L8 f" q9 c
  25. }
复制代码

% b5 ^* Y4 G' k/ O# R' V
创建信号量:
  1. OS_SEM semaphore;% o" c4 }  L9 \" h5 @' {( D

  2. 3 Y* N; K8 `/ t- b: k$ b+ I
  3. /*( m$ b6 _! v3 l* Y4 E; g
  4. *********************************************************************************************************
    2 Z6 ]- |$ o" H1 \9 x9 n
  5. *    函 数 名: AppObjCreate
    1 o* n$ g" y! a% w( P1 v6 [* i
  6. *    功能说明: 创建任务通信机制; I  R7 `- e; e
  7. *    形    参: 无
    2 }( d% q- N2 r8 ?  ?2 ?  g# G4 N
  8. *    返 回 值: 无; D7 J7 a% R0 j" }  _5 o8 V
  9. *********************************************************************************************************
    # [. i6 g& A: f3 w# x/ ?4 R5 r
  10. */
    : d1 \2 w; k* A0 z$ J
  11. static void AppObjCreate (void)
    2 S2 i: N% G% l0 h. ]2 ~
  12. {
    + \+ Q- t, w4 z5 B$ @
  13.      /* 创建信号量计数值是0, 用于任务同步 */3 [% X* M# v6 U  e; g; g
  14.      os_sem_init (&semaphore, 0);
    ) W2 p, y* T# X( z( i
  15.    
    1 \6 h4 K8 ~% i* I* W3 o8 S
  16. }
复制代码
$ O; X  k: [3 G' \0 Q, a
四个RTX任务的实现,定时器的创建在任务AppTaskUserIF中实现:
  1. /*2 `) a7 g6 }( @  B3 s6 V
  2. /*
    ! p8 m+ U8 h# v2 a5 Q# p8 \4 u) e
  3. *********************************************************************************************************) e& n' U; a' ]* O7 P; K
  4. *    函 数 名: AppTaskUserIF7 k+ G) k: s; U% @" u6 L; g, X# {
  5. *    功能说明: 按键消息处理     
    7 J2 A1 u3 t' M: c" O( ?
  6. *    形    参: 无3 ~! T' H. a! T! V5 ^( Y
  7. *    返 回 值: 无
    - V4 W- ~9 S, W2 T; ^: l0 l
  8. *   优 先 级: 1  (数值越小优先级越低,这个跟uCOS相反)& n3 d. {2 S6 X7 \9 c
  9. *********************************************************************************************************/ o3 F) b" S+ Z8 n# [, O5 p9 o2 S, H% m
  10. */1 }  x4 F( T1 y3 F2 m
  11. __task void AppTaskUserIF(void)
    ' C! P$ T8 }5 H0 m' x
  12. {! ~& W9 U( k' C* Q3 K* r9 x( b) ]  K$ ]
  13.      uint8_t ucKeyCode;3 V: u/ m. l( V, j1 I
  14. + Y0 a& R# |, a/ Z0 Q( P# }1 Q+ D
  15.     while(1)) y+ n- j! p7 Q+ l! U( C, M, @
  16.     {& D6 R4 P! e- R) D% ^* p& \  v
  17.          ucKeyCode = bsp_GetKey();$ u7 t, e6 D; b
  18.         
    0 y: f( i% T$ l) h# m, a/ P( G* Q
  19.          if (ucKeyCode != KEY_NONE)% e- f0 Y; H4 T; Z; s" W2 a
  20.          {
    # ?0 H/ M! N) R3 H3 \
  21.               switch (ucKeyCode): |( X% b# |/ t7 l
  22.               {3 x3 p9 R- C+ c# U+ w, R  H) E
  23.                    /* K1键按下,打印调试说明 */
    3 `% D, w: Q0 [" h
  24.                    case KEY_DOWN_K1:
    , r/ w7 B( h' a( F, m
  25.                        printf("K1键按下,使用MDK中自带的RTX调试组件,请务必使用MDK4.74版本进行调试\r\n");& ?$ ]2 b9 Q+ R( p; z% [+ `
  26.                        break;  
    / [; W  D& F& t8 _$ _  d. o
  27.                   8 @1 s* O; `( [+ y; R0 n1 N
  28.                    /*9 u5 O+ y8 y" n- O5 G3 c0 _
  29.                       K2键按下,创建单次定时器,定时时间10个系统时钟节拍, 在定时器回调函数中给任务
    1 o+ O* f6 W) E' O. Z
  30.                       AppTaskMsgPro发信号量同步信号2 O% v2 t) ^# T+ R
  31.                    */8 `. [) ~/ s+ m
  32.                    case KEY_DOWN_K2:  Z" n" u. W# v; u) e7 q
  33.                        printf("K2键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数中给任务  z5 h# X* j' [% f0 S9 g
  34. AppTaskMsgPro发信号量同步信号\r\n");! m) j0 H' J3 s" z/ B
  35.                        /*
    . [0 g+ ?' N( [8 k
  36.                          1. RTX的定时器仅支持单次,不支持周期性执行,如果需要周期执行,需要重复创建
    8 P/ H3 ?' @: m' C+ G0 J
  37.                          2. 定时器回调函数os_tmr_call中仅支持isr_开头的系统函数,os_开头的不支持,此回调函9 }$ T9 V. `5 U: x! a
  38. 数是在滴答定时器中断中执行的。
    . j. i$ c8 c7 p" Q: O
  39.                          3. 回调函数os_tmr_call在文件RTX_Conf_CM.c文件中。- z  Q6 _4 f% M) Q% {, m! e
  40.                        */
    ( q2 B, S8 G1 O% k
  41.                        OneShotTimerID1 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */5 |2 {0 H) m' t( V2 }( Z3 m
  42.                                                       1);  /* 回调函数的参数,可用于区分不同的定时器 */
    5 P" I7 i1 T* N& F; c2 w% g0 D) e
  43.                      
    " i. |1 Z* c; r* d4 a1 d1 i+ u" C- F
  44.                        if (OneShotTimerID1 == NULL)
    6 E# \+ u, V9 p9 Q/ A4 V# ]
  45.                        {/ p( \3 M4 Z/ t  U7 j3 J& l6 l# E
  46.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */! }8 d3 L9 c) |) b0 I0 }+ o! m
  47.                        }
    & Q3 ^  P/ e& o( `
  48.                        break;
    " u  Z- f$ O: _
  49.                       : i0 N' p. j5 n" G! B. g/ X& A3 w
  50.                    case KEY_DOWN_K3:9 v7 I& R& O2 _  i# Y, b. C. O
  51.                        printf("K3键按下,创建单次定时器,10个系统时钟节拍后在定时器回调函数翻转LED1\r\n");
    * z+ i9 ]4 T, Z% k
  52.                        OneShotTimerID2 = os_tmr_create(10,  /* 定时10个系统时钟节拍 */
    6 u/ d. m, `, N: G; h5 @; C
  53.                                                        2);  /* 回调函数的参数,可用于区分不同的定时器 */
    . x! j7 i5 f! N" o
  54.                      
    1 x5 [; {5 i6 }( y! Z8 y
  55.                        if (OneShotTimerID2 == NULL)
    8 v  W  y" q) n. \
  56.                        {
    * C8 D# i, T" _1 O" q" R
  57.                             /* 没有创建成功,用户可以在这里加入创建失败的处理机制 */
    & |, J$ g% I8 x7 |: h& M
  58.                        }  {! g3 M3 q* m# {  `/ }4 L) w
  59.                        break;
    % B9 M% I# i" {+ `1 e# F% t

  60. 3 n* ~6 Y5 @" _3 l0 p, H
  61.                    /* 其他的键值不处理 */# R/ N% b' ~" k
  62.                    default:                    ! ~; ?0 |9 h' G  z2 Y# h, E% u
  63.                        break;8 O/ ?2 e. T3 ^! p/ S9 S7 L
  64.               }1 |# `3 m, h' r% f, u0 k1 o
  65.          }: S; l& L! i1 J) m2 m! j! Q
  66.         ! J7 }/ [2 h# b. O. Q; q* d; N" @
  67.          os_dly_wait(20);
    " ^- ]% F& J- p2 K0 O  `6 R
  68.      }. M$ W6 m' H0 K0 X5 U* P* g
  69. }% B0 r8 a3 o% g( ?1 z* c% f

  70. . |8 C# K3 l' u
  71. /*  W7 e: Z4 A# T4 m; ^) d
  72. *********************************************************************************************************
    * w0 i: D7 p- x1 z/ Z
  73. *    函 数 名: AppTaskLED) f8 P4 _7 _1 S
  74. *    功能说明: LED闪烁。9 }7 I, h9 ^( A! W# ]
  75. *    形    参: 无
    " {& H' v: s( c6 k2 N  v! w
  76. *    返 回 值: 无
    1 n' n$ V" @( R$ b* I3 |. @% p
  77. *   优 先 级: 2
    . ~" F! I  ~8 F( U
  78. *********************************************************************************************************
    2 W" S) f! g, S2 `1 j  P
  79. */
    : _% S/ X0 F" s3 ~2 o
  80. __task void AppTaskLED(void)
    8 p( M1 H5 S" ]0 d# n
  81. {3 B5 l% {4 n1 X0 Y1 q% u
  82.      const uint16_t usFrequency = 200; /* 延迟周期 */( i( X. @/ l" ?: U4 g
  83.    
    ( E. ~: C+ T  w# `, X! o7 K, Q0 ^
  84.      /* 设置延迟周期 */" U  H4 t- M4 ]7 Y0 {1 F& T/ C5 a  C
  85.      os_itv_set(usFrequency);# X$ d3 J+ h# @* @0 A3 t1 C9 `4 i
  86.     5 H( w2 f. F+ t" g4 Y4 r
  87.     while(1): q' i5 P, u6 J+ G6 u, w2 x
  88.     {6 r9 [# j1 {% Q. D4 S, r* H# O
  89.          bsp_LedToggle(2);
    , O' x8 \6 U' W& l3 ^% o; q+ t% k; B
  90.          bsp_LedToggle(3);
    : ~% D( i2 g1 B( z

  91. / b, c6 V7 }. x/ h- i
  92.          /* os_itv_wait是绝对延迟,os_dly_wait是相对延迟。*/0 j% D5 d# T6 f  Y# Z) {
  93.          os_itv_wait();
    5 R! M- L$ m* l7 K7 z: y
  94.     }. k! U7 s- _  A3 n. G
  95. }# B! S, ]2 G. P, X  `2 @- ?) q$ V, D

  96.   h; c6 h  ]; ~% a
  97. /*
    * C6 L0 T% z! ?- ~
  98. *********************************************************************************************************
    2 c  E# ]7 T6 E( _  J( i
  99. *    函 数 名: AppTaskMsgPro# N9 u1 j& H% J- k( S1 v, ~( A
  100. *    功能说明: 消息处理,等待RTX定时器发来的信号量同步信号
      G! d3 E3 {; m0 X
  101. *    形    参: 无
    $ ^- i. k8 M7 g
  102. *    返 回 值: 无, Y- m' B. S( ~
  103. *   优 先 级: 3 8 F% ]  E7 w' ~! k$ X. w
  104. *********************************************************************************************************
    ! P# K. n; A' Y  a' U6 w
  105. */1 C8 n. z0 l, |
  106. __task void AppTaskMsgPro(void)
    , j0 I- h- f6 m, l
  107. {- N' S6 M+ B: A. R1 x, k4 Z8 A* D: ?
  108.      OS_RESULT xResult;
    ( r* T# D! b' \
  109.      const uint16_t usMaxBlockTime = 200; /* 延迟周期 */
    + p) [2 z& X- B+ h# k
  110.    
    : H' A0 o) z! Q, {, Y: f& {
  111.     while(1)
    + L6 x" o7 Z" Y" x. f7 A5 w8 z
  112.     {& g* a' I- v$ h
  113.          xResult = os_sem_wait (&semaphore, usMaxBlockTime);
    ) @2 o! _/ T5 j: Q  r* W6 ]+ Y6 u! }
  114.         
    : m+ A2 F- j. h) F7 J
  115.          switch (xResult)
    * U; t% b7 {% v; t2 {
  116.          {$ o9 _& ]3 W2 C, e4 Y5 q5 ?9 c
  117.               /* 无需等待接受到信号量同步信号 */# N; V  A8 _. r! L  u; v
  118.               case OS_R_OK:8 Y+ X* A; F, f* Y8 v* D: s
  119.                    printf("无需等待接受到信号量同步信号\r\n");
    # A# A1 \' S# P2 X8 L0 w) k$ h
  120.                    break;  
    ; R+ m5 y% U6 @  F

  121. 0 e8 Q  K7 p+ e, M6 u( d- T
  122.               /* 信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号 */4 L: D  k! p- Z- m/ m$ ?
  123.               case OS_R_SEM:
    4 t: e  X6 _" m* y7 P6 r/ x( @; {
  124.                    printf("信号量不可用,usMaxBlockTime等待时间内收到信号量同步信号\r\n");
    6 R1 m, |9 V. G! B  {
  125.                    break;* U/ t0 x. U- V8 c) T4 F$ J  V

  126. 8 ?4 x% X! w" e, V7 g& {
  127.               /* 超时 */2 H$ T+ p" ~2 R& u% m* }3 a
  128.               case OS_R_TMO:
    5 Q$ Z% W1 P) t
  129.                    bsp_LedToggle(4);/ w; W  ]+ u% S3 `3 v* E3 m4 X
  130.                    break;/ I7 q- z( U0 `- M
  131.             
    , V8 q" N: {4 r( o% \, i+ U
  132.               /* 其他值不处理 */
    5 A: S" k% }9 ^' o  ^8 E
  133.               default:                    3 o9 Q! n$ C8 E, C! K  S0 r
  134.                    break;
    + ^% f+ H+ Q) O: v
  135.          }   # r1 c/ l& U. h4 r/ B
  136.     }
    9 z) A- n. M3 c$ l- J9 K
  137. }  ?& n0 C; o  N/ c- X8 J

  138. 6 l8 t: |+ O1 X4 X! T- S- w4 O
  139. /*4 j4 D. _7 {' ^3 u$ L) U2 S
  140. *********************************************************************************************************& d! \4 f% N' H; T' \4 b: j( X. p
  141. *    函 数 名: AppTaskStart2 K; c6 J) c4 R
  142. *    功能说明: 启动任务,也就是最高优先级任务。这里实现按键扫描。
    , v8 ~. y: J" N. t% |) T9 I; r
  143. *    形    参: 无
    7 {- d& X* K; B0 f+ b
  144. *    返 回 值: 无
    - }' M* }/ q6 A: |* ?, e- W
  145. *   优 先 级: 4
    " E  I4 k2 @+ v9 v/ B7 F) T
  146. ********************************************************************************************************** _. m) y3 o5 I1 {7 b$ w* K' D' r# ?
  147. */
    # v0 @& j: h1 u3 ]
  148. __task void AppTaskStart(void)
    6 @$ b# _! i! X
  149. {) m4 }& Q1 [4 ?  ~/ z
  150.      /* 创建任务 */' p3 ?" r& F4 P! _! b
  151.      AppTaskCreate();
    * r5 B+ I) L. {8 `* U
  152.     3 ^2 s" T2 D. b
  153.      /* 创建任务通信机制 */2 K/ I: K7 [2 @+ y7 v0 l
  154.      AppObjCreate();1 c- h: U6 ?$ f
  155.    
    0 h9 `+ N, [9 r# O
  156.     while(1)( e  U& Q  C) A' [- P
  157.     {9 {$ g6 K; z9 k  A7 k, p6 H* y9 I- ]
  158.          /* 按键扫描 */
    7 w; t2 ]3 Y+ {/ f
  159.          bsp_KeyScan();
    . v. n0 P4 |- p
  160.         os_dly_wait(10);
    " P1 r3 ^: w9 N
  161.     }
    7 \# P$ [4 c0 L, e! t
  162. }
复制代码
) q5 b, J4 Q9 z" j' Z! S: J
定时器回调函数的实现,在文件RTX_Conf_CM.c:
  1. /*--------------------------- os_tmr_call -----------------------------------*/. N! V# n  a# e. B. R4 R+ c
  2. #include "bsp.h"! q; U  M$ [! Z" N" Q: w
  3. extern OS_SEM semaphore;
    7 x- C. p# |4 G5 I9 I- I
  4. void os_tmr_call (U16 info) {6 j2 f! W. b1 T% |0 |/ U
  5.   /* This function is called when the user timer has expired. Parameter   */
    ! I% R$ P0 N+ L( l3 J* N
  6.   /* 'info' holds the value, defined when the timer was created.          */; B% G# M# ^  t! y! ~8 Y
  7. 7 m/ r* \$ Y& t
  8.   /* HERE: include optional user code to be executed on timeout. */3 i+ S2 B1 N6 @9 G
  9.   /* 定时器回调函数中仅支持isr_开头的系统函数,os_开头的不支持,此回调函数是在
    & ~# L4 f* W1 [" e3 ]; O8 w
  10.      滴答定时器中断中执行的。
    , o! ?, Q3 N9 n4 ^
  11.   */
    8 F0 A- m& [. Y- G+ I( y) c% k
  12.   switch(info)
    , Q6 E* u; b8 v; @' x
  13.   {1 k7 ~4 S8 p6 j% E# X
  14.      case 1:          /* 参数为1 */
    + Z; @- R& K0 F2 z
  15.       isr_sem_send (&semaphore);     
    % q/ S) t+ O9 k
  16.       break;
    5 Z2 d  h+ u+ t+ T
  17.     ' b, f2 P* H; }' P0 ^7 W/ K; T% v
  18.      case 2:          /* 参数为2 */
    3 y5 n/ v1 v8 {: r" m3 Q
  19.        bsp_LedToggle(1);   $ g8 J7 o0 R( }. p
  20.       break;+ `: t4 S8 |* Z6 @4 s: Q/ m
  21.   }
    8 y7 G, U/ H. j
  22. }
复制代码
! J' i7 V& D/ k& o
" A* `. `$ N6 `; n; H7 i+ X
baiyongbin2009 回答时间:2016-2-2 17:33:35
17.4 总结
    本章节主要为大家讲解了软件定时器,对于初学者来说,比较容易掌握。
/ X8 n0 B) ?- B, @$ H
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版