GPIO
一、GPIO 概述
GPIO 是通用型输入输出的简称,一个 GPIO 引脚可以用于输入、输出或其他特殊功能。
二、演示功能概述
本文将介绍 Air780EPM GPIO 的输入与输出 demo 讲解与效果演示。
三、准备硬件环境
参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。
四、软件环境
在开始实践本示例之前,先筹备一下软件环境:
1. Luatools工具;
2. 内核固件文件(底层core固件文件):LuatOS-SoC_V2003_Air780EPM;参考项目使用的内核固件;
3. luatos需要的脚本和资源文件
脚本和资源文件点我浏览所有文件
lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到Air780EPM开发板,将本篇文章中演示使用的项目文件烧录到Air780EPM开发板中。
4. LuatOS 工程文件
GPIO输出模式:gpio_out_20250328.luatos
GPIO输入模式:gpio_in_20250328.luatos
GPIO中断(触发)模式:gpio_irq_20250328.luatos
GPIO中断(计数)模式:gpio_count_20250328.luatos
AGPIO:agpio_20250328.luatos
GPIO翻转测速:gpio_turn20250328.luatos
GPIO上拉下拉模式:gpio_updown_20250328.luatos
五、GPIO 软硬件参考
5.1 API 接口介绍
本教程使用 api 接口为:
https://docs.openluat.com/air780epm/luatos/api/core/gpio/
5.2 GPIO 硬件设计
5.2.1 GPIO 复用表
六、GPIO 简介
认识模块 GPIO 管脚:Air780EPM 模块的 GPIO 与其他 MCU 类的芯片一样,也可以配置为输入/输出/上拉/下拉/中断等状态,只有在硬件设计手册上注明带 GPIO 功能的管脚才能作为 GPIO 使用。
Air780EPM 的 GPIO 口根据特性分为三种类型:普通 GPIO、AGPIO、Wakeup IO。
下面是普通 GPIO 和 AGPIO 的区别
休眠后状态 |
驱动能力 |
输入输出 |
中断 |
|
---|---|---|---|---|
普通 GPIO |
掉电且伴随网络状态可能会有不定周期的波动 |
单个 <10mA 总计 <200mA |
支持 |
支持 |
AGPIO |
保持原设置状态 |
单个 <5mA 总计 <5mA |
支持 |
支持 |
6.1 输出模式简介
GPIO 的输出模式是指将 GPIO 配置为向外界输出高低电平的模式。
6.1.1 输出模式示例
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "gpiodemo"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- sys库是标配
_G.sys = require("sys")
if wdt then
-- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000) -- 初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
end
local gpio_number = 27 -- Air780EPM开发板上的网络指示灯(蓝灯)与GPIO27相连
LED = gpio.setup(gpio_number, 1) -- 设置GPIO27为输出模式
sys.taskInit(function()
-- 开始呼吸灯
local count = 0
while 1 do
-- 呼吸灯程序
LED(1)
log.info("GPIO", "Go Go Go", count, rtos.bsp())
sys.wait(500)--点亮时间 500ms
LED(0)
sys.wait(500)--熄灭时间 500ms
count = count + 1
end
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
6.1.2 示例效果展示
每隔 1 秒亮 0.5 秒。
6.2 输入模式简介
GPIO 的输入模式是指将 GPIO 配置为接收外部信号的模式。
6.2.1 输入模式测试 demo
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "gpio_irq"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- sys库是标配
_G.sys = require("sys")
if wdt then
-- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000) -- 初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
end
-- 配置gpio24为输入模式
-- 配置GPIO27(即开发板上LED灯)为输出模式
-- 请根据实际需求更改gpio编号和上下拉
local inputpin = 24
local ledpin = 27
local input = gpio.setup(inputpin,nil)
local led = gpio.setup(ledpin, 1)
--GPIO24检测到有高低电平输入后,会返回GPIO24当前获取到的电平为高还是低,高返回值为1,低返回值为0
--将这个返回值,传给GPIO27(LED),为0 则GPIO27输出低电平(LED灯灭),为1则输出高电平(LED灯亮)
sys.taskInit(function ()
while true do
led(input())
sys.wait(50)
end
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
6.2.2 硬件连接
本文使用的是 Air780EPM 开发板,需要准备一根杜邦线将开发板上的 GPIO24 引脚在 GND/3.3V 引脚中间切换起来(模块的屏蔽盖也是 GND)。
6.2.3 示例效果展示
6.3 中断模式简介
当 GPIO 检测到电平变化且满足触发条件时,触发中断,CPU 就会暂停当前任务,执行中断回调函数中的内容,当中断回调函数中的内容执行完毕时,再继续执行之前没有执行完的任务。
除了中断回调方式,还有中断计数模式。中断计数模式时,中断时不回调。
6.3.1 中断模式(触发)测试 demo
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "gpio_irq"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- sys库是标配
_G.sys = require("sys")
if wdt then
-- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000) -- 初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
end
-- 配置gpio24为中断模式,上升沿(gpio.RISING)和下降沿(gpio.FALLING)均触发(gpio.BOTH)
-- 请根据实际需求更改gpio编号和触发模式
local gpio_pin = 24
gpio.debounce(gpio_pin, 100)
gpio.setup(gpio_pin, function()
log.info("gpio", gpio_pin, "被触发")
end, gpio.PULLUP, gpio.BOTH)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
6.3.2 硬件链接
将下图中的 GPIO24,在插拔GND之间来回切换,即可在日志中看到打印
6.3.3 示例效果展示
6.3.4 中断模式(计数)简介
中断计数模式时,中断时不回调,中断结束后打印来的中断次数(高低电平变化次数)
6.3.5 硬件链接
此 demo 实现了检测中断触发次数。
硬件上我们需要找到 GPIO24 和 GPIO27(PWM 通道 4,如下图所示),然后将 PWM4 与 GPIO24 连接起来
通过 PWM4 输出中断(高低电平变化的方波),再通过 GPIO24 统计输出的中断数。
6.3.6 示例效果展示
6.4 AGPIO 简介
AGPIO 是一种特殊的通用输入输出接口,全称为 AON GPIO(Always-On GPIO),具有在低功耗模式或休眠模式下保持供电和功能的特性。
当AGPIO作为GPIO中断功能使用时,无法设置为内部上拉或内部下拉。
AGPIO输出驱动能力单管脚<=5mA,但是所有AGPIO驱动电流总和也不能超过5mA。
AGPIO电压一致性没有普通IO电压一致性高,普通IO电压偏差在0.05V以内,AGPIO在0.15V以内。
Air780EPM的AGPIO其他说明及其管脚号参考:GPIO使用必读 - luatos@air780epm - 合宙模组资料中心
6.4.1 AGPIO 测试 demo
-- 本示例对比了普通GPIO和AGPIO的进入休眠模式前后的区别。
-- Luatools需要PROJECT和VERSION这两个信息
PROJECT = "AGPIO_GPIO_testdemo"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- sys库是标配
_G.sys = require("sys")
if wdt then
-- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000) -- 初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
end
local gpio_number = 1 -- 普通GPIO GPIO号为1,休眠后掉电。
local Agpio_number = 27 -- AGPIO GPIO号为27,休眠后可保持电平。
gpio.setup(gpio_number, 1)
gpio.setup(Agpio_number, 1)
sys.taskInit(function()
sys.wait(16000)
-- 关闭USB电源
pm.power(pm.USB, false)
-- 进入低功耗模式
pm.power(pm.WORK_MODE, 3)
sys.wait(10000)
pm.power(pm.USB, true)
pm.power(pm.WORK_MODE, 0)
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
6.4.2 硬件链接
6.4.3 示例效果展示
下方展示图片是裁剪过的,与代码中设置的进入休眠模式的时间不一致,请注意。
GPIO1 进入休眠模式下的管脚电平变化如下:
GPIO27 进入休眠模式下的管脚电平变化如下:
6.5 IO 翻转速度简介
IO 翻转速度即 IO 电平变化一次所需的时间
6.5.1 IO 翻转测试 demo
-- Luatools需要PROJECT和VERSION这两个信息
PROJECT = "gpio2demo"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- sys库是标配
_G.sys = require("sys")
if wdt then
-- 添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000) -- 初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000) -- 3s喂一次狗
end
local test_gpio_number = 27
gpio.setup(test_gpio_number, 0, gpio.PULLUP)
sys.taskInit(function()
sys.wait(100)
while true do
sys.wait(100)
-- 通过GPIO27脚输出输出8组电平变化
-- 0xA9就是输出的电平高低状态,即 10101001
gpio.pulse(test_gpio_number, 0xA9, 8, 0)
log.info("gpio----------->pulse2")
end
end)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
6.5.2 硬件链接
将 GPIO27 链接到示波器上即可
6.5.3 示例效果展示
由下图测试可知,翻转一次所需时间大概 50ns。
七、常见问题
7.1 如果我不需要 UART2 或者不需要 IIC 功能,能将对应引脚复用为 GPIO 吗?
答:可以,但是有限制,详细可以看下面的讲述
7.1.1 IO 复用简介
由于固件特性的存在, LuatOS 的 io 复用默认是固定的, 通过 mcu.iomux 函数可以部分修改映射.
不同模块的外部管脚布局不一样, 但 PAD(paddr)值是一致的, 要对应 “PIN/GPIO 对应表格” 文档, 该文档可以在此处找到
由于芯片的引脚少,存在大量复用的场景,有很多功能是会冲突的,若使用 SIM2, 会占用 4 个 IO(GPIO4/5/6/23)
7.1.2 Air780EPM 复用参考文档
7.2 怎么没看见上拉/下拉输入模式的介绍?
上拉/下拉输入需要接入上拉/下拉电阻和一个按键,在 Air780EPM 开发板上不方便演示,需要用全 IO 板进行演示,下面是上拉下拉输入模式的简介
7.2.1 上拉/下拉模式测试 demo
-- Luatools需要PROJECT和VERSION这两个信息
PROJECT = "gpio2demo"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- sys库是标配
_G.sys = require("sys")
if wdt then
--添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000)--初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end
--配置gpio27为中断下拉模式
--配置gpio24为中断下拉模式
--请根据实际需求更改gpio编号和上下拉
local gpio_pin1 = 7
local gpio_pin2 = 6
-- 按键防抖函数
gpio.debounce(gpio_pin1, 50)
gpio.debounce(gpio_pin2, 50)
-- 设置GPIO24引脚为上拉输入模式
gpio.setup(gpio_pin1, nil, gpio.PULLUP)
-- 设置GPIO27引脚为下拉输入模式
gpio.setup(gpio_pin2, nil, gpio.PULLDOWN)
sys.timerLoopStart(function ()
log.info("GPIO",gpio_pin1,"电平",gpio.get(gpio_pin1))
log.info("GPIO",gpio_pin2,"电平",gpio.get(gpio_pin2))
end,1000)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
7.2.2 硬件链接
上拉输入:连接上拉电阻,当电路未连接时,引脚读取电平是稳定的高电平。在没有外部信号(或外部信号为高阻态)时,通过上拉电阻将输入端拉至一个确定的电平(通常是高电平)
下拉输入:连接下拉电阻,当电路未连接时,引脚读取电平是稳定的低电平。通过将输入引脚连接到地(GND)通过一个下拉电阻,当没有外部信号连接时,下拉电阻将把输入引脚拉低到逻辑低电平。下拉电阻的存在形成了一个电流路径,从输入引脚通过下拉电阻到地,从而保持输入引脚在低电平状态