• 欢迎大家分享资料!前往留言板评论即可!

5、合宙Air模块Luat开发:GPIO输入常见的两种使用方法及其优劣性

合宙 模组资料网 2年前 (2021-05-15) 431次浏览 0个评论 扫描二维码
文章目录[隐藏]

目录

点击这里查看所有博文

本系列博客,理论上适用于合宙的Air202、Air268、Air720x、Air720S以及最近发布的Air720U(我还没拿到样机,应该也能支持)。

先不管支不支持,如果你用的是合宙的模块,那都不妨一试,也许会有意外收获
我使用的是Air720SL模块,如果在其他模块上不能用,那就是底层core固件暂时还没有支持,这里的代码是没有问题的。例程仅供参考!

一、前言

上一篇博文我们讲到了将GPIO初始化为输出功能用来驱动LED或者其他外设,这篇博文我们来继续讲讲GPIO剩下的另外一个功能——输入功能

既然是智能设备,那就需要和外界交互信息。获取外界消息的方法有很多。
通过互联网访问是一种获取信息的方式。
在这里插入图片描述
还有是通过自身的传感器或者按钮开关,获取传感信息,也是一种获取信息的方式,它们输出的信号是开关量
5、合宙Air模块Luat开发:GPIO输入常见的两种使用方法及其优劣性5、合宙Air模块Luat开发: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采用中断,几乎感觉不出来有延时
5、合宙Air模块Luat开发:GPIO输入常见的两种使用方法及其优劣性

四、总结

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里面讲了怎么下载
这里只是我的学习笔记,拿出来给大家分享,欢迎大家批评指正,本篇教程到此结束


喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址