定时器管理接口

定时器管理系统初始化

初始化定时器管理系统,可以通过下面的函数接口完成:

  1. void rt_system_timer_init(void);

函数参数

函数返回

如果需要使用SOFT_TIMER,则系统初始化时,应该调用下面这个函数接口:

  1. void rt_system_timer_thread_init(void);

函数参数

函数返回

创建定时器

当动态创建一个定时器时,可使用下面的函数接口:

  1. rt_timer_t rt_timer_create(const char* name,
  2. void (*timeout)(void* parameter), void* parameter,
  3. rt_tick_t time, rt_uint8_t flag);

调用该函数接口后,内核首先从动态内存堆中分配一个定时器控制块,然后对该控制块进行基本的初始化。

函数参数


  1. 参数 描述

  1. const char* name 定时器的名称;

void (timeout)(void parameter) 定时器超时函数指针(当定时器超时时,系统会调用这个函数);

  1. void* parameter 定时器超时函数的入口参数(当定时器超时时,调用超时回调函数
  2.  
  3. 会把这个参数做为入口参数传递给超时函数);
  4.  
  5. rt_tick_t time 定时器的超时时间,单位是系统节拍;
  6.  
  7. rt_uint8_t flag 定时器创建时的参数,支持的值包括(可以用“或”关系取多个值);

include/rtdef.h中定义了一些定时器相关的宏,如下。

  1. #define RT_TIMER_FLAG_DEACTIVATED 0x0 /* 定时器为非激活态 */
  2. #define RT_TIMER_FLAG_ACTIVATED 0x1 /* 定时器为激活状态 */
  3. #define RT_TIMER_FLAG_ONE_SHOT 0x0 /* 单次定时 */
  4. #define RT_TIMER_FLAG_PERIODIC 0x2 /* 周期定时 */
  5. #define RT_TIMER_FLAG_HARD_TIMER 0x0 /* 硬件定时器 */
  6. #define RT_TIMER_FLAG_SOFT_TIMER 0x4 /* 软件定时器 */

当指定的flag为RT_IMER_FLAG_HARD_TIMER时,如果定时器超时,定时器的回调函数将在时钟中断的服务例程上下文中被调用;当指定的flag为RT_TIMER_FLAG_SOFT_TIMER时,如果定时器超时,定时器的回调函数将在系统时钟timer线程的上下文中被调用。

函数返回

如果定时器创建成功,则返回定时器的句柄;如果创建失败,会返回RT_NULL(通常会由于系统内存不够用而返回RT_NULL)。

