定时器(timer)
一、定时器(timer)的概述
- 在 Air780E 模组搭载的 LuatOS 系统中,定时器(timer)是一项基础且关键的服务。它允许开发者在特定的时间点或周期性地执行代码段,为物联网设备的运行提供了精确的时间控制。定时器在多种应用场景中都发挥着重要作用,如定时发送数据、周期性检查传感器状态等。
二、准备硬件环境
参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。
三、软件环境
“凡事预则立,不预则废。”在详细阐述本功能示例之前,我们需先精心筹备好以下软件环境。
1. Luatools工具;
2. 内核固件文件(底层core固件文件):LuatOS-SoC_V1112_EC618_FULL.soc;参考项目使用的内核固件;
3. luatos需要的脚本和资源文件
脚本和资源文件右键点我,另存为,下载完整压缩文件包
lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到Air780E核心板,将本篇文章中演示使用的项目文件烧录到Air780E核心板中。
四、定时器(timer)基本用法
4.1 本教程实现的功能定义:
- 此次 demo 验证单次触发定时器和周期性触发定时器的基本功能。
- 尝试展示了如何通过定时器回调函数执行特定任务。
- 验证定时
sys.timerStopAll
和sys.timerStop
的用法。
4.2 文章内容引用
- Air780E 开发板软硬件资料 : Air780E 产品手册
- 以上接口函数不做详细介绍,可通过此链接查看具体介绍:sys 库
4.3 sys.timerStart
功能:启动一个定时器,该定时器在指定的延迟时间后执行回调函数,或者如果指定了重复次数,则周期性地执行回调函数。
函数原型:local timerId = sys.timerStart(func, timeout, repeat, arg1, arg2, ..., argN)
参数:
func
:定时器触发时要执行的回调函数。timeout
:定时器启动后的延迟时间(以毫秒为单位),即定时器触发前需要等待的时间。arg1, arg2, ..., argN
(可选):传递给回调函数的参数,可以是多个。
例子:
sys.timerStart(function(a, b, c)
log.info("task", a, b, c) -- 1000毫秒后才会执行, 打印 task A B C
end, 1000, "A", "B", "N")
4.4 sys.timerStop
功能:停止一个已启动的定时器。
函数原型:sys.timerStop(timerId)
参数:timerId
:要停止的定时器的唯一标识符。
例子:
-- 停止之前启动的定时器timerId1
sys.timerStop(timerId1)
4.5 sys.timerLoopStart
功能:启动一个周期性定时器,该定时器会按照指定的时间间隔反复执行回调函数。
函数原型:local timerId = sys.timerLoopStart(func, timeout, arg1, arg2, ..., argN)
参数:
func
:定时器触发时要执行的回调函数。timeout
:定时器的时间间隔(以毫秒为单位),即每次触发之间的等待时间。arg1, arg2, ..., argN
:传递给回调函数的参数(可选),可以是多个。
返回值:返回定时器的唯一标识符 timerId
,该标识符可用于后续停止定时器。
例子:
-- 定义一个回调函数,该函数会打印传递给它的参数
local function printArgs(arg1, arg2)
print("Argument 1:", arg1)
print("Argument 2:", arg2)
end
-- 启动一个每3000毫秒触发一次的周期性定时器,并传递两个参数给回调函数
local timerId = sys.timerLoopStart(printArgs, 3000, "Hello", 123)
-- 为了保持程序运行并观察定时器的触发,可以添加一个无限循环(注意:在实际应用中,应避免使用简单的无限循环,而是应使用更高效的任务调度机制)
while true do -- 这里可以添加其他逻辑,但在这个例子中,我们仅仅保持循环运行以观察定时器的触发
sys.wait(1000)
-- 等待1秒(注意:这里的等待不会影响定时器的触发) -- 注意:在实际应用中,应该使用更合适的机制来管理程序的运行和定时器的触发,而不是简单的无限循环和等待
end
-- 注意:在实际代码中,应该在不再需要定时器时调用sys.timerStop来停止它,以避免资源泄露。但由于上面的例子包含了一个无限循环,所以这里没有展示停止定时器的代码。在实际应用中,您应该在适当的时机调用sys.timerStop(timerId)来停止定时器。
4.6 sys.timerStopAll
功能:关闭同一回调函数的所有定时器。
函数原型:sys.timerStopAll([fnc])
参数:fnc
:fnc回调的函数。
返回值:无。
例子:
-- 关闭回调函数为publicTimerCbFnc的所有定时器
local function publicTimerCbFnc(tag)
log.info("publicTimerCbFnc",tag)
end
sys.timerStart(publicTimerCbFnc,8000,"first")
sys.timerStart(publicTimerCbFnc,8000,"second")
sys.timerStart(publicTimerCbFnc,8000,"third")
sys.timerStopAll(publicTimerCbFnc)
五、定时器(timer)整体演示
5.1 成果演示与深度解析:视频 + 图文全面展示
5.1.1 成果运行精彩呈现
5.1.2 演示视频生动展示
5.1.3 完整实例深度剖析
-- main.lua文件
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "timer_demo"
VERSION = "1.0.0"
sys = require("sys")
-- 定义一个单次触发的定时器回调函数
local function oneShotCallback(message)
log.info("One-shot timer triggered: " .. message)
end
-- 定义一个周期性触发的定时器回调函数
local function periodicCallback(count)
log.info("Periodic timer triggered (Count: " .. count .. ")")
end
-- 定义一个周期性触发的定时器回调函数
local function periodicCallback1(count)
log.info("Periodic timer triggered1 (Count: " .. count .. ")")
end
-- 初始化计数器,用于周期性定时器
local periodicCount = 0
-- 启动一个单次触发的定时器,延迟3秒后触发
local oneShotTimerId = sys.timerStart(oneShotCallback, 3000, 0, "Hello from one-shot timer!")
-- 启动一个一次性定时器,分别再第7、6、5秒触发一次
sys.timerStart(periodicCallback,7000,"first")
sys.timerStart(periodicCallback,6000,"second")
sys.timerStart(periodicCallback,5000,"third")
local periodicTimerId2 = sys.timerLoopStart(function() periodicCount = periodicCount + 1 periodicCallback1(periodicCount)
end, 2000)
-- 停止所有定时器(仅作为测试,实际应用中应根据需要停止)
sys.timerStart(function()
sys.timerStop(periodicTimerId2)
log.info("stop 2s loop timer periodicCallback1")
end,5000)
sys.timerStart(function()
sys.timerStopAll(periodicCallback)
log.info("stop periodicCallback loop timer ")
end,4000)
sys.run()-- sys.run()-此后不要在添加其他函数
六、总结
七、常见问题:
7.1 回调函数执行异常:
- 如果定时器的回调函数中存在异常处理不当的情况,可能会导致程序崩溃或产生不可预知的行为。
- 需要在回调函数中做好异常处理,确保程序的健壮性。
7.2 定时器冲突:
- 在多个定时器同时存在的情况下,可能会存在定时器冲突的问题,即多个定时器同时触发或相互干扰。
- 需要合理设计定时器的触发时间和周期,避免冲突的发生。
7.3 资源占用问题:
- 定时器的创建、启动和停止等操作可能会占用一定的系统资源,如内存、CPU 等。
- 在资源受限的嵌入式系统中,需要合理管理定时器的使用,避免资源过度占用。
7.4 定时器 ID 管理:
- 在使用定时器接口函数时,通常会返回一个定时器 ID 用于后续操作。如果定时器 ID 管理不当,可能会导致无法正确停止或删除定时器。
- 需要建立良好的定时器 ID 管理机制,确保定时器的正确操作。
7.5 定时器重复启动问题:
- 在某些情况下,可能会不小心重复启动同一个定时器,导致多个相同的定时器同时存在。
- 这可能会导致资源浪费或任务重复执行。需要确保定时器的唯一性和正确性。
八、扩展
8.1 定时器的嵌套与递归
- 嵌套定时器:在某些情况下,一个定时器的回调函数可能会启动另一个定时器。这种嵌套定时器的使用需要特别小心,以避免无限递归或资源耗尽。
- 递归定时器:递归定时器是指一个定时器在其回调函数中重新启动自己。这种用法需要特别注意避免无限循环和堆栈溢出。
8.2 定时器的动态调整
- 周期调整:在某些应用中,可能需要动态调整定时器的周期。这通常涉及停止当前定时器并重新启动一个新周期的定时器。
- 任务优先级调整:对于某些实时性要求较高的任务,可能需要动态调整定时器的优先级,以确保任务能够及时执行。
给读者的话
本篇文章由
永仔
开发;本篇文章描述的内容,如果有错误、细节缺失、细节不清晰或者其他任何问题,总之就是无法解决您遇到的问题;
请登录合宙技术交流论坛,点击文档找错赢奖金-Air780E-LuatOS-软件指南-基础服务-定时器;
用截图标注+文字描述的方式跟帖回复,记录清楚您发现的问题;
我们会迅速核实并且修改文档;
同时也会为您累计找错积分,您还可能赢取月度找错奖金!