一键多功能实现方法(Lua版本)

        这两天面试了一家做传感器的公司,当时老板问:按键处理要延迟多长?口快回答了:我一般会延时20ms。后来想想,其实我写按键处理程序从来就不加延时,但又能达到20ms防抖的效果。实现方式是:20ms调度一次按键扫描程序,如果连接扫描到有按键触发的电平时,就可以认为是有效的按键动作。平时使用20ms,一来方便计算N次后使用了多少时间,二来调度程序里还会做点别的事。

        最近在LuatOS上写了个一键多功能的模块,使用按键的次数来判断按键触发动作。例如:按1次为单击功能、按2次为双击功能......如此类推。以下分享完整的源码:

OneKeyScan.lua

--- 模块功能:一键多功能按键程序
-- @module onekeyscan
-- @author Denuin
-- @release 2022.03.19
local onekeyscan = {}
 
local holdcnt = 0
local scancnt = 0
local lastscancnt = 0
local state = 0
local holdcnt_state = 0

local pin_key = 4 -- LCD_CENTER
 
local pass_fun = nil  -- 单击
local release_fun = nil -- 释放
local double_pass_fun = nil  -- 双击
local three_pass_fun = nil  -- 三连操作
local hold_fun = nil  -- 长按
 
 -- id值为连接按键的次数
local function key_pass_action(id)
    if id== 1 then 
        if pass_fun ~= nil then pass_fun() end
    end
    if id== 2 then 
        if double_pass_fun ~= nil then double_pass_fun() end
    end
    if id== 3 then 
        if three_pass_fun ~= nil then three_pass_fun() end
    end
end

local function key_release_action()
    if release_fun ~= nil then release_fun() end
   -- log.info("key_release_action","")
end

 -- id值为连接按键的次数
local function key_hold_action(id)
    if hold_fun ~= nil then hold_fun() end
end

function onekeyscan.setup(pin)
    pin_key = pin
    gpio.setup(pin_key, nil, gpio.PULLUP)
end
 
function onekeyscan.pass(action)
    pass_fun = action
end
function onekeyscan.double(action)
    double_pass_fun = action
end
function onekeyscan.three(action)
    three_pass_fun = action
end
function onekeyscan.release(action)
    release_fun = action
end
function onekeyscan.hold(action)
    hold_fun = action
end

-- 20ms进行一次扫描
function onekeyscan.run()
    scancnt = scancnt + 1
    if gpio.get(pin_key) == 0 then
        holdcnt = holdcnt + 1
        if holdcnt > 50 then 
            holdcnt = 40 
            holdcnt_state = holdcnt_state + 1
        end
        if holdcnt == 1 then 
            state = state + 1
            lastscancnt = scancnt
        end
         -- 长按
        if holdcnt == 49 then 
            key_hold_action(holdcnt_state)
            state = 0
        end
    else
        if holdcnt > 0 then 
            key_release_action()
            holdcnt_state = 0
        end
        holdcnt = 0
    end

    if scancnt-lastscancnt > 25 then
        scancnt = 0
        lastscancnt = 0
        if state > 0 and holdcnt==0 then 
            key_pass_action(state)
        end
        state = 0
    end
end
 
return onekeyscan

使用方法(demo)

-- (其它代码略)

local keyscan = require("onekeyscan")

-- 引脚设置
keyscan.setup(4) -- ESP32C3的BOOT键引脚为4
 
-- 单击操作
keyscan.pass(function() log.info("keyscan.pass", "pass") end)
 
-- 松开操作
keyscan.release(function() log.info("keyscan.release", "release") end)
 
-- 长按操作
keyscan.hold(function() log.info("keyscan.hold", "hold") end)

-- 双击操作
keyscan.double(function() log.info("keyscan.double", "double") end)

-- 三连操作
keyscan.three(function() log.info("keyscan.three", "three") end)


-- 按键扫描(20ms扫描一次)
sys.taskInit(function()
    while 1 do
        keyscan.run()
        sys.wait(20)
    end
end)

-- (其它代码略)

参考:

Air101-LCD扩展板按键源码_Denuin的博客-CSDN博客

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Lua实现多线程模式可以使用 Lua 提供的 coroutine 库,它可以创建多个协同程序,每个协同程序都有自己的执行栈和局部变量。 在 Lua 中创建协同程序可以使用 coroutine.create() 函数,该函数会返回一个协同程序对象。使用 coroutine.resume() 函数可以启动一个协同程序并执行它的代码,使用 coroutine.yield() 函数可以挂起一个协同程序并返回执行权给调用它的程序。 下面是一个简单的示例代码: ```lua function foo() for i = 1, 10 do print("foo", i) coroutine.yield() end end function bar() for i = 1, 10 do print("bar", i) coroutine.yield() end end co1 = coroutine.create(foo) co2 = coroutine.create(bar) while true do if coroutine.status(co1) ~= "dead" then coroutine.resume(co1) end if coroutine.status(co2) ~= "dead" then coroutine.resume(co2) end if coroutine.status(co1) == "dead" and coroutine.status(co2) == "dead" then break end end ``` 这个例子中,我们创建了两个协同程序 co1 和 co2,分别对应函数 foo 和 bar。在主程序中,我们不断轮流启动这两个协同程序,直到它们都执行完毕为止。运行这个程序,输出如下: ``` foo 1 bar 1 foo 2 bar 2 foo 3 bar 3 foo 4 bar 4 foo 5 bar 5 foo 6 bar 6 foo 7 bar 7 foo 8 bar 8 foo 9 bar 9 foo 10 bar 10 ``` 可以看到,两个协同程序在交替执行实现了多线程的效果。需要注意的是,在 Lua 中使用协同程序实现的多线程并不是真正的多线程,只是通过协同程序的切换实现了并发执行的效果。此外,协同程序之间并没有固定的执行顺序,具体的执行顺序取决于调度器的实现和协同程序的状态。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值