目录
本系列博客,理论上适用于合宙的Air202、Air268、Air720x、Air720S以及最近发布的Air720U(我还没拿到样机,应该也能支持)。
先不管支不支持,如果你用的是合宙的模块,那都不妨一试,也许会有意外收获
我使用的是Air720SL模块,如果在其他模块上不能用,那就是底层core固件暂时还没有支持,这里的代码是没有问题的。例程仅供参考!
一、前言
上一篇博文我们讲到了将GPIO初始化为输出功能用来驱动LED或者其他外设,这篇博文我们来继续讲讲GPIO剩下的另外一个功能——输入功能
既然是智能设备,那就需要和外界交互信息。获取外界消息的方法有很多。
通过互联网访问是一种获取信息的方式。
还有是通过自身的传感器或者按钮开关,获取传感信息,也是一种获取信息的方式,它们输出的信号是开关量
通过互联网获取信息,我们后面的博客在讲,先不急。
我们今天来讲一讲,怎么利用GPIO的输入功能来获取外界的开关信号。
二、编写程序
利用GPIO的输入功能获取开关信号有两种方法,一种是查询法,另外一种是中断法,我们依次讲解
1、查询法
顾名思义,查询法就是不停的查询GPIO的状态,不管开关有没有按下,我都去查询,查询到什么就是什么,我没有查询的时候,你按了也没有用,这种方法的实时性比较低。
具体使用方法如下
local function GPIO_Input_init()
local KEY1 = pins.setup(27, nil, pio.PULLUP)--将GPIO27初始化为输入上拉
local LED1 = pins.setup(64, 0)--将GPIO64初始化为输出
while true do
if KEY1() == 0 then--如果KEY1被接地,那么就点亮LED1
LED1(1)
else
LED1(0)--否则熄灭LED1
end
sys.wait(1000)--一秒查询一次
end
end
查询法用起来比较简单需要不停的去查询
假如延时过短,就会出现任务切换频繁,执行效率低,cpu一直在忙着查询。
延时时间过长就会出现实时性低,比如我上面的代码key1接通后运气不好的时候需要等一秒钟才会有反应,不建议在对事件敏感的时候使用
2、中断法
中断我对它的理解是,他的优先级高于普通函数,可以打断正在执行的低优先级中断,和普通任务。
有打断的意思,只要正在执行的任务优先级比它低,当中断来临时就可以被打断,转而去执行中断函数。
中断的原则是快进快出,不能在里面执行复杂的事情,否则会影响其他任务执行。相对普通任务实时性较高,适用于对事件敏感的情况
在Air720SL中GPIO输入中断的使用方法如下
local LED2
function GPIO_Exti_cb(msg)--中断回调函数
if msg == cpu.INT_GPIO_POSEDGE then--如果当前中断是上升沿触发
LED2(0)--熄灭LED2
else
LED2(1)--否则点亮LED2
end
end
local function GPIO_Exti_init()
local KEY2 = pins.setup(28, GPIO_Exti_cb, pio.PULLUP)--将GPIO28初始化为输入上拉,并且启用中断回调
LED2 = pins.setup(65, 0)--将GPIO65初始化为输出
end
中断的使用方法相比查询到要显得麻烦一下,需要多写一个函数,代码量比较多,但是好处就是实时性高。
# 三、下载完整的代码到Air720Sl开发板
这里我们直接贴出全部代码
--必须在这个位置定义PROJECT和VERSION变量
--PROJECT:ascii string类型,可以随便定义,只要不使用,就行
--VERSION:ascii string类型,如果使用Luat物联云平台固件升级的功能,必须按照"X.X.X"定义,X表示1位数字;否则可随便定义
PROJECT = "LED"
VERSION = "0.0.1"
require "sys"
--加载日志功能模块,并且设置日志输出等级
--如果关闭调用log模块接口输出的日志,等级设置为log.LOG_SILENT即可
require "log"
LOG_LEVEL = log.LOGLEVEL_TRACE
require "pins"
local function GPIO_Input_init()
local KEY1 = pins.setup(27, nil, pio.PULLUP)--将GPIO27初始化为输入上拉
local LED1 = pins.setup(64, 0)--将GPIO64初始化为输出
while true do
if KEY1() == 0 then--如果KEY1被接地,那么就点亮LED1
LED1(1)
else
LED1(0)--否则熄灭LED1
end
sys.wait(1000)--一秒查询一次
end
end
local LED2
function GPIO_Exti_cb(msg)--中断回调函数
if msg == cpu.INT_GPIO_POSEDGE then--如果当前中断是上升沿触发
LED2(0)--熄灭LED2
else
LED2(1)--否则点亮LED2
end
end
local function GPIO_Exti_init()
local KEY2 = pins.setup(28, GPIO_Exti_cb, pio.PULLUP)--将GPIO28初始化为输入上拉,并且启用中断回调
LED2 = pins.setup(65, 0)--将GPIO65初始化为输出
end
local function user_main()
sys.wait(10000)
sys.taskInit(GPIO_Input_init)
sys.taskInit(GPIO_Exti_init)
end
--启动系统框架
sys.taskInit(user_main)
sys.init(0, 0)
sys.run()
下载程序后运行结果如下,GPIO27控制LED1,GPIO28控制LED2.
GPIO27使用一秒查询一次,反应速度感觉明显有卡顿
GPIO28采用中断,几乎感觉不出来有延时
四、总结
1、官方的pins库函数
- pins.setup(28, GPIO_Exti_cb, pio.PULLUP)–将GPIO28初始化为输入上拉,并且启用中断回调
- pins.setup(27, nil, pio.PULLUP)–将GPIO27初始化为输入上拉
2、两种使用方法的环境
- 查询法适用于普通场景,对事件敏感度不高的情况,查询不建议太过于频繁,一般按钮的话500ms查询一次,速度都还可以接收,
- 中断法适用于强实时性场所,比如某些设备的
急停按钮
这就不能用查询法了,这类按钮对事件要求比较严格,用中断可以满足要求
不会下载的点击这里,进去查看我的第二篇博文
2、Air720SL模块Luat开发:第一个Luat的Hello World
里面讲了怎么下载
这里只是我的学习笔记,拿出来给大家分享,欢迎大家批评指正,本篇教程到此结束