15天入门-第十四次-定时器的使用

发表在 Kernel2018-5-31 17:00 [复制链接] 2 1039

本次课程主要讲软件定时器,主要包括:
" Y$ I) g5 \+ P$ a1 f0 S! X
8 a! i$ U7 D' V& t* ]4 x9 N! j1、使用软件定时器需要的配置宏, f$ f$ p% d+ X3 ?( N
#define RT_USING_SOFT_TIMER- m. O$ b& [' [5 J2 r1 j# _

1 u7 k6 }& K! }% Y2 k2、例程源码解读及软件定时器相关操作介绍:0 T3 }0 S0 W( j, g, Q
) I5 t/ [; D, m: u6 x
需要设置定时周期   启动 中断处理函数
" H; l" `) C6 }& jstatic rt_timer_t timer2;$ N5 X9 |% U. Q# ^
初始化/创建   ' s' l3 q8 B, D5 ^
    /* 创建定时器1 */* |: m( x+ D1 `  A2 Z( J

2 h' O& T1 W9 m" `. Z9 `  G- y. F- Mtimer1 = rt_timer_create("timer1", /* 定时器名字是 timer1 */9 K5 Q* b" W4 }0 q; J4 V
  5 }4 k/ o6 q: @! o
                           timeout1, /* 超时时回调的处理函数 */
9 |3 z! }8 k& L! \/ T) [$ |; X4 k  
  e) V0 v5 i7 o4 y# B                           RT_NULL, /* 超时函数的入口参数 */6 E2 q, p% v3 Q  Y/ r& d& ?

6 I0 D) B9 R% K9 d                            10, /* 定时长度,以OS Tick为单位,即10个OS Tick */
9 P- q2 \& o4 u  x( v 1 K) R' `" J$ M
                            RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */
# k2 W: _* G0 Dvoid rt_timer_init(rt_timer_t  timer,8 H& }" ]- J% M+ y  N
                   const char *name,+ `& B6 Q& s) p7 Y3 `; v
                   void (*timeout)(void *parameter),
% D+ X" `( j5 `+ M% ?! U# o                   void       *parameter,2 U8 s3 J0 y/ g5 H' e  H$ ?! B
                   rt_tick_t   time,4 U% i% }& p' x1 |( S, `
                   rt_uint8_t  flag)3 i' Q6 T( a  d. Y- h2 E7 {; L; o
启动/停止    超时处理函数
+ @7 \9 P  d# O2 J6 I3 t5 p1 f /* 启动定时器 */
$ V0 d3 t: i8 K; V  5 ~9 T. Z# U. D" f7 s
  if (timer1 != RT_NULL) rt_timer_start(timer1);
