这两天面试了一家做传感器的公司,当时老板问:按键处理要延迟多长?口快回答了:我一般会延时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)
-- (其它代码略)
参考: