晨旭的博客
你想干什么!
晨旭的博客~
Luat系列教程:3、LUAT程序的基本时序

LUAT系列全部教程可以点击下面链接查看(建议保存书签):

https://www.chenxublog.com/tag/luat系列教程

适合阅读本文的人
至少用过一款单片机的
接触、了解过或听说过rtos、ucos等多线程系统
前几篇文章所提内容都已经懂了的
有耐心看完本文的
对lua语法熟悉的,如不熟悉请移步
http://www.runoob.com/lua/lua-tutorial.html

https://www.lua.org/manual/5.1/manual.html
进行学习。

本文只会介绍LuaTask中多线程任务的基本用法,不会过多的讨论原理,如果需要深入研究,请查看wiki页的详细介绍:http://wiki.openluat.com/doc/run/

简单定时器函数的使用

上一章里的点亮led小灯,最后一步是让led灯闪烁起来。习惯了c语言写代码的人可能会发现,这个lua程序中好像没有delay之类的函数。

我们把上一章的代码简化一下,像如下这样:

function sayHello()
    print("hello")
    sys.timerStart(sayHello,1000)--一秒后执行指定函数
    print("bye")
end

sayHello()

.....其他代码

这里使用了定时器的接口:sys.timerStart(fnc, ms, ...),用过js之类语言的可能会感到特别熟悉。在luat中,一般不在主线程中使用类似c一样用死循环阻塞式地来延时,取而代之的是这种定时器的结构,流程图如下:

其实实现上述定时器循环执行某函数的功能,可以直接使用sys.timerLoopStart(fnc, ms, ...)接口,改成如下样式:

function sayHello()
    print("hello")
end

sys.timerLoopStart(sayHello,1000)

.....其他代码

整个流程图便变成了如下的顺序:

为了使函数更简洁,我们可以直接把函数名改成function() ..... end的形式,在函数变量中直接定义要使用的函数:

sys.timerLoopStart(function()
                       print("hello")
                   end,1000)

甚至可以写成一行:

sys.timerLoopStart(function() print("hello") end,1000)

上述两段代码的功能与一开始的timerLoopStart示例代码的运行结果完全相同

协程

在wiki页中,给出了这样一段简洁的代码,我们为了照顾不熟悉lua语言的人,稍微改一下代码:

test.lua

function test()
    while true do
        print("ss function test")
        sys.wait(1000)          -- 挂起1000ms,同理为每隔1000ms运行一次
    end
end

sys.taskInit(test)

.....其他代码

在这里,sys.taskInit的作用可以理解为创建了一个新的线程,这个线程运行的内容就是test()函数

test()进行while true这样的死循环时,并不会使其他程序被阻塞运行,反而是多线程运行的

LuaTask架构下,协程内的函数可以直接使用sys.wait(ms)函数进行延时操作,延时途中只是将cpu让给了其他需要运行的程序,在倒计时完成后继续该进程的运行,从而实现了延时操作

我们一般会把sys.taskInit内的函数直接写在其中,像下面这样:

sys.taskInit(function()
    while true do
        print("ss function test")
        sys.wait(1000)          -- 挂起1000ms,同理为每隔1000ms运行一次
    end
end)

.....其他代码

相信各位已经可以理解这种写法了(如果从文章开头看到这里了的话),协程的运行流程图如下

我们可以同时开多个线程,使用方法都是一样的

程序注册

LuaTask可以使用订阅和发布,使某个程序等待另一个程序完成后才继续运行

我们来看最简单的一个示例代码:

sys.timerStart(function()
                   sys.publish("TEST")
               end,3000)--三秒后执行发布"TEST"消息的函数

function sub()
    print("start")
    sys.waitUntil("TEST")
    print("wait end")
end

sub()

程序定义了一个5秒后的定时器,并运行了一个包含了时间订阅等待的函数,整体流程运行如下:

这种用法经常用在http、socket等操作和其他需要等待的操作中,利用回调函数可实现等待功能。

sys.publish也可传递参数:

sys.timerStart(function()
                   sys.publish("TEST",123)
               end,3000)--三秒后执行发布"TEST"消息的函数

function sub()
    print("start")
    result,data = sys.waitUntil("TEST")
    print(result,data)
end

sub()

上述代码将会输出:

true    123

同时,luat在库中自带了许多系统消息,部分如下:

消息 释义
SN_READY_IND 可以成功获取SN
IMEI_READY_IND 可以成功获取IMEI
TIME_UPDATE_IND 将当前时间设置为正确的时间
NET_STATE_REGISTERED GSM网络注册成功
GSM_SIGNAL_REPORT_IND 读取到了信号强度
NET_STATE_UNREGISTER GSM网络注册失败
NTP_SUCCEED NTP同步成功
IP_READY_IND IP数据阶段

三种线程控制的使用方法全部介绍完毕了,如果需要了解原理,请去研读http://wiki.openluat.com/doc/run/的说明与解释

如有错误和疑问请在下方留言指出,谢谢

赞赏
如非特殊说明,本站所有文章均采用知识共享 署名-非商业性使用-相同方式共享4.0国际许可协议(CC BY-NC-SA 4.0)进行许可。

发表评论

textsms
account_circle
email

  • https://secure.gravatar.com/avatar/7cc041deac415b9f2193aeb754d9c925?s=80&d=mm&r=x
    zhm6909
    Google Chrome 67.0.3396.87 Google Chrome 67.0.3396.87 Windows 10 x64 Edition Windows 10 x64 Edition

    示意图中的resume和yield是不是反了?

    2月前回复
    • https://secure.gravatar.com/avatar/b431bf781498d1fe47f732913dce394c?s=80&d=mm&r=x
      晨旭博主
      Vivaldi 1.97.1259.3 Vivaldi 1.97.1259.3 Windows 10 x64 Edition Windows 10 x64 Edition

      没吧。。?
      mermaid
      graph TD
      A[定义了一个定时器] –> |等待5秒| C[发布TEST消息]
      B[sub函数] –> D[打印start]
      D –> E[订阅TEST消息]
      E –> F[收到了订阅的TEST消息]
      C –> |把发布的消息推送到订阅处| F
      F –> G[打印wait end]

      2月前回复

晨旭的博客~

Luat系列教程:3、LUAT程序的基本时序
LUAT系列全部教程可以点击下面链接查看(建议保存书签): https://www.chenxublog.com/tag/luat系列教程 适合阅读本文的人 至少用过一款单片机的 接触、了解过或听说过rtos、uc…
扫描二维码继续阅读
2018-08-10