Timer内核定时器
官方文档:OpenAtom OpenHarmony
所需头文件:los_swtmr.h
头文件所在位置:
基本概念:
软件定时器
软件定时器,是基于系统Tick时钟中断且由软件来模拟的定时器,当经过设定的Tick时钟计数值后会触发用户定义的回调函数。定时精度与系统Tick时钟的周期有关。
硬件定时器受硬件的限制,数量上不足以满足用户的实际需求,因此为了满足用户需求,提供更多的定时器,OpenHarmony LiteOS-M内核提供软件定时器功能。软件定时器扩展了定时器的数量,允许创建更多的定时业务。
软件定时器功能上支持:
- 静态裁剪:能通过宏关闭软件定时器功能。
- 软件定时器创建。
- 软件定时器启动。
- 软件定时器停止。
- 软件定时器删除。
- 软件定时器剩余Tick数获取。
定时器状态
- OS_SWTMR_STATUS_UNUSED(未使用) 系统在定时器模块初始化的时候将系统中所有定时器资源初始化成该状态。
- OS_SWTMR_STATUS_CREATED(创建未启动/停止) 在未使用状态下调用LOS_SwtmrCreate接口或者启动后调用LOS_SwtmrStop接口后,定时器将变成该状态。
- OS_SWTMR_STATUS_TICKING(计数) 在定时器创建后调用LOS_SwtmrStart接口,定时器将变成该状态,表示定时器运行时的状态。
定时器模式
OpenHarmony LiteOS-M内核的软件定时器提供三类定时器机制:
- 第一类是单次触发定时器,这类定时器在启动后只会触发一次定时器事件,然后定时器自动删除。
- 第二类是周期触发定时器,这类定时器会周期性的触发定时器事件,直到用户手动地停止定时器,否则将永远持续执行下去。
- 第三类也是单次触发定时器,但与第一类不同之处在于这类定时器超时后不会自动删除,需要调用定时器删除接口删除定时器。
BUILD.gn
因为用到了liteos-m的软件定时器,所以需要引用liteos-m内核库,具体可以参考上节课程中的BUILD.gn
LOS_Timer_example.c
#include "los_swtmr.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "los_task.h"
#include "ohos_run.h"
void Timer1_Callback(uint32_t arg);
void Timer2_Callback(uint32_t arg);
#define LOSCFG_BASE_CORE_SWTMR_ALIGN = 1
#define TASK_PRIO 5
UINT32 g_timercount1 = 0;
UINT32 g_timercount2 = 0;
UINT32 g_testTaskId01;
void Timer1_Callback(uint32_t arg) // 回调函数1
{
unsigned long tick_last1;
g_timercount1++;
tick_last1=(UINT32)LOS_TickCountGet(); // 获取当前Tick数
printf("g_timercount1=%d\n",g_timercount1);
printf("tick_last1=%d\n",tick_last1);
}
void Timer2_Callback(uint32_t arg) // 回调函数2
{
unsigned long tick_last2;
tick_last2=(UINT32)LOS_TickCountGet();
g_timercount2 ++;
printf("g_timercount2=%d\n",g_timercount2);
printf("tick_last2=%d\n",tick_last2);
}
void Timer_example(void)
{
UINT32 id1;
UINT32 id2; // timer id
UINT32 uwTick;
/* 创建单次软件定时器,Tick数为1000,启动到1000Tick数时执行回调函数1 */
LOS_SwtmrCreate (1000, LOS_SWTMR_MODE_ONCE, Timer1_Callback, &id1, 1, OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE);
/* 创建周期性软件定时器,每100Tick数执行回调函数2 */
LOS_SwtmrCreate(100, LOS_SWTMR_MODE_PERIOD, Timer2_Callback, &id2, 1, OS_SWTMR_ROUSES_ALLOW, OS_SWTMR_ALIGN_INSENSITIVE);
printf("create Timer1 success\n");
LOS_SwtmrStart (id1); //启动单次软件定时器
printf("start Timer1 success\n");
LOS_TaskDelay(200); // 延时200Tick数
LOS_SwtmrTimeGet(id1, &uwTick); // 获得单次软件定时器剩余Tick数
printf("uwTick =%d\n", uwTick);
LOS_SwtmrStop(id1); // 停止软件定时器
printf("stop Timer1 success\n");
LOS_SwtmrStart(id1);
LOS_TaskDelay(1000);
LOS_SwtmrDelete(id1); // 删除软件定时器
printf("delete Timer1 success\n");
LOS_SwtmrStart(id2); // 启动周期性软件定时器
printf("start Timer2\n");
LOS_TaskDelay(1000);
LOS_SwtmrStop(id2);
LOS_SwtmrDelete(id2);
}
UINT32 Example_TaskEntry(VOID)
{
UINT32 ret;
TSK_INIT_PARAM_S task1;
/* 锁任务调度 */
LOS_TaskLock();
/* 创建任务1 */
ret = memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
if (ret != 0) {
printf("memset_s fail!\r\n");
}
task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Timer_example;
task1.pcName = "TimerTsk";
task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
task1.usTaskPrio = TASK_PRIO;
ret = LOS_TaskCreate(&g_testTaskId01, &task1);
if (ret != LOS_OK) {
printf("TimerTsk create failed.\n");
return LOS_NOK;
}
/* 解锁任务调度 */
LOS_TaskUnlock();
return LOS_OK;
}
OHOS_APP_RUN(Example_TaskEntry);
代码分析:
- 首先定义了用于保存定时器ID的变量
id1
和id2
,以及用于获取定时器剩余时间的变量uwTick
。 - 接下来,创建了一个单次运行的软件定时器(
id1
),设置其在1000个时钟滴答后触发Timer1_Callback
。 - 创建了一个周期性运行的软件定时器(
id2
),设置其每隔100个时钟滴答就触发Timer2_Callback
。 - 启动定时器
id1
并延时200个时钟滴答后获取其剩余时间,并打印出来。 - 停止并重新启动定时器
id1
,等待1000个时钟滴答后删除定时器id1
。 - 启动周期性定时器
id2
,等待1000个时钟滴答后停止并删除定时器id2
。
编译并烧录
修改工作文件夹级的BUILD.gn文件,将编译的文件夹指定为新建的003_LOS_Timer
在源码根目录下使用hb工具对写好的代码进行编译
选择mini级系统
同理 产品选择esp公司下的esp32
选择完毕后在源码根目录下执行hb build -f 进行编译
编译完成后会有如下界面,并且编译后的代码固件位于:out\esp32\esp32
验证结果
打开串口工具->选择COM5->打开串口
按下ESP32开发板上的EN键,即可观察到实验现象:
API参考
LOS_SwtmrCreate()
LOS_SwtmrCreate(UINT32 interval,
UINT8 mode,
SWTMR_PROC_FUNC handler,
UINT32 *swtmrID,
UINT32 arg);
描述:
创建一个一次性或周期性计时器,并将其与一个带参数的回调函数相关联。计时器在LOS_SwtmrStart启动之前一直处于停止状态。可以在RTOS启动(调用 LOS_Start)之前安全地调用该函数,但不能在内核初始化 (调用 LOS_KernelInit)之前调用该函数。
注意 :不能在中断服务调用该函数
参数:
名字 | 描述 |
interval | 要创建的软件计时器的定时时长,单位ms |
mode | 定时器类型,课参考EnSwTmrType,包括单次定时器、周期性定时器以及单次定时器但不删除定时器三种类型 |
handler | 函数指针指向回调函数 |
swtmrID | 定时器ID |
argument | 定时器回调函数的参数 |
arg | 回调函数handler的入参 |
LOS_SwtmrStart()
UINT32 LOS_SwtmrStart(UINT32 swtmrID);
描述:
启动或重新启动指定参数swtmrID的计时器。
注意 :不能在中断服务调用该函数
参数:
名字 | 描述 |
swtmrID | 由osTimerNew获得的计时器ID |
LOS_SwtmrStop()
UINT32 LOS_SwtmrStop(UINT32 swtmrID);
描述:
暂停指定参数swtmrID的计时器。
参数:
名字 | 描述 |
swtmrID | 由LOS_SwtmrCreate获得的计时器ID |
LOS_SwtmrDelete()
UINT32 LOS_SwtmrDelete(UINT32 swtmrID);
描述:
删除指定参数swtmrID的计时器。
参数:
名字 | 描述 |
swtmrID | 由LOS_SwtmrCreate获得的计时器ID |