GPIO
一、GPIO 概述
GPIO 是通用型输入输出的简称,一个 GPIO 引脚可以用于输入、输出或其他特殊功能。
二、演示功能概述
本文将介绍 Air780EGH GPIO 的输入输出、中断、AGPIO等demo的讲解与效果演示。
三、准备硬件环境
3.1 Air780EGH 核心板V1.0
四、软件环境
在开始实践本示例之前,先筹备一下软件环境:
1. Luatools工具;
2. 内核固件文件(底层core固件文件):LuatOS-SoC_V2007_Air780EGH;参考项目使用的内核固件;
3. luatos需要的脚本和资源文件
脚本和资源文件点我浏览所有文件
lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件;
准备好软件环境之后,接下来查看如何烧录项目文件到Air780EGH开发板,将本篇文章中演示使用的项目文件烧录到Air780EGH 核心板中。
五、GPIO 软硬件参考
5.1 API 接口介绍
本教程使用 api 接口为:
https://docs.openluat.com/osapi/core/gpio/
5.2 GPIO 硬件设计
5.2.1 GPIO 复用表
以下链接获取IO复用表
例:如图所示的Air780egh的部分IO复用表
GPIO编号需要根据模块引脚号和表格中的ALT FUNC来确定;
配置IO复用功能的方法参考 LuatIO配置工具的使用
例如:管脚80的GPIO4,管脚81的GPIO5,对应复用配置ALT FUNC0;管脚97的GPIO16功能则对应复用配置ALT FUN4;可以修改配置如下所示:
保存json配置文件为pins_Air780EGH.json, 其中文件中module对应键值修改为使用的型号
注意,本文档后续章节的demo示例均为GPIO的相关测试,默认配置配合api调用可以满足测试要求,所以GPIO demo测试未烧录pins_Air780EGH.json。
六、GPIO 简介
认识模块 GPIO 管脚:Air780EPM 模块的 GPIO 与其他 MCU 类的芯片一样,也可以配置为输入/输出/上拉/下拉/中断等状态,只有在硬件设计手册上注明带 GPIO 功能的管脚才能作为 GPIO 使用。
Air780EPM 的 GPIO 口根据特性分为三种类型:普通 GPIO、AGPIO、Wakeup IO。
下面是普通 GPIO 和 AGPIO 的区别
休眠后状态 |
驱动能力 |
输入输出 |
中断 |
模块休眠唤醒 |
|
---|---|---|---|---|---|
普通 GPIO |
掉电且伴随网络状态可能会有不定周期的波动 |
单个 <10mA 总计 <200mA |
支持 |
支持 |
不支持 |
AGPIO |
保持原设置状态 |
单个 <5mA 总计 <5mA |
支持 |
支持 |
不支持 |
Wakeup IO |
保持原设置状态 |
单个 <30uA |
仅支持输入 |
支持 |
支持 |
6.1 输出模式简介
GPIO 的输出模式是指将 GPIO 配置为向外界输出高低电平的模式。
6.1.1 输出模式示例
-- 配置外接LED灯的GPIO端口
local led_io_number = 27
function test_gpio_output_func()
-- 定义运行计数器
local count = 0
-- 配置GPIO为输出模式
gpio.setup(led_io_number, 1)
while 1 do
-- 打印运行计数
log.info("GPIO", "Go Go Go", count, rtos.bsp())
-- 点亮500ms
gpio.set(led_io_number, 1)
sys.wait(500)
-- 熄灭500ms
gpio.set(led_io_number, 0)
sys.wait(500)
-- 运行计数器累计加1
count = count + 1
end
end
--创建并且启动一个task
--运行这个task的主函数 test_gpio_output_func
sys.taskInit(test_gpio_output_func)
6.1.2 示例效果展示
每隔 1 秒亮 0.5 秒。
6.2 输入模式简介
GPIO 的输入模式是指将 GPIO 配置为接收外部信号的模式。
6.2.1 输入模式测试 demo
-- 配置外接LED灯的GPIO端口
local led_io_number = 27
-- 配置输入检测的GPIO端口
local input_io_numble = 24
function test_gpio_input_func()
local input_level
-- 配置LED GPIO为推挽输出模式,第二参数1表示初始为输出高电平
gpio.setup(led_io_number, 1)
-- 配置输入检测的GPIO为输入模式, 第二参数nil表示输入模式,第三参数nil表示浮空输入(未检测到电平时 电平状态不确定)
gpio.setup(input_io_numble, nil, nil)
-- 配置输入IO防抖动参数:50ms
gpio.debounce(input_io_numble, 50)
while 1 do
-- 获取IO电平,并打印
input_level = gpio.get(input_io_numble)
log.info("GPIO", "input level", input_level)
-- 根据获取的电平来设置LED
gpio.set(led_io_number, input_level)
-- 延时500ms,循环上面的流程
sys.wait(500)
end
end
--创建并且启动一个task
--运行这个task的主函数 test_gpio_input_func
sys.taskInit(test_gpio_input_func)
6.2.2 硬件连接
本文使用的是 Air780EGH 核心板,GPIO27 外接LED指示灯,需要准备一根杜邦线将开发板上的 GPIO24 引脚在 GND/3.3V 引脚中间切换起来(模块的屏蔽盖也是 GND)。
6.2.3 示例效果展示
GPIO24 连接GND时 led指示灯熄灭,连接3.3V时 led指示灯点亮
6.3 中断模式简介
当 GPIO 检测到电平变化且满足触发条件时,触发中断,CPU 就会暂停当前任务,执行中断回调函数中的内容,当中断回调函数中的内容执行完毕时,再继续执行之前没有执行完的任务。
除了中断回调方式,还有中断计数模式。中断计数模式时,中断时不回调。
6.3.1 中断模式(触发)测试 demo
-- 配置GPIO中断检测端口
local irq_io_number = 24
function io_irq_handler(level, io_number)
log.info("gpio", io_number, "被触发", "level=", level)
end
function test_gpio_irq_func()
-- 配置GPIO为中断模式, 第二参数为function表示中断模式,
-- 第三参数表示内部上拉输入,第四参数表示下降沿触发中断
gpio.setup(irq_io_number, io_irq_handler, gpio.PULLUP, gpio.FALLING)
-- 配置输入IO防抖动参数:100ms
gpio.debounce(irq_io_number, 100)
end
--创建并且启动一个task
--运行这个task的主函数 test_gpio_irq_func
sys.taskInit(test_gpio_irq_func)
6.3.2 硬件链接
使用Air780EGH 核心板GPIO24通过杜邦线,可以在插拔GND之间来回切换即可在日志中看到对应的打印指示。
6.3.3 示例效果展示
6.3.4 中断模式(计数)简介
中断计数模式时,中断时不回调,中断结束后打印来的中断次数(高低电平变化次数)
6.3.5 中断模式(计数)测试 demo
-- 配置GPIO中断检测端口
local irq_io_number = 24
function test_gpio_irq_count_func()
-- PIN引脚16,配置PWM4输出波形,并作为信号源将其通过杜邦线连接到PIN引脚20(GPIO24)
-- 第一参数表示PWM channel4,第二参数表示频率为1000Hz,第三参数表示占空比为50%
pwm.open(4,1000,50)
-- 配置GPIO为中断计数模式, 第二参数为gpio.count表示中断计数模式,
gpio.setup(irq_io_number, gpio.count)
--每隔1S统计一次中断触发的次数
while true do
sys.wait(1000)
log.info("irq cnt", gpio.count(irq_io_number))
end
end
--创建并且启动一个task
--运行这个task的主函数 test_gpio_irq_count_func
sys.taskInit(test_gpio_irq_count_func)
6.3.6 硬件链接
此 demo 实现了检测中断触发次数。
硬件上我们需要找到 GPIO24 和 GPIO27(PWM 通道 4,如下图所示),然后将 PWM4 与 GPIO24 连接起来
通过 PWM4 输出中断(高低电平变化的方波),再通过 GPIO24 统计输出的中断数。
6.3.7 示例效果展示
6.4 AGPIO 简介
AGPIO 是一种特殊的通用输入输出接口,全称为 AON GPIO(Always-On GPIO),具有在低功耗模式或休眠模式下保持供电和功能的特性。
当AGPIO作为GPIO中断功能使用时,无法设置为内部上拉或内部下拉。
AGPIO输出驱动能力单管脚<=5mA,但是所有AGPIO驱动电流总和也不能超过5mA。
AGPIO电压一致性没有普通IO电压一致性高,普通IO电压偏差在0.05V以内,AGPIO在0.15V以内。
Air780EGH的AGPIO其他说明及其管脚号参考:GPIO使用必读 - luatos@air780egh - 合宙模组资料中心
6.4.1 AGPIO 测试 demo
-- 定义AGPIO端口: GPIO27
local agpio_number = 27
-- 定义普通GPIO端口: GPIO01
local normal_gpio_number = 1
function test_agpio_func()
-- 配置AGPIO为输出模式,初始输出高电平
gpio.setup(agpio_number, 1)
-- 配置普通GPIO为输出模式,初始输出高电平
gpio.setup(normal_gpio_number, 1)
sys.wait(16000)
-- 上电模式工作运行16s后关闭USB电源
pm.power(pm.USB, false)
-- 进入低功耗模式
pm.power(pm.WORK_MODE, 3)
-- 之后按rst键重新复位系统测试
end
--创建并且启动一个task
--运行这个task的主函数 test_agpio_func
sys.taskInit(test_agpio_func)
6.4.2 硬件链接
VBat连接合宙IOT power或Air9000的"+",供电配置输入3.8V,GND接合宙IOT power或Air9000的"-", 测量工作电流的同时,通过万用表测量GPIO01和GPIO27的电平
6.4.3 示例效果展示
下方展示图片是裁剪过的,与代码中设置的进入休眠模式的时间不一致,请注意。
GPIO1(普通GPIO) 进入休眠模式下的管脚电平变化如下:
进入低功耗模式,GPIO01电平变化到0V
GPIO27(AGPIO) 进入休眠模式下的管脚电平变化如下:
进入低功耗模式,GPIO27电平保持
6.5 IO 翻转速度简介
IO 翻转速度即 IO 电平变化一次所需的时间
6.5.1 IO 翻转测试 demo
-- 配置输出pulse的GPIO端口
local pulse_io_number = 27
function test_gpio_toggle_func()
-- 配置GPIO为输出模式,初始输出低电平
gpio.setup(pulse_io_number, 0)
while 1 do
-- 通过测试的GPIO27 输出指定的脉冲信号
-- 结合脉冲高低变化可以评估IO翻转时间,使用示波器或逻辑分析仪来测量电平翻转的时间
-- 第三参数表示输出8组电平变化,每组1或0表示高和低电平
-- 第二参数0xA9就是输出的电平高低状态,即 10101001
-- 第四参数表示每个电平的延时保持时间,0代表无延时
gpio.pulse(pulse_io_number, 0xA9, 8, 0)
-- 打印运行打印信息
log.info("gpio----------->pulse")
sys.wait(100)
end
end
--创建并且启动一个task
--运行这个task的主函数 test_gpio_toggle_func
sys.taskInit(test_gpio_toggle_func)
6.5.2 硬件链接
将 GPIO27 接到逻辑分析仪channel 6上,启动采集信号
6.5.3 示例效果展示
由下图测试可知,翻转一次所需时间大概 40-50ns,输出10101001波形
6.6 上拉/下拉模式测试
上拉/下拉输入测试,需要接入上拉/下拉电阻和一个按键
6.6.1 上拉/下拉模式测试demo
-- 定义输入上拉模式的端口GPIO7
local gpio_pullup_number = 7
-- 定义输入下拉模式的端口GPIO27
local gpio_pulldown_number = 27
function test_gpio_pullupdown_func()
-- 设置GPIO输入上拉模式
gpio.setup(gpio_pullup_number, nil, gpio.PULLUP)
-- 配置输入检测防抖50ms
gpio.debounce(gpio_pullup_number, 50)
-- 设置GPIO输入下拉模式
gpio.setup(gpio_pulldown_number, nil, gpio.PULLDOWN)
-- 配置输入检测防抖50ms
gpio.debounce(gpio_pulldown_number, 50)
while 1 do
-- 打印获取端口当前的电平状态
log.info("GPIO",gpio_pullup_number,"电平",gpio.get(gpio_pullup_number))
log.info("GPIO",gpio_pulldown_number,"电平",gpio.get(gpio_pulldown_number))
sys.wait(1000)
end
end
--创建并且启动一个task
--运行这个task的主函数 test_gpio_pullupdown_func
sys.taskInit(test_gpio_pullupdown_func)
7.2.2 硬件链接
GPIO07上拉输入:连接上拉电阻,当电路未连接时,引脚读取电平是稳定的高电平。在没有外部信号(或外部信号为高阻态)时,通过上拉电阻将输入端拉至一个确定的电平(通常是高电平)
GPIO27下拉输入:连接下拉电阻,当电路未连接时,引脚读取电平是稳定的低电平。通过将输入引脚连接到地(GND)通过一个下拉电阻,当没有外部信号连接时,下拉电阻将把输入引脚拉低到逻辑低电平。下拉电阻的存在形成了一个电流路径,从输入引脚通过下拉电阻到地,从而保持输入引脚在低电平状态
7.2.3 示例效果展示
七、常见问题
7.1 如果我不需要 UART2 或者不需要 IIC 功能,能将对应引脚复用为 GPIO 吗?
答:可以,但是有限制,需要通过luatio工具来配置支持的复用IO功能,生成并烧录对应的pins_Air780EGH.json文件,详细可以参考 Air780EGH GPIO 设计说明