1、定时器
系统定时器(timer)分为两种,一种是硬件定时器,一种是软件定时器。
- 硬件定时器:它会产生固定的时钟节拍,作为操作系统的时钟基准,其数量是受硬件模块数量的限制的。
- 软件定时器:通过软件模拟出来的定时器,在精度方面比硬件定时器差一些;它的优点在于只要系统资源足够,可以由一个硬件定时器模拟出成千上万个软件定时器。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。所以,一个好的软件定时器实现要求有较高的精度、较小的处理器开销,且占用较少的存储器资源。
本节要讲的就是软件定时器的概念。每个软件定时器都保存着自己的到期时间即时间超时处理函数。软件定时器管理模块会需要扫描所有的软件定时器设定,每个timer到期之后呼叫其预设的时间超时处理函数。
定时器按照是否重复可以分为一次性timer和周期性timer 两种。
2、AliOS Things Timer模块
AliOS Things操作系统对用户提供定时接口的是Timer模块。Timer模块屏蔽了硬件定时器的实现差异,它基于Tick作为最小的时间调度单元来推动自己时间轴的运行,因此 Tick的时间长度也就是Timer模块的最小定时精度。
Timer模块提供的接口包括Timer的创建、删除、启动以及单次或周期定时器。
Timer模块在操作系统默认加载的模块指引,操作系统启动的时候会自动启动。
2.1、Timer API列表
API名称
扫描二维码关注公众号,回复:
12808124 查看本文章
|
功能 |
aos_timer_new |
创建软件定时器 |
aos_timer_new_ext |
创建软件定时器 |
aos_timer_start |
启动软件定时器 |
aos_timer_stop |
停止软件定时器 |
aos_timer_change |
修改软件定时器的定时参数 |
aos_timer_free |
删除软件定时器 |
2.1.1、aos_timer_new
创建一个软件定时器,创建后自动运行。
- 函数原型及参数说明
int aos_timer_new(aos_timer_t *timer,void (*fn)(void *, void *),void *arg, int ms, int repeat);
API名称 |
功能 |
timer |
软件定时器句柄 |
fn |
定时到期处理函数 |
arg |
定时到期处理函数被呼叫时需要Timer模块传递的参数 |
ms |
定时器超时时间(单位ms),即间隔多少时间之后执行fn |
repeat |
周期定时或单次定时(1:周期,0:单次) |
- 返回值
0表示成功,其他值表示失败。具体的返回值定义请参考k_err.h中kstat_t的定义。
2.1.2、aos_timer_new_ext
创建一个软件定时器,可通过入参决定创建后是否自动运行。
- 函数原型及参数说明
int aos_timer_new_ext(aos_timer_t *timer, void (*fn)(void *, void *),void *arg, int ms, int repeat, unsigned char auto_run);
API名称 |
功能 |
timer |
软件定时器句柄 |
fn |
定时到期处理函数 |
arg |
定时到期处理函数被呼叫时需要Timer模块传递的参数 |
ms |
定时器超时时间(单位ms),即间隔多少时间之后执行fn |
repeat |
周期定时或单次定时(1:周期,0:单次) |
auto_run |
1表示自动运行,0表示不自动运行,需要手动调用aos_timer_start才能启动 |
- 返回值
0表示成功,其他值表示失败。具体的返回值定义请参考k_err.h中kstat_t的定义。
2.1.3、aos_timer_start
启动软件定时器
- 函数原型及参数说明
int aos_timer_start(aos_timer_t *timer);
API名称 |
功能 |
timer |
软件定时器句柄 |
- 返回值
0表示成功,其他值表示失败。具体的返回值定义请参考k_err.h中kstat_t的定义。
2.1.4、aos_timer_change
修改软件定时器的定时参数
- 函数原型及参数说明
int aos_timer_change(aos_timer_t *timer, int ms);
API名称 |
功能 |
timer |
软件定时器句柄 |
ms |
新的定时器超时时间(单位ms),即间隔多少时间执行定时器到期处理函数 |
- 返回值
0表示成功,其他值表示失败。具体的返回值定义请参考k_err.h中kstat_t的定义。
2.1.5、aos_timer_stop
停止软件定时器。
- 函数原型及参数说明
int aos_timer_stop(aos_timer_t *timer);
API名称 |
功能 |
timer |
软件定时器句柄 |
- 返回值
0表示成功,其他值表示失败。具体的返回值见本文档返回参数定义小节。
2.1.6、aos_timer_free
删除软件定时器。删除定时器前需调用aos_timer_stop停止定时器。
- 函数原型及参数说明
void aos_timer_free(aos_timer_t *timer);
API名称 |
功能 |
timer |
软件定时器句柄 |
- 返回值
无
3、Timer使用案例
本案例中通过创建“单词自动执行定时器”,“不自动执行周期性定时器”以及“自动执行周期性定时器”为例对AOS Timer API进行说明
3.1、需要包含的头文件
#include <aos/kernel.h>
3.2、创建自动执行的单次定时器
#include "aos/kernel.h"
aos_timer_t g_single_timer;
static void g_single_timer_handler(void *arg1, void* arg2)
{
printf("enter %s\r\n", __func__);
return;
}
/**
* set up a timer with timeout value of period and set timer's handler to g_single_timer_handler
* @param period - timer timeout value, in unit of ms
*
* @return 0 for success; negative no. for failure
*/
int single_timer_example(int period) {
int ret = -1;
if (period <= 0) {
printf("invalid period:%d\r\n", period);
return -1;
}
/*setup a timer with timeout value set to period ms and disable autoload function */
ret = aos_timer_new_ext(&g_single_timer, g_single_timer_handler, NULL, period, 0, 0);
if (ret != 0) {
printf("timer create failed\r\n");
return 2;
}
/* start the timer */
aos_timer_start(&g_single_timer);
/* sleep for (period * 2) ms */
usleep (period * 5 * 1000);
/* stop the timer again */
aos_timer_stop(&g_single_timer);
/* free the timer's resource */
aos_timer_free(&g_single_timer);
return 0;
}
3.3、创建自动运行周期性定时器
aos_timer_t g_repeat_autoload_timer;
static void repeat_autoload_timer_handler(void *arg1, void* arg2)
{
printf("enter %s\r\n", __func__);
return;
}
/**
* set up an auto reload timer with timeout value of period and set timer's handler to repeat_autoload_timer_handler
* @param period - timer timeout value, in unit of ms
*
* @return 0 for success; negative no. for failure
*/
int repeat_autoload_timer_example(int period) {
int ret = -1;
if (period <= 0) {
printf("invalid period:%d\r\n", period);
return -1;
}
/*setup a timer with timeout value set to period ms and enable autoload function */
ret = aos_timer_new(&g_repeat_autoload_timer, repeat_autoload_timer_handler, NULL, period, 1);
if (ret != 0) {
printf("timer create failed\r\n");
return 2;
}
/* sleep for (period * 2) ms */
usleep (period * 5 * 1000);
/* stop the timer again */
aos_timer_stop(&g_repeat_autoload_timer);
/* free the timer's resource */
aos_timer_free(&g_repeat_autoload_timer);
return 0;
}
3.4、创建不自动运行周期性定时器
aos_timer_t g_repeat_non_autoload_timer;
static void repeat_non_autoload_timer_handler(void *arg1, void* arg2)
{
printf("enter %s\r\n", __func__);
return;
}
/**
* set up an repeat timer with timeout value of period and set timer's handler to repeat_non_autoload_timer_handler
* @param period - timer timeout value, in unit of ms
*
* @return 0 for success; negative no. for failure
*/
int repeat_timer_example(int period) {
int ret = -1;
if (period <= 0) {
printf("invalid period:%d\r\n", period);
return -1;
}
/*setup a timer with timeout value set to period ms and enable autoload function */
ret = aos_timer_new_ext(&g_repeat_non_autoload_timer, repeat_non_autoload_timer_handler, NULL, period, 1, 0);
if (ret != 0) {
printf("timer create failed\r\n");
return 2;
}
aos_timer_start(&g_repeat_non_autoload_timer);
/* sleep for (period * 2) ms */
usleep (period * 5 * 1000);
/* stop the timer again */
aos_timer_stop(&g_repeat_non_autoload_timer);
/* free the timer's resource */
aos_timer_free(&g_repeat_non_autoload_timer);
return 0;
}
3.5、Timer案例测试方法
我们为Timer的测试案例添加几个CLI的测试指令,其中:
- stimer指令:用来进行“单次定时器”的测试
- rtimer指令:用来创建“不自动执行的周期性定时器”的测试
- srtimer指令:用来创建“自动执行的周期性定时器”的测试
#include <aos/cli.h>
static void single_timer(char *buf, int len, int argc, char **argv)
{
single_timer_example(1000);
return;
}
static void repeat_timer(char *buf, int len, int argc, char **argv)
{
repeat_timer_example(2000);
return;
}
static void autoload_repeat_timer(char *buf, int len, int argc, char **argv)
{
g_repeat_autoload_timer_example(3000);
return;
}
struct cli_command timer_cli_cmds[] = {
{"stimer", "single timer test", single_timer},
{"rtimer", "non-autoload repeat timer test", repeat_timer},
{"artimer", "autoload repeat timer test", autoload_repeat_timer},
};
int new_comp_timer_test_cmd_init(void) {
return aos_cli_register_commands(&timer_cli_cmds[0],
sizeof(timer_cli_cmds)/sizeof(timer_cli_cmds[0]));
}
将本节中的所有代码复制到AliOS-Things/application/example/helloworld_demo/appdemo.c中,并修改appdemo.c中application_start函数实现如下:
int application_start(int argc, char *argv[])
{
int count = 0;
printf("nano entry here!\r\n");
new_comp_timer_test_cmd_init();
while(1) {
//printf("hello world! count %d \r\n", count++);
aos_msleep(1000);
};
}
3.6、Timer案例执行结果
编译helloworld_demo@haaseduk1并将固件烧录到HaaS EDU之后,系统启动之后测试方法如下:
- 敲help,确认为timer测试添加的cli指令是否出现
- 敲入stimer,确认单次timer是否只执行了一次。
- 敲入rtimer,确认timer是否执行了5次。
- 敲入artimer,确认timer是否执行了5次。
开发者技术支持
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/