3 N) d- O/ V' e, r /*停止定时器*/
( X. `; \6 K2 F% f( H" G- K0 ?  rt_err_t rt_timer_stop(rt_timer_t timer)/ [2 y# Z: u, Y3 a. ?
控制3 ]/ o8 A9 _1 _( d: D
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)% V: d1 l" [. w& R- b$ K
控制命令:) `% ^  ^( n# P1 ~% f! t  T
#define RT_TIMER_CTRL_SET_TIME          0x0             /**< set timer control command */9 c$ }4 ~7 u, G
#define RT_TIMER_CTRL_GET_TIME          0x1             /**< get timer control command */+ \; \+ ^4 W" c- ~# H
#define RT_TIMER_CTRL_SET_ONESHOT       0x2             /**< change timer to one shot */3 S" X3 X; k$ Y3 ^) m" P
#define RT_TIMER_CTRL_SET_PERIODIC      0x3             /**< change timer to periodic */
& B' u4 a( ]) c. ` 脱离/删除
) D/ B! Q; ~" v0 r; v, srt_err_t rt_timer_detach(rt_timer_t timer), b) j! F9 W) l9 F  ~& h8 \( Z, ^7 q
rt_err_t rt_timer_delete(rt_timer_t timer)1 e/ G6 w2 l5 X9 a+ Y+ h& P
0 X5 D4 ^3 D- G- H1 A

7 b) Y5 ~4 k6 f$ `4 U3、软件定时器使用的两个注意点:
' d( x5 x" x+ f9 N: @, l: w8 C
# A5 j5 z+ ]9 p& }, Z(1)定时时间都是系统滴答的整数倍。精度,最小为1个滴答时钟;
( ?3 U. h8 @3 G) ^" V; K) u(2)超时处理函数, 尽可能短一点。
! G2 [$ z: T" x. s$ \& o1 L. k 创建定时器时 硬件定时器  软件定时器FLAG  区别:超时函数执行上下文环境不一样。
# S7 ?, o/ P4 s; {. P8 n( ]& BRT_TIMER_FLAG_SOFT_TIMER    在定时器上下文环境中执行,软件TIMER的任务中执行。; ?4 h- ]. u5 o) G+ z& O# S! }
                                 不是很精确,但可以调用等待资源的操作8 K2 E. P9 D3 e9 X% z6 f
RT_TIMER_FLAG_HARD_TIMER, v9 ^6 J# r- i3 e
HARD FLAG     system -- tick 在系统滴答时钟中断中执行  保证定时的精度度。/ `2 _+ @2 Z2 |) u1 ]2 g
不要尝试获取IPC的操作,
) ?! y2 w; O# Y4 I# ?3 P$ H1 j1 E用处比较多,比如扫描按键等。
- I8 O8 H" A# z4 o! a0 p作业:9 w9 i8 i, L) L8 W" \
1.使用控制函数修改定时器的超时时间。
" V* g1 y, X% L3 Z. C1 X
  1. /*5 l$ }1 A! D4 v; ^1 l4 @# U$ v$ N
  2. * 程序清单:定时器例程
    . _8 X2 G, g1 ^
  3. *
    / g, `) \/ `. t2 y' T
  4. * 这个例程会创建两个动态定时器对象,一个是单次定时,一个是周期性的定时3 f) b$ |* O, v- n$ A' I- a& Q2 v
  5. * */
    ! L: T$ a% ]3 }8 H" c) u+ g1 {
  6. #include <rtthread.h>4 [) ]2 X  r4 W8 }( d  e0 B
  7. 0 B: D4 u: j. H7 `+ S9 q3 P
  8. /* 定时器的控制块 */
      Z5 f' E' b$ H) x& ?& M! m$ j; ]
  9. static rt_timer_t timer1;
    6 ~8 j3 F. D" q& c2 U" ^, h$ z; x
  10. static rt_timer_t timer2;* @% Y- D7 X7 i( c+ _
  11. static int cnt = 0;8 ~9 N0 ^+ M* x' r9 T  u2 R1 P
  12. 6 D0 J  I8 e% d, j& ~8 Z, k9 ?2 e, P
  13. /* 定时器1超时函数 */
    ( x4 n( E9 W( F0 j
  14. static void timeout1(void *parameter)' t, J! Q# R2 r  |- p/ Z
  15. {; z* u% A  j7 H2 I' I2 O
  16.     rt_tick_t timeout = 30;//300
    * c6 r5 r) \1 [' f' {

  17. , Y/ u& {) K: N4 O" u+ E- v
  18.     rt_kprintf("periodic timer is timeout\n");
    3 w" w# z: o, @$ n( Q- Q

  19. / U" X# K% w3 L' q' [2 k
  20.     /* 运行10次 */
    1 h6 L8 g7 r9 Z/ v' ?
  21.     if (cnt++ >= 10)( c7 s, q9 R" ?
  22.     {' w; v5 b! m* W9 U, Q
  23.        // rt_timer_control(timer1, RT_TIMER_CTRL_SET_ONESHOT, (void *)&timeout);
    % c9 t% w$ n" C
  24.                          rt_timer_control(timer1, RT_TIMER_CTRL_SET_PERIODIC, (void *)&timeout);! w" m7 c; ^, t0 }* F8 c# F# Q
  25.     }8 T0 |$ F" r8 d" D* p
  26. }
    0 I0 @9 [9 ]$ E; l4 ~# W1 [% b
  27. , m7 O) |; S" ^% }- o2 E6 g$ x. A
  28. /* 定时器2超时函数 */: A, l1 l: n, W& M7 o, B7 n
  29. static void timeout2(void *parameter)7 k' B/ a# V! o& V$ d
  30. {
    ! J3 a8 v3 A. L& T2 ?8 Q0 i6 U
  31.     rt_kprintf("one shot timer is timeout\n");3 C& E) C6 E( _" q
  32. }# P  T% D: M0 {" c& ?
  33. + O) Z  t+ S8 w# e5 O# T! e
  34. int timer_sample_init(void)
    2 G. t* ~: X* v
  35. {& O$ K" G3 E8 G6 {
  36.     /* 创建定时器1 */
    6 t# u) M% D9 \; Y) y7 j- D1 J
  37.     timer1 = rt_timer_create("timer1", /* 定时器名字是 timer1 */( \5 z5 a$ T- U- T
  38.                              timeout1, /* 超时时回调的处理函数 */, ~& A# `' u3 E/ P! P1 q. {5 g
  39.                              RT_NULL, /* 超时函数的入口参数 */0 X9 D  a0 d- M! X
  40.                              10, /* 定时长度,以OS Tick为单位,即10个OS Tick */% K! E0 g) W7 V* m" Q7 o  O
  41.                              RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */5 l- E% l6 X8 I
  42. - q' T- f8 p% d# j
  43.     /* 启动定时器 */; \) W8 f+ ~  M# g* P
  44.     if (timer1 != RT_NULL) rt_timer_start(timer1);
    3 ?0 x% l: j6 E3 \8 A6 m( o0 C
  45. ) ~' v" z' p) v# @7 |1 _  m
  46.     /* 创建定时器2 */
    / o  T, p9 j' r+ i  b1 U" [1 F2 E
  47.     timer2 = rt_timer_create("timer2", /* 定时器名字是 timer2 */
    / Y+ B  Z5 L" k, H7 Z. _( W
  48.                              timeout2, /* 超时时回调的处理函数 */" `5 o; _5 }7 \. j: q
  49.                              RT_NULL, /* 超时函数的入口参数 */8 I! b- r7 k' I9 {
  50.                              30, /* 定时长度为30个OS Tick */
    ' O% m. A. r/ W" j
  51.                              RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */
    & \- O9 A+ M, F5 N4 G

  52. 3 v: [- `+ v/ k: F7 F  u$ g
  53.     /* 启动定时器 */6 T6 [) d1 k- b  I1 m4 U% t) d6 _4 Y
  54.     if (timer2 != RT_NULL) rt_timer_start(timer2);
    # u* z1 f( k6 L
  55.     return 0;
    ; q; i. R! [/ H5 V! _4 [
  56. }* p! G) M! a# ^! z& v
  57. /* 如果设置了RT_SAMPLES_AUTORUN,则加入到初始化线程中自动运行 */
    * D- I) x. O1 l1 C# `# m1 s
  58. #if defined (RT_SAMPLES_AUTORUN) && defined(RT_USING_COMPONENTS_INIT)
    # k8 T& Y- F" X/ E$ @
  59.     INIT_APP_EXPORT(timer_sample_init);
    " |( [. m* n2 A" i; E" T
  60. #endif2 N- |5 W7 z3 i8 S% `
  61. /* 导出到 msh 命令列表中 */
    - p: `. H3 _+ |8 |8 G9 C# P; G- Q5 |
  62. MSH_CMD_EXPORT(timer_sample_init, timer sample);
    6 T8 J  v  }  A# H; Y1 @) k

  63. 4 A% T. T( g5 {
复制代码

/ H1 _1 R" d9 z( j" y
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-1-8 15:20:11 | 显示全部楼层
设置回掉函数参数的话,  timer2 = rt_timer_create("timer2", /* 定时器名字是 timer2 */
2 Q) P; m/ `6 v' A$ T/ I8 W1 s                             timeout2, /* 超时时回调的处理函数 */3 m  m9 p8 g& z
                             RT_NULL, /* 超时函数的入口参数 */+ L, f7 p) x6 ]: ^3 K, ?) z
                             30, /* 定时长度为30个OS Tick */
7 ?7 B- L, P9 l0 A/ k                             RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */
- _3 b) g7 i. u; c. G) j入口参数不能是局部变量。
使用道具 举报 回复
发表于 2019-1-10 13:51:40 | 显示全部楼层
嗯...格式有一点点乱哦
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区  

© 2013-2017 上海睿赛德电子科技有限公司 沪ICP备13014002号-1

Powered by RT-Thread

快速回复 返回顶部 返回列表