创建定时器的例子如下所示:

  1. /*
  2. * 程序清单:动态定时器例程
  3. *
  4. * 这个例程会创建两个动态定时器对象,一个是单次定时,一个是周期性的定时
  5. */
  6. #include <rtthread.h>
  7.  
  8. /* 定时器的控制块 */
  9. static rt_timer_t timer1;
  10. static rt_timer_t timer2;
  11.  
  12. /* 定时器1超时函数 */
  13. static void timeout1(void* parameter)
  14. {
  15. rt_kprintf("periodic timer is timeout\n");
  16. }
  17.  
  18. /* 定时器2超时函数 */
  19. static void timeout2(void* parameter)
  20. {
  21. rt_kprintf("one shot timer is timeout\n");
  22. }
  23.  
  24. int rt_application_init(void)
  25. {
  26. /* 创建定时器1 */
  27. timer1 = rt_timer_create("timer1", /* 定时器名字是 timer1 */
  28. timeout1, /* 超时时回调的处理函数 */
  29. RT_NULL, /* 超时函数的入口参数 */
  30. 10, /* 定时长度,以OS Tick为单位,即10个OS Tick */
  31. RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */
  32. /* 启动定时器 */
  33. if (timer1 != RT_NULL) rt_timer_start(timer1);
  34.  
  35. /* 创建定时器2 */
  36. timer2 = rt_timer_create("timer2", /* 定时器名字是 timer2 */
  37. timeout2, /* 超时时回调的处理函数 */
  38. RT_NULL, /* 超时函数的入口参数 */
  39. 30, /* 定时长度为30个OS Tick */
  40. RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */
  41.  
  42. /* 启动定时器 */
  43. if (timer2 != RT_NULL) rt_timer_start(timer2);
  44.  
  45. return 0;
  46. }

删除定时器

系统不再使用特定定时器时,可使用下面的函数接口:

  1. rt_err_t rt_timer_delete(rt_timer_t timer);

调用这个函数接口后,系统会把这个定时器从rt_timer_list链表中删除,然后释放相应的定时器控制块占有的内存。

函数参数


  1. 参数 描述

  1. rt_timer_t timer 定时器句柄,指向要删除的定时器。

函数返回

返回RT_EOK (如果参数timer句柄是一个RT_NULL,将会导致一个ASSERT断言)

删除定时器的例子请参考例9-1中删除定时器的代码。

初始化定时器

当选择静态创建定时器时,可利用rt_timer_init接口来初始化该定时器,函数接口如下:

  1. void rt_timer_init(rt_timer_t timer,
  2. const char* name, void (*timeout)(void* parameter), void* parameter,
  3. rt_tick_t time, rt_uint8_t flag);

使用该函数接口时会初始化相应的定时器控制块,初始化相应的定时器名称,定时器超时函数等等。

函数参数


  1. 参数 描述

  1. rt_timer_t timer 定时器句柄,指向要初始化的定时器控制块;
  2.  
  3. const char* name 定时器的名称;

void (timeout)(void parameter) 定时器超时函数指针(当定时器超时时,系统会调用这个函数);

  1. void* parameter 定时器超时函数的入口参数(当定时器超时时,调用超时回调函数
  2. 会把这个参数做为入口参数传递给超时函数);
  3.  
  4. rt_tick_t time 定时器的超时时间,单位是系统节拍;
  5.  
  6. rt_uint8_t flag 定时器创建时的参数,支持的值包括(可以用“或”关系取多个值);

  1. #define RT_TIMER_FLAG_ONE_SHOT 0x0 /* 单次定时 */
  2. #define RT_TIMER_FLAG_PERIODIC 0x2 /* 周期定时 */
  3. #define RT_TIMER_FLAG_HARD_TIMER 0x0 /* 硬件定时器 */
  4. #define RT_TIMER_FLAG_SOFT_TIMER 0x4 /* 软件定时器 */

当指定的flag为RT_IMER_FLAG_HARD_TIMER时,如果定时器超时,定时器的回调函数将在时钟中断的服务例程上下文中被调用;当指定的flag为RT_TIMER_FLAG_SOFT_TIMER时,如果定时器超时,定时器的回调函数将在系统时钟timer线程的上下文中被调用。

初始化定时器的例子如下代码所示:

  1. /*
  2. * 程序清单:静态定时器例程
  3. *
  4. * 这个程序会初始化2个静态定时器,一个是单次定时,一个是周期性的定时
  5. */
  6. #include <rtthread.h>
  7.  
  8. /* 定时器的控制块 */
  9. static struct rt_timer timer1;
  10. static struct rt_timer timer2;
  11.  
  12. /* 定时器1超时函数 */
  13. static void timeout1(void* parameter)
  14. {
  15. rt_kprintf("periodic timer is timeout\n");
  16. }
  17.  
  18. /* 定时器2超时函数 */
  19. static void timeout2(void* parameter)
  20. {
  21. rt_kprintf("one shot timer is timeout\n");
  22. }
  23.  
  24. int rt_application_init(void)
  25. {
  26. /* 初始化定时器 */
  27. rt_timer_init(&timer1, "timer1", /* 定时器名字是 timer1 */
  28. timeout1, /* 超时时回调的处理函数 */
  29. RT_NULL, /* 超时函数的入口参数 */
  30. 10, /* 定时长度,以OS Tick为单位,即10个OS Tick */
  31. RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */
  32. rt_timer_init(&timer2, "timer2", /* 定时器名字是 timer2 */
  33. timeout2, /* 超时时回调的处理函数 */
  34. RT_NULL, /* 超时函数的入口参数 */
  35. 30, /* 定时长度为30个OS Tick */
  36. RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */
  37.  
  38. /* 启动定时器 */
  39. rt_timer_start(&timer1);
  40. rt_timer_start(&timer2);
  41.  
  42. return 0;
  43. }

脱离定时器

当一个静态定时器不需要再使用时,可以使用下面的函数接口:

  1. rt_err_t rt_timer_detach(rt_timer_t timer);

脱离定时器时,系统会把定时器对象从系统容器的定时器链表中删除,但是定时器对象所占有的内存不会被释放。

函数参数


  1. 参数 描述

  1. rt_timer_t timer 定时器句柄,指向要脱离的定时器控制块。

函数返回

返回RT_EOK。

脱离定时器的例子可参考9-2例程代码中的脱离部分。

启动定时器

当定时器被创建或者初始化以后,并不会被立即启动,必须在调用启动定时器函数接口后,才开始工作,启动定时器函数接口如下:

  1. rt_err_t rt_timer_start(rt_timer_t timer);

调用定时器启动函数接口后,定时器的状态将更改为激活状态(RT_TIMER_FLAG_ACTIVATED),并按照超时顺序插入到rt_timer_list队列链表中。

函数参数


  1. 参数 描述

  1. rt_timer_t timer 定时器句柄,指向要启动的定时器控制块。

函数返回

如果timer已经处于激活状态,则返回-RT_ERROR;否则返回RT_EOK。

启动定时器的例子请参考9-1例程代码中的定时器代码。

停止定时器

启动定时器以后,若想使它停止,可以使用下面的函数接口:

  1. rt_err_t rt_timer_stop(rt_timer_t timer);

调用定时器停止函数接口后,定时器状态将更改为停止状态,并从rt_timer_list链表中脱离出来不参与定时器超时检查。当一个(周期性)定时器超时时,也可以调用这个函数接口停止这个(周期性)定时器本身。

函数参数


  1. 参数 描述

  1. rt_timer_t timer 定时器句柄,指向要停止的定时器控制块。

函数返回

如果timer已经处于停止状态,返回-RT_ERROR;否则返回RT_EOK。

控制定时器

除了上述提供的一些编程接口,RT_thread也额外提供了定时器控制函数接口,以获取或设置更多定时器的信息。控制定时器函数接口如下:

  1. rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void* arg);

控制定时器函数接口可根据命令类型参数,来查看或改变定时器的设置。

函数参数


  1. 参数 描述

  1. rt_timer_t timer 定时器句柄,指向要进行控制的定时器控制块;
  2.  
  3. rt_uint8_t cmd 用于控制定时器的命令,当前支持四个命令接口,分别是设置
  4. 定时时间,查看定时时间,设置单次触发,设置周期触发;
  5.  
  6. void* arg command相对应的控制命令参数;

  1. #define RT_TIMER_CTRL_SET_TIME 0x0 /* 设置定时器超时时间 */
  2. #define RT_TIMER_CTRL_GET_TIME 0x1 /* 获得定时器超时时间 */
  3. #define RT_TIMER_CTRL_SET_ONESHOT 0x2 /* 设置定时器为单一超时型 */
  4. #define RT_TIMER_CTRL_SET_PERIODIC 0x3 /* 设置定时器为周期型定时器 */

函数返回

函数返回RT_EOK

使用定时器控制接口的代码如下所示:

  1. /*
  2. * 程序清单:定时器控制接口示例
  3. *
  4. * 这个例程会创建1个动态周期型定时器对象,然后控制它进行更改定时器的时间长度。
  5. */
  6. #include <rtthread.h>
  7.  
  8. /* 定时器的控制块 */
  9. static rt_timer_t timer1;
  10. static rt_uint8_t count;
  11.  
  12. /* 定时器超时函数 */
  13. static void timeout1(void* parameter)
  14. {
  15. rt_kprintf("periodic timer is timeout\n");
  16.  
  17. count ++;
  18. /* 当超过8次时,更改定时器的超时长度 */
  19. if (count >= 8)
  20. {
  21. int timeout_value = 50;
  22. /* 控制定时器更改定时器超时时间长度 */
  23. rt_timer_control(timer1, RT_TIMER_CTRL_SET_TIME, (void*)&timeout_value);
  24. count = 0;
  25. }
  26. }
  27.  
  28. int rt_application_init(void)
  29. {
  30. /* 创建定时器1 */
  31. timer1 = rt_timer_create("timer1", /* 定时器名字是 timer1 */
  32. timeout1, /* 超时时回调的处理函数 */
  33. RT_NULL, /* 超时函数的入口参数 */
  34. 10, /* 定时长度,以OS Tick为单位,即10个OS Tick */
  35. RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */
  36. /* 启动定时器 */
  37. if (timer1 != RT_NULL)
  38. rt_timer_start(timer1);
  39.  
  40. return 0;
  41. }