鸿蒙LiteOS软件定时器实战:多定时器周期性任务完整示例(源码+解析)
一、前言
在嵌入式鸿蒙(OpenHarmony LiteOS)开发中,软件定时器是实现周期性任务、延时任务、定时触发逻辑的核心内核工具,无需占用硬件定时器资源,支持创建多个定时器同时运行。
本文基于LiteOS内核API,手把手讲解软件定时器创建、启动、周期性运行的完整流程,提供可直接编译运行的标准源码,适合鸿蒙单片机开发入门学习。
哔站视频《06:RK2206 OpenHarmonyOS 鸿蒙 软件定时器与硬件定时器区别 软件定时器与任务区别 软件定时器实战》:https://www.bilibili.com/video/BV1w3546DEBS/?vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7
哔站视频《05:RK2206 OpenHarmonyOS 鸿蒙 什么是信号量 为什么需要信号量 代码演示》:https://www.bilibili.com/video/BV1to5W6pETF/?vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7
哔站视频《04:RK2206 OpenHarmonyOS 鸿蒙 任务实战》:https://www.bilibili.com/video/BV15R5E6JEHy/
哔站视频《03:RK2206 鸿蒙 LiteOS 如何通过控制编译选项编译不同案例》:https://www.bilibili.com/video/BV15e5J6QEGY/?spm_id_from=333.1387.homepage.video_card.click&vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7
哔站视频《02:RK2206 鸿蒙 LiteOS bin 文件 烧写》:https://www.bilibili.com/video/BV1pcRdBaEAt/?spm_id_from=333.1387.homepage.video_card.click&vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7
哔站视频《01:RK2206 鸿蒙 LiteOS ubuntu 开发环境 全程 安装配置》:https://www.bilibili.com/video/BV1nrRkBoEMR/?spm_id_from=333.1387.homepage.video_card.click&vd_source=3a9dd7a328acafb09dd1b8d05f3e2bf7
二、LiteOS软件定时器核心概念
1. 什么是软件定时器
软件定时器是基于系统时钟节拍实现的定时服务,由LiteOS内核提供,不依赖硬件外设,可创建多个独立定时器,分别设置不同超时时间和回调函数。
2. 软件定时器主要作用
- 实现周期性任务(每隔1s、2s执行一段逻辑)
- 实现延时触发功能
- 替代硬件定时器,节省硬件资源
- 多任务定时调度,简化业务逻辑
3. 核心工作模式
本文使用LOS_SWTMR_MODE_PERIOD(周期性模式):
定时器超时后自动重启,循环执行回调函数,直到手动停止/删除。
三、软件定时器核心API函数
| API函数 | 功能说明 |
|---|---|
| LOS_SwtmrCreate | 创建软件定时器,指定超时时间、模式、回调函数 |
| LOS_SwtmrStart | 启动已创建的定时器 |
| LOS_SwtmrStop | 停止正在运行的定时器 |
| LOS_SwtmrDelete | 删除定时器,释放内核资源 |
API参数说明
LOS_SwtmrCreate(timeout,// 超时时间(单位:Tick,LiteOS默认1Tick=1ms)mode,// 模式:单次/周期callback,// 超时回调函数timerID,// 定时器ID(输出)arg// 回调函数参数)四、完整可运行源码
#include"los_swtmr.h"#include"ohos_init.h"voidtimer1_timeout(void*arg){printf("This is Timer1 Timeout function\n");}voidtimer2_timeout(void*arg){printf("This is Timer2 Timeout function\n");}voidtimer_example(){unsignedinttimer_id1,timer_id2;unsignedintret;/* 创建定时器1:1000ms = 1s 周期性执行 */ret=LOS_SwtmrCreate(1000,LOS_SWTMR_MODE_PERIOD,timer1_timeout,&timer_id1,NULL);if(ret==LOS_OK){ret=LOS_SwtmrStart(timer_id1);if(ret!=LOS_OK){printf("start timer1 fail ret:0x%x\n",ret);return;}}else{printf("create timer1 fail ret:0x%x\n",ret);return;}/* 创建定时器2:2000ms = 2s 周期性执行 */ret=LOS_SwtmrCreate(2000,LOS_SWTMR_MODE_PERIOD,timer2_timeout,&timer_id2,NULL);if(ret==LOS_OK){ret=LOS_SwtmrStart(timer_id2);if(ret!=LOS_OK){printf("start timer2 fail ret:0x%x\n",ret);return;}}else{printf("create timer2 fail ret:0x%x\n",ret);return;}}/* 系统自动初始化入口 */APP_FEATURE_INIT(timer_example);五、代码逻辑逐行解析
1. 头文件
los_swtmr.h:LiteOS软件定时器内核头文件ohos_init.h:鸿蒙自动初始化模块头文件
2. 定时器回调函数
timer1_timeout:定时器1超时执行函数,1s执行一次timer2_timeout:定时器2超时执行函数,2s执行一次
3. 定时器创建与启动流程
- 调用
LOS_SwtmrCreate创建定时器 - 判断创建是否成功(返回LOS_OK)
- 调用
LOS_SwtmrStart启动定时器 - 两个定时器独立运行,互不干扰
4. 自动初始化
APP_FEATURE_INIT(timer_example);
系统启动时自动执行定时器初始化,无需手动调用。
六、串口运行打印效果
- Timer1:每隔1s打印一次
- Timer2:每隔2s打印一次
- 两个定时器周期性并发运行
七、常见注意事项
- 回调函数不能阻塞:不能在定时器回调里使用延时、死循环、阻塞API
- 回调函数要简洁:只处理快速逻辑,避免占用系统时钟
- 单位是毫秒:LiteOS默认配置 1 Tick = 1ms
- 多定时器互不影响:可同时创建N个软件定时器并行运行
- 必须先创建、再启动,否则定时器不会运行
八、对比分析 任务 与 软件定时器
| 对比项 | 任务(Task / 线程) | 软件定时器(Software Timer) |
|---|---|---|
| 运行方式 | 独立循环执行 | 只在超时时刻触发一次回调 |
| 能否阻塞 | 可以(延时、等待信号量、休眠) | 绝对不能(一阻塞系统就崩溃) |
| 优先级 | 可设置独立优先级 | 共享定时器任务优先级,不可单独设置 |
| 资源占用 | 较高(需要独立栈) | 极低(共用栈) |
| 执行时长 | 可长可短 | 必须极短(几ms内完成) |
| 使用场景 | 大循环逻辑、复杂业务 | 定时计数、定时打印、定时触发标志 |
| 能否等待信号量 | ✅ 可以 | ❌ 不可以 |
| 能否延时 | ✅ LOS_Msleep 可以 | ❌ 绝对不可以 |
定时器回调函数绝对不能做
- 不能延时(LOS_Msleep)
- 不能死循环
- 不能等待信号量/消息队列
- 不能执行耗时操作(超过10ms都危险)
任务可以随便做
- 可以循环
- 可以阻塞
- 可以等待
- 可以运行复杂业务
九、什么时候用定时器?什么时候用任务?
✅ 用定时器的场景
- 定时1秒打印一次日志
- 定时刷新LED
- 定时更新计数器
- 定时设置一个标志位
- 功能简单、时间短、到点触发一下
✅ 用任务的场景
- 需要大循环
- 需要等待信号量
- 需要处理复杂逻辑
- 需要阻塞、延时、休眠
- 需要处理串口、网络、文件系统