当NodeMCU定时器内的代码执行超过我设置的定时器间隔会发生什么?

在esp8266芯片中,我们可以很容易地创建计时器功能。但是,我想知道,如果定时器内的代码执行超过我设置的定时器间隔,会发生什么?

请参见下面的代码。 如果我设置一个2秒的定时器间隔,并且在此定时器内的“要做的事情”执行超过2秒,然后会发生什么?

tmr.alarm(0, 2000, 1, function ()
    --要做的事情
end)

a)一旦定时器间隔达到2秒,“要做的事情”会被终止吗?

b)或者“要做的事情”将继续执行直到完成,并且下一个“要做的事情”将被延迟?

c)还是这个定时器的每一轮都会等待“要做的事情”完成而不管2秒的间隔?(间隔自动扩展)

d)还是其他情况?

点赞
用户6614127
用户6614127

该函数的行为可能与您想象的不同。通常,在需要提供回调函数时,回调函数将在事件发生时执行;这也是这里发生的情况。回调函数是在计时器到期执行的。

tmr.alarm() 的文档称该函数是 tmr.register()tmr.start() 的组合。tmr.register() 的文档指出:

配置计时器并注册在任务结束时调用的回调函数。

因此,答案是“要做某事”,直到它完成,在调用 tmr.alarm() 函数后 2 秒之后才会运行。

tmr.alarm()(以及它基于的 tmr.register())可以接受 mode 参数。我将描述它们的行为以及如何受回调函数执行时间的影响。

  • tmr.ALARM_SINGLE:仅在调用 tmr.alarm() 结束 n 秒后运行一次回调函数。与回调函数的执行时间完全无关。
  • tmr.ALARM_AUTO:在调用 tmr.alarm() 结束后每 n 秒重复运行回调函数。需要注意的是,下一次间隔会在上一次完成后立即开始,而不管回调函数的执行时间如何。因此,如果回调函数需要 0.5 秒来完成执行,而计时器是 2 秒,则下一次调用将在回调函数结束后 1.5 秒发生。
  • tmr.ALARM_SEMI:在调用 tmr.alarm() 结束后 n 秒运行回调函数。与 tmr.ALARM_AUTO 不同的是,下一个间隔不会自动启动,而只有在调用 tmr.start() 后才会启动。您可能应该在回调函数中调用它。这意味着您可以根据回调函数的执行时间设置计时器。如果计时器是 2 秒,并在回调函数结束时重新启动计时器,则下一次回调将在 2 秒后运行。

正如您可能已经注意到的,您不希望回调函数的执行时间大于计时器周期,回调函数将始终堆叠在一起,永远不会完成。回调应该是简单且快速执行的,并可能将其他工作安排为另一个任务。

2017-06-01 05:15:41
用户131929
用户131929

我相信有一些误解关于 NodeMCU 是什么类型的固件或需要怎样的编程模型。

NodeMCU 的编程模型类似于 Node.js 的模型,只不过是用 Lua 完成的。它是异步和事件驱动的。因此,许多函数需要回调函数作为参数。

来源: NodeMCU README, "Programming Model"

Lua 库提供了一组函数,用于将应用程序功能(用 Lua 编写)声明为回调函数(存储在 Lua 注册表中),将应用程序任务与特定的硬件和定时器事件关联起来。它们是非抢占式的,位于应用程序级别 *。Lua 库与 SDK 协同工作,将待定事件排队,并调用任何已注册的 Lua 回调例程,然后不间断地运行到完成。

来源:NodeMCU Lua 开发人员 FAQ

完整的解释详见 https://nodemcu.readthedocs.io/en/latest/en/lua-developer-faq/#so-how-does-the-sdk-event-tasking-system-work-in-lua 中的 “事件任务系统” 章节。

你说:

这个计时器内的 “Something to do” 执行时间超过了 2 秒

但事实上它将 永远不会 运行 2 秒。实际上,任何运行超过几毫秒的未中断任务都可能导致 Wifi 和 TCP 栈失败。如果您编写违反此原则的代码,则看门狗可能会任何时间重置您的设备。您的代码触发的事件只是按顺序添加到队列中执行。

因此,在大多数情况下,正确答案是 b)。

2017-06-01 09:54:12