跳转至

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复用表

!!!一定要仔细阅读这里的GPIO使用注意事项!!!

例:如图所示的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 输出模式示例

输出模式测试 demo

-- 配置外接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 秒。

air780egh_gpioout

6.2 输入模式简介

GPIO 的输入模式是指将 GPIO 配置为接收外部信号的模式。

6.2.1 输入模式测试 demo

输入模式测试 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指示灯点亮

air780egh_gpioin

6.3 中断模式简介

当 GPIO 检测到电平变化且满足触发条件时,触发中断,CPU 就会暂停当前任务,执行中断回调函数中的内容,当中断回调函数中的内容执行完毕时,再继续执行之前没有执行完的任务。

除了中断回调方式,还有中断计数模式。中断计数模式时,中断时不回调。

6.3.1 中断模式(触发)测试 demo

测试 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 示例效果展示

air780egh_gpio_irq

6.3.4 中断模式(计数)简介

中断计数模式时,中断时不回调,中断结束后打印来的中断次数(高低电平变化次数)

6.3.5 中断模式(计数)测试 demo

示例 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 统计输出的中断数。

air780egh_gpio_count_hw

6.3.7 示例效果展示

air780egh_gpio_count

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 测试 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 硬件链接

PixPin_2025-03-19_12-49-14

VBat连接合宙IOT power或Air9000的"+",供电配置输入3.8V,GND接合宙IOT power或Air9000的"-", 测量工作电流的同时,通过万用表测量GPIO01和GPIO27的电平

6.4.3 示例效果展示

下方展示图片是裁剪过的,与代码中设置的进入休眠模式的时间不一致,请注意。

GPIO1(普通GPIO) 进入休眠模式下的管脚电平变化如下:

air780egh_lowpower_gpio

进入低功耗模式,GPIO01电平变化到0V

GPIO27(AGPIO) 进入休眠模式下的管脚电平变化如下:

air780egh_lowpower_agpio

进入低功耗模式,GPIO27电平保持

6.5 IO 翻转速度简介

IO 翻转速度即 IO 电平变化一次所需的时间

6.5.1 IO 翻转测试 demo

测试 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波形

air780egh_gpio_toggle_la

air780egh_gpio_toggle

6.6 上拉/下拉模式测试

上拉/下拉输入测试,需要接入上拉/下拉电阻和一个按键

6.6.1 上拉/下拉模式测试demo

测试 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 设计说明