air202c语言编程,Air202学习 五

air202 使用lua程序开发个人理解(基于操作系统)

其实使用lua开发和C语言开发是一样的,只不过使用lua时把硬件的底层给封装好,不需要在自己配置寄存器了, 这一块就需要调用air202官方给封装好的lib库文件

一. 函数运行:

1. 当在文件只是定义实现函数时,它是不会运行的,需要在调用一下, 如:

--test.lua文件

local function TASK( )

print("TASK function test")

end

TASK() --直接调用,在main.lua文件中require"test"的时候则会调用该函数

此时只会打印一次"TASK function test"信息

2. 在协程中运行:死循环一直运行,通过wait挂起

--test.lua文件

--定义的函数时不会执行的,需要调用

local function ss( )

print("ss function test")

end

--调动sys.lua中的函数taskInit 弄出个协程来

sys.taskInit(function()

cnt = 0

while true do

ss()

sys.wait(1000) -- 挂起1000ms,同理为每隔1000ms运行一次

end

end)

定义的函数在协程中调用1000ms执行一次

3. 定时器和协程一起使用:

--test.lua文件

local function ss( )

print("Task function test")

end

local function TIM()

print("TIM function test")

end

--直接调用

--ss() --直接调用,在main.lua文件中require"test"的时候则会调用该函数

--协程

sys.taskInit(function()

cnt = 0

while true do

ss()

sys.wait(1000) -- 挂起1000ms,同理为每隔1000ms运行一次

end

end)

--定时器调用

--sys.timerStart(ss,3000) --3秒运行一次

sys.timerLoopStart (TIM,1000) --循环定时器,每隔1秒运行一次

定时器和协程一起运行结果:

二. 简单总结

1. 因为lua程序是顺序执行下来, 且只执行一遍的那么就需要另外的方法,让需要一直执行的程序块一直运行

2. 如果想要程序一直运行可以像C语言开发单片机那样, 直接用一个循环, 在循环内是一个需要一直运行的程序块,不过要记住把系统要挂起,不知会不会直接死在这.

3. air202 模块还使用了另一方法实现类似C语言开发单片机中的中断方式,当一个操作完成时就会发出一个信号; 其他函数可以订阅该消息并做对应的操作,在接收这个信号后执行某段程序(subscribe订阅方式) ; 调用  sys.lua( Luat协程调度框架 )  中的函数

三. 程序注册 (抄的)

LuaTask通过订阅发布来实现消息机制。

当函数完成一个操作后,可以发布一个消息,其他函数可以订阅该消息并做对应的操作。举个例子,当socket发送完数据后发布“SEND_FINISH”。这时开发者想socket发布完成后通过串口发送数据或者改变某个IO口的状态。就可以订阅该消息subscribe("SEND_FINISH",callback)。callback为接收到SEND_FINISH消息后需要做的事。

先来看一个程序

testMsgPub.lua

--testMsgPub.lua

module(...,package.seeall)

require"sys"

local a = 2

local function pub()

print("pub")

sys.publish("TEST",a) --可以发布多个变量sys.publish("TEST",1,2,3)

end

pub()

testMsgSub.lua

--testMsgSub.lua

module(...,package.seeall)

require"sys"

local function subCallBack(...)

print("rev",arg[1])

end

sys.subscribe("TEST",subCallBack)

如果要在任务函数中订阅消息并做相应的处理,怎么办?

module(...,package.seeall)

require"sys"

local a = 2

local function pub()

print("pub")

sys.publish("TEST",a)

end

pub()

sys.taskInit(function()

while true do

result, data = sys.waitUntil("TEST", 10000)

if result == true then

print("rev")

print(data)

end

sys.wait(2000)

end

end)

调用sys.waitUntil()函数即可。

接下来分析实现的源码

为了更好的理解源码,需要以下的预备知识:

1、回调函数的实现

local function callBackTest(...)

print("callBack",arg[1])

end

local function test( a,callBackTest )

if a > 1 then

callBackTest(1)

end

end

test(2,callBackTest)

--输出

--callBack 1

2、不定参数

function g (a, b, ...) end

g(3) -- a=3, b=nil, arg={n=0} -- n为不定参数的个数

g(3, 4) -- a=3, b=4, arg={n=0}

g(3, 4, 5, 8) -- a=3, b=4, arg={5, 8; n=2}

进入正题

订阅和发布官方给的实例:

------------------------------------------ LUA应用消息订阅/发布接口 ------------------------------------------

-- 订阅者列表

local subscribers = {}

--内部消息队列

local messageQueue = {}

--- 订阅消息

-- @param id 消息id

-- @param callback 消息回调处理

-- @usage subscribe("NET_STATUS_IND", callback)

function subscribe(id, callback)

if type(id) ~= "string" or (type(callback) ~= "function" and type(callback) ~= "thread") then

log.warn("warning: sys.subscribe invalid parameter", id, callback)

return

end

if not subscribers[id] then subscribers[id] = {} end -- 如果没有重复消息

subscribers[id][callback] = true --标记id和callback关系

end

--- 取消订阅消息

-- @param id 消息id

-- @param callback 消息回调处理

-- @usage unsubscribe("NET_STATUS_IND", callback)

function unsubscribe(id, callback)

if type(id) ~= "string" or (type(callback) ~= "function" and type(callback) ~= "thread") then

log.warn("warning: sys.unsubscribe invalid parameter", id, callback)

return

end

if subscribers[id] then subscribers[id][callback] = nil end --删除id和callback关系

end

--- 发布内部消息,存储在内部消息队列中

-- @param ... 可变参数,用户自定义

-- @return 无

-- @usage publish("NET_STATUS_IND")

function publish(...)

table.insert(messageQueue, arg) -- 将不定参数插入队列中

end

-- 分发消息

local function dispatch()

while true do

if #messageQueue == 0 then --如果队列长度为 跳出循环

break

end

local message = table.remove(messageQueue, 1) --获取队列的第一个

if subscribers[message[1]] then --如果订消息存在

for callback, _ in pairs(subscribers[message[1]]) do

if type(callback) == "function" then

print("unpack",unpack(message, 2, #message))

callback(unpack(message, 2, #message)) -- 返回第二个到最后一个

elseif type(callback) == "thread" then

coroutine.resume(callback, unpack(message))

end

end

end

end

end

以sys.publish("TEST",a)和sys.subscribe("TEST",subCallBack),订阅者列表为local subscribers = {}。内部消息队列为local messageQueue = {}为例:

1、在publish函数中,将"TEST"消息和参数插入messageQueue列表中

此时messageQueue中为{{"TEST",2;n=1}}

2、在subscribe函数中判断消息和callback类型是否正确,如果正确则在subscribers中建立消息与回调函数之间的关系。

此时subscribers["TEST"][subCallBack] = true。表明TEST消息对应的回掉函数为subCallBack

3、在dispatch()函数中,获得表头列表。

local message = table.remove(messageQueue, 1)

此时message为{"TEST",2;n=1}

找到该消息对应的回调函数或消息。将message中的参数传给回调函数。

通过pairs遍历得到消息对应的回调函数或者任务。

如果callback是函数,那么将publish时候的参数传给回调函数。

如果callback是线程,那么唤醒该线程。

以上只是单个消息举例,多个消息同理,因为每次循环都会将messageQueue的头部出队列,满足FIFO原则。

在有上基础下容易的理解waitUntil()的实现

--- Task任务的条件等待函数(包括事件消息和定时器消息等条件),只能用于任务函数中。

-- @param id 消息ID

-- @number ms 等待超时时间,单位ms,最大等待126322567毫秒

-- @return result 接收到消息返回true,超时返回false

-- @return data 接收到消息返回消息参数

-- @usage result, data = sys.waitUntil("SIM_IND", 120000)

function waitUntil(id, ms)

subscribe(id, coroutine.running())

local message = ms and {wait(ms)} or {coroutine.yield()}

unsubscribe(id, coroutine.running())

return message[1] ~= nil, unpack(message, 2, #message)

end

1、订阅id,并传入线程号

2、阻塞线程,如果接收到了消息,那么返回message

3、取消订阅该id

4、返回结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值