01 AirGPIO_1000
作者:沈园园
一、AirGPIO_1000概述
AirGPIO_1000 是合宙推出的一款I2C转16路GPIO配件板,其中:
- I2C转16路GPIO(输入输出可配置);
- 关键元器件:TAC9555;
- 适用于Air780系列/Air8000系列/Air8101系列/Air6101系列,尤其适合GPIO较少的Air8101系列/Air6101系列;
二、演示功能概述
AirGPIO_1000是合宙设计生产的一款I2C转16路扩展GPIO的配件板;
本demo演示的核心功能为:
Air8000核心板+AirGPIO_1000配件板,演示I2C扩展16路GPIO功能;
分输出、输入和中断三种应用场景来演示;
三、准备硬件环境


1、Air8000核心板一块
2、TYPE-C USB数据线一根
3、AirGPIO_1000配件板
4、母对母的杜邦线8根
5、Air8000核心板和数据线的硬件接线方式为
- Air8000核心板通过TYPE-C USB口连接TYPE-C USB 数据线,数据线的另外一端连接电脑的USB口;
- 核心板正面的 供电/充电 拨动开关 拨到供电一端;
- 核心板背面的 USB ON/USB OFF 拨动开关 拨到USB ON一端;
6、Air8000核心板和AirGPIO_1000配件板的硬件接线方式为
| Air8000核心板 | AirGPIO_1000配件板 |
|---|---|
| VDD_EXT | 3V3 |
| GND | GND |
| I2C1_SDA | SDA |
| I2C1_SCL | SCL |
| GPIO2 | INT |
- 扩展GPIO输出演示时,无需接线;通过万用表或者示波器检测AirGPIO_1000配件板上的P00电平即可;
- 扩展GPIO输入演示时,将AirGPIO_1000配件板上的P10和P11两个引脚通过杜邦线短接;软件上会将P10配置为输出(第一秒输出低电平,第二秒输出高电平,如此循环输出),将P11配置为输入,通过检测P11引脚输入电平的状态来演示;
- 扩展GPIO中断演示时,将AirGPIO_1000配件板上的P03和P04两个引脚通过杜邦线短接,将AirGPIO_1000配件板上的P13和P14两个引脚通过杜邦线短接;软件上会将P03和P13配置为输出(第一秒输出低电平,第二秒输出高电平,如此循环输出),将P04和P14配置为中断,通过检测中断函数的触发状态来演示。
四、准备软件环境
4.1 软件环境
在开始实践本示例之前,先筹备一下软件环境:
1、烧录工具:Luatools 下载调试工具
2、内核固件:Air8000 最新版本的内核固件
3、脚本文件:https://gitee.com/openLuat/LuatOS/tree/master/module/Air8000/demo/accessory_board/AirGPIO_1000
4、lib脚本文件:使用Luatools烧录时,勾选 添加默认lib 选项,使用默认lib脚本文件
准备好软件环境之后,接下来查看如何烧录项目文件到Air8000核心板,将本篇文章中演示使用的项目文件烧录到Air8000核心板中。
4.2 API 介绍
I2C库:https://docs.openluat.com/osapi/core/i2c/
五、程序结构
AirGPIO_1000/
│── main.lua
│── gpio_app.lua
│── AirGPIO_1000.lua
│── readme.md
5.1 文件说明
main.lua:主程序入口文件。gpio_app.lua:AirGPIO_1000扩展GPIO输出测试,输入测试,GPIO中断测试。AirGPIO_1000.lua:AirGPIO_1000驱动配置文件。
六、代码详解
6.1 main.lua
主程序文件 main.lua 是整个项目的入口点。它负责初始化系统环境。
6.2 gpio_app.lua
AirGPIO_1000扩展GPIO输出测试,输入测试,GPIO中断测试。
6.2.1 GPIO输出测试
--AirGPIO_1000扩展GPIO输出测试
--P00每隔一秒切换输出一次高低电平,可以通过示波器或者万用表测量AirGPIO_1000上P00引脚电平
local function gpio_output_task_func()
air_gpio.setup(0x00, 0)
while true do
air_gpio.set(0x00, 0)
sys.wait(1000)
air_gpio.set(0x00, 1)
sys.wait(1000)
end
end
6.2.2 GPIO输入测试
--AirGPIO_1000扩展GPIO输入测试
--P10配置为输出模式,每隔一秒切换输出一次高低电平
--P11配置为输入模式,每隔一秒调用get接口读取一次输入的电平
--将P10和P11两个引脚短接
local function gpio_input_task_func()
air_gpio.setup(0x10, 0)
air_gpio.setup(0x11)
while true do
air_gpio.set(0x10, 0)
sys.wait(1000)
log.info("air_gpio.get(0x11)", air_gpio.get(0x11))
air_gpio.set(0x10, 1)
sys.wait(1000)
log.info("air_gpio.get(0x11)", air_gpio.get(0x11))
end
end
6.2.3 GPIO中断测试
--AirGPIO_1000扩展GPIO中断测试
--P03配置为输出模式,每隔一秒切换输出一次高低电平
--P04配置为中断模式,并且配置中断处理函数P04_int_cbfunc
--将P03和P04两个引脚短接
--P13配置为输出模式,每隔一秒切换输出一次高低电平
--P14配置为中断模式,并且配置中断处理函数P14_int_cbfunc
--将P13和P14两个引脚短接
local function gpio_int_task_func()
air_gpio.setup(0x03, 0)
air_gpio.setup(0x04, P04_int_cbfunc)
air_gpio.setup(0x13, 0)
air_gpio.setup(0x14, P14_int_cbfunc)
while true do
air_gpio.set(0x03, 0)
air_gpio.set(0x13, 0)
sys.wait(1000)
air_gpio.set(0x03, 1)
air_gpio.set(0x13, 1)
sys.wait(1000)
end
end
6.2.4 初始化Air8000和AirGPIO_1000之间的通信参数
--初始化Air8000和AirGPIO_1000之间的通信参数
--使用Air8000的I2C0
--使用Air8000的GPIO2做为中断引脚
--Air8000核心板和AirGPIO_1000配件板的接线方式如下
--Air8000核心板 AirGPIO_1000配件板
--VDD_EXT(3.3V)-----------------3V3
-- GND-----------------GND
-- I2C1_SDA-----------------SDA
-- I2C1_SCL-----------------SCL
-- GPIO2-----------------INT
air_gpio.init(1, 2)
6.3 AirGPIO_1000.lua
AirGPIO_1000驱动配置文件。
6.3.1 寄存器配置和读写
-- 从机硬件上有三个引脚A0 A1 A2可以配置I2C从设备的地址
-- 当A0 A1 A2都接地时的从设备基地址为(0x40 >> 1)
-- A0 A1 A2有0到7一共八种排序组合,基地址+0/1/2/3/4/5/6/7即为八种从设备的地址
-- AirGPIO_1000默认A0 A1 A2都接地,所以AirGPIO_1000的从设备地址默认也为(0x40 >> 1)
local SALVE_ADDRESS_HIGH_4BIT = (0x40 >> 1)
-- 寄存器地址
local REG_INPUT_PORT_0 = 0x00 -- 输入端口0
local REG_INPUT_PORT_1 = 0x01 -- 输入端口1
local REG_OUTPUT_PORT_0 = 0x02 -- 输出端口0
local REG_OUTPUT_PORT_1 = 0x03 -- 输出端口1
local REG_POL_INV_0 = 0x04 -- 极性反转端口0
local REG_POL_INV_1 = 0x05 -- 极性反转端口1
local REG_CONFIG_0 = 0x06 -- 配置端口0
local REG_CONFIG_1 = 0x07 -- 配置端口1
-- 写入AirGPIO_1000的寄存器
--reg:number类型;
-- 表示AirGPIO_1000上的寄存器地址;
-- 取值范围:0x00到0x07,参考本文件上方的寄存器地址列表;
-- 必须传入,不允许为空;
--value:number类型;
-- 表示要写入到AirGPIO_1000寄存器中的数据;
-- 取值范围:0x00到0xFF,1个字节的长度;
-- 必须传入,不允许为空;
--返回值:成功返回true,失败返回false
local function write_register(reg, value)
local data = {reg, value}
local result = i2c.send(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, data)
return result
end
-- 读取AirGPIO_1000的寄存器
--reg:number类型;
-- 表示AirGPIO_1000上的寄存器地址;
-- 取值范围:0x00到0x07,参考本文件上方的寄存器地址列表;
-- 必须传入,不允许为空;
--返回值:成功返回1个字节的number类型,失败返回nil
local function read_register(reg)
i2c.send(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, reg)
local data = i2c.recv(AirGPIO_1000.i2c_id, AirGPIO_1000.slave_address, 1)
if data and #data == 1 then
return string.byte(data, 1)
end
return nil
end
6.3.2 主机上的中断引脚处理函数
--主机上的中断引脚处理函数
local function gpio_int_callback()
log.info("gpio_int_callback")
--在中断处理函数中不能直接执行耗时较长的动作
--所以在此处publish一个"AirGPIO_1000_INT"消息
--在其他位置订阅这个消息,进行异步处理
--异步处理这个消息的函数可以直接执行耗时较长的动作
sys.publish("AirGPIO_1000_INT")
end
--遍历用户扩展GPIO中断函数表,进行处理
local function user_gpio_int_callback()
if AirGPIO_1000.ints then
--遍历用户扩展GPIO中断函数表
for k,v in pairs(AirGPIO_1000.ints) do
if v then
--读取扩展GPIO的输入电平
local cur_level = AirGPIO_1000.get(k)
--如果输入电平和上一次输入电平不一致
--则执行用户扩展GPIO中断函数
if v.old_level~=cur_level then
v.old_level = cur_level
if v.cb_func then v.cb_func(k, cur_level) end
end
end
end
end
end
--订阅"AirGPIO_1000_INT"消息的处理函数user_gpio_int_callback
--当其他位置publish "AirGPIO_1000_INT"消息时,会执行user_gpio_int_callback
sys.subscribe("AirGPIO_1000_INT", user_gpio_int_callback)
6.3.3 配置主机和AirGPIO_1000之间的通信参数
--配置主机和AirGPIO_1000之间的通信参数;
--i2c_id:number类型;
-- 主机使用的I2C ID,用来控制AirGPIO_1000;
-- 取值范围:仅支持0和1;
-- 如果没有传入此参数,则默认为0;
--int_id:number类型;
-- 主机使用的中断引脚GPIO ID,和AirGPIO_1000上的INT引脚相连;
-- AirGPIO_1000可以扩展出来16个GPIO,这些GPIO支持配置为输入;
-- AirGPIO_1000上的任意一个输入GPIO的状态发生上升沿或者下降沿变化时,会通过INT引脚通知到主机的int_id中断引脚;
-- 此时主机可以通过I2C接口立即读取AirGPIO_1000上配置为输入模式的扩展GPIO的电平状态,从而判断是哪些扩展GPIO的输入电平发生了变化;
-- 如果没有传入此参数,则默认为空,表示不使用中断通知功能;
--返回值:成功返回true,失败返回false
function AirGPIO_1000.init(i2c_id, gpio_int_id)
--检查参数的合法性
if not (i2c_id == 0 or i2c_id == 1) then
log.error("AirGPIO_1000.init", "invalid i2c_id", i2c_id)
return false
end
AirGPIO_1000.i2c_id = i2c_id
AirGPIO_1000.gpio_int_id = gpio_int_id
--初始化I2C
if i2c.setup(i2c_id, i2c.FAST) ~= 1 then
log.error("AirGPIO_1000.init", "i2c.setup error", i2c_id)
return false
end
--自动识别从设备地址
--AirGPIO_1000上使用的TCA9555芯片有三个引脚,A2 A1 A0,可以配置三个bit的I2C从设备地址
--从 0 0 0 到 1 1 1,也就是十进制的0到7,一共可以配置8种;
--依次读取这8个从设备地址上的一个寄存器地址数据
--如果返回应答数据,则从设备地址自动识别成功
for i=0,7 do
i2c.send(i2c_id, SALVE_ADDRESS_HIGH_4BIT+i, REG_INPUT_PORT_0)
local data = i2c.recv(i2c_id, SALVE_ADDRESS_HIGH_4BIT+i, 1)
if data~=nil then
AirGPIO_1000.slave_address = SALVE_ADDRESS_HIGH_4BIT+i
log.error("AirGPIO_1000.init", "slave_address", SALVE_ADDRESS_HIGH_4BIT+i, data:byte())
break
end
end
--自动识别从设备地址失败
if not AirGPIO_1000.slave_address then
log.error("AirGPIO_1000.init", "slave_address unknown")
i2c.close(i2c_id)
return false
end
--配置主机上的中断GPIO,用来实时检测从机上扩展GPIO的输入电平变化
if gpio_int_id then
gpio.setup(gpio_int_id, gpio_int_callback, gpio.PULLUP, gpio.FALLING)
end
return true
end
6.3.4 关闭主机和AirGPIO_1000之间的通信
--关闭主机和AirGPIO_1000之间的通信;
--返回值:成功返回true,失败返回false
function AirGPIO_1000.deinit()
--关闭主机I2C
if AirGPIO_1000.i2c_id then
i2c.close(AirGPIO_1000.i2c_id)
AirGPIO_1000.i2c_id = nil
AirGPIO_1000.slave_address = nil
end
--关闭主机中断GPIO
if AirGPIO_1000.gpio_int_id then
gpio.close(AirGPIO_1000.gpio_int_id)
AirGPIO_1000.gpio_int_id = nil
end
--清空用户注册的扩展GPIO中断处理表
if type(AirGPIO_1000.ints)=="table" then
for k,v in pairs(AirGPIO_1000.ints) do
AirGPIO_1000.ints[k] = nil
end
AirGPIO_1000.ints = nil
end
end
6.3.5 配置AirGPIO_1000上的扩展GPIO管脚功能
--[[
配置AirGPIO_1000上的扩展GPIO管脚功能;
支持配置为输出,输入和中断三种模式;
@api AirGPIO_1000.setup(gpio_id, gpio_mode)
@number
gpio_id
表示AirGPIO_1000上的扩展GPIO ID;
取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
必须传入,不允许为空或者nil;
@number or function or nil or 空
gpio_mode
number类型时,表示输出模式,取值范围为0和1,0表示默认输出低电平,1表示默认输出高电平;
nil或者空类型时,表示输入模式;
function类型时,表示中断模式,此function为中断回调函数,函数的定义格式如下:
function cb_func(id, level)
--id:表示触发中断的AirGPIO_1000上的扩展GPIO ID,取值范围为0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
--level:触发中断后,某一时刻,扩展GPIO输入的电平状态,高电平为1, 低电平为0;并不是指触发中断的电平状态;
end
@return bool
成功返回true,失败返回false
@usage
-- GPIO ID 0x00配置为输出模式,默认输出低电平
AirGPIO_1000.setup(0x00, 0)
-- GPIO ID 0x11配置为输入模式
AirGPIO_1000.setup(0x11)
--P04引脚中断处理函数
--id:0x04
--level:触发中断后,某一时刻,扩展GPIO输入的电平状态,高电平为1, 低电平为0
local function P04_int_cbfunc(id, level)
log.info("P04_int_cbfunc", id, level)
end
-- GPIO ID 0x04配置为中断模式,中断处理函数为P04_int_cbfunc
AirGPIO_1000.setup(0x04, P04_int_cbfunc)
]]
function AirGPIO_1000.setup(gpio_id, gpio_mode)
--检查参数的合法性
if not check_gpio_id_valid(gpio_id) then
log.error("AirGPIO_1000.setup", "invalid gpio_id", gpio_id)
return false
end
if not (gpio_mode==0 or gpio_mode==1 or gpio_mode==nil or type(gpio_mode)=="function") then
log.error("AirGPIO_1000.setup", "invalid gpio_mode", type(gpio_mode), gpio_mode)
return false
end
log.info("AirGPIO_1000.setup", "enter", gpio_id, type(gpio_mode), gpio_mode)
--根据扩展GPIO ID识别当前扩展GPIO使用的配置寄存器地址
--0x0x开头的ID为REG_CONFIG_0,0x01开头的ID为REG_CONFIG_1
local reg_addr = ((gpio_id>>4) == 0) and REG_CONFIG_0 or REG_CONFIG_1
--读取从机中输出寄存器当前的值
local reg_data = read_register(reg_addr)
if reg_data==nil then
log.error("AirGPIO_1000.setup", "read config register error", reg_addr)
return false
end
local mask = 1<<(gpio_id&0x0F)
local value
--GPIO配置为输出模式
if gpio_mode==0 or gpio_mode==1 then
value = reg_data & (~mask)
--GPIO配置为输入模式
elseif gpio_mode==nil or type(gpio_mode)=="function" then
value = reg_data | mask
end
--如果寄存器新值和旧值相比,发生变化
--写新值到从机的配置寄存器中
if reg_data~=value then
if not write_register(reg_addr, value) then
log.error("AirGPIO_1000.setup", "config write error", reg_addr, value)
return false
end
end
log.info("AirGPIO_1000.setup", "config", reg_addr, reg_data, value)
--如果是中断模式,并且用户注册了中断处理函数
if type(gpio_mode)=="function" then
if AirGPIO_1000.ints==nil then
AirGPIO_1000.ints = {}
end
if AirGPIO_1000.ints[gpio_id]==nil then
AirGPIO_1000.ints[gpio_id] = {}
end
--存储中断处理函数
AirGPIO_1000.ints[gpio_id].cb_func = gpio_mode
--读取当前时刻GPIO的输入电平状态
AirGPIO_1000.ints[gpio_id].old_level = AirGPIO_1000.get(gpio_id)
end
--如果配置的是输入模式或者中断模式,可以直接返回了
if gpio_mode~=0 and gpio_mode~=1 then return true end
--如果配置的输出模式,初始化输出的电平为gpio_mode
if not AirGPIO_1000.set(gpio_id, gpio_mode) then
log.error("AirGPIO_1000.setup", "output set error")
return false
end
log.info("AirGPIO_1000.setup", "output", reg_addr, reg_data, value)
return true
end
--设置AirGPIO_1000上配置为输出模式的扩展GPIO的输出电平
--gpio_id:number类型;
-- 表示AirGPIO_1000上的扩展GPIO ID;
-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
-- 必须传入,不允许为空;
--output_level:number类型;
-- 表示配置为输出模式的扩展GPIO对外输出的电平;
-- 取值范围:0和1,0表示输出低电平,1表示输出高电平;
-- 必须传入,不允许为空;
--返回值:成功返回true,失败返回false
function AirGPIO_1000.set(gpio_id, output_level)
--检查参数的合法性
if not check_gpio_id_valid(gpio_id) then
log.error("AirGPIO_1000.set", "invalid gpio_id", gpio_id)
return false
end
if not (output_level==0 or output_level==1) then
log.error("AirGPIO_1000.set", "invalid output_level", type(output_level), output_level)
return false
end
log.info("AirGPIO_1000.set", "enter", gpio_id, output_level)
--根据扩展GPIO ID识别当前扩展GPIO使用的输出寄存器地址
--0x0x开头的ID为REG_OUTPUT_PORT_0,0x01开头的ID为REG_OUTPUT_PORT_1
local reg_addr = ((gpio_id>>4) == 0) and REG_OUTPUT_PORT_0 or REG_OUTPUT_PORT_1
--读取从机中输出寄存器当前的值
local reg_data = read_register(reg_addr)
if reg_data==nil then
log.error("AirGPIO_1000.set", "read output register error", reg_addr)
return false
end
local mask = 1<<(gpio_id&0x0F)
local value
--输出低电平
if output_level==0 then
value = reg_data & (~mask)
--输出高电平
elseif output_level==1 then
value = reg_data | mask
end
--如果寄存器新值和旧值相比,发生变化
--写新值到从机的输出寄存器中
if reg_data~=value then
if not write_register(reg_addr, value) then
log.error("AirGPIO_1000.set", "output write error", reg_addr, value)
return false
end
end
log.info("AirGPIO_1000.set", "output", reg_addr, reg_data, value)
return true
end
--读取AirGPIO_1000上配置为输入或者中断模式的扩展GPIO的输入电平
--gpio_id:number类型;
-- 表示AirGPIO_1000上的扩展GPIO ID;
-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
-- 必须传入,不允许为空;
--返回值:number类型,表示输入的电平,0表示低电平,1表示高电平;如果读取失败,返回false
function AirGPIO_1000.get(gpio_id)
--检查参数的合法性
if not check_gpio_id_valid(gpio_id) then
log.error("AirGPIO_1000.get", "invalid gpio_id", gpio_id)
return false
end
--根据扩展GPIO ID识别当前扩展GPIO使用的输入寄存器地址
--0x0x开头的ID为REG_INPUT_PORT_0,0x01开头的ID为REG_INPUT_PORT_1
local reg_addr = ((gpio_id>>4) == 0) and REG_INPUT_PORT_0 or REG_INPUT_PORT_1
--读取从机中输入寄存器当前的值
local value = read_register(reg_addr)
if not value then
log.error("AirGPIO_1000.get", "read_register error", reg_addr)
return false
end
--返回输入寄存器的值和GPIO对应的bit位的值
return ((value>>(gpio_id&0x0F)) & 0x01)
end
6.6.6 关闭AirGPIO_1000上的扩展GPIO功能
--关闭AirGPIO_1000上的扩展GPIO功能
--实际上是恢复为默认状态(配置为输入)
--gpio_id:number类型;
-- 表示AirGPIO_1000上的扩展GPIO ID;
-- 取值范围:0x00到0x07,0x10到0x17,一共16种,分别对应16个扩展GPIO引脚;
-- 必须传入,不允许为空;
--返回值:成功返回true,失败返回false
function AirGPIO_1000.close(gpio_id)
local result = AirGPIO_1000.setup(gpio_id)
if not result then
log.error("AirGPIO_1000.close", "error", gpio_id)
end
return result
end
七、运行结果展示
(1) 通过万用表或者示波器检测AirGPIO_1000配件板上的P00电平,持续1秒输出0V的低电平,持续1秒输出3.3V的高电平,循环输出,表示GPIO输出测试正常;
(2) 通过观察Luatools的运行日志,首先打印 air_gpio.get(0x11) 0, 再隔一秒打印 air_gpio.get(0x11) 1,再隔一秒打印 air_gpio.get(0x11) 0,如此循环输出,表示GPIO输入测试正常;
(3) 通过观察Luatools的运行日志,首先打印 P04_int_cbfunc 4 0 P14_int_cbfunc 20 0, 再隔一秒打印 P04_int_cbfunc 4 1 P14_int_cbfunc 20 1,再隔一秒打印 P04_int_cbfunc 4 0 P14_int_cbfunc 20 0,如此循环输出,表示GPIO中断测试正常;
出现类似于下面的日志,就表示运行成功:
[2025-09-24 16:15:09.221][000000054.571] I/user.air_gpio.get(0x11) 1
[2025-09-24 16:15:09.223][000000054.572] I/user.AirGPIO_1000.set enter 16 0
[2025-09-24 16:15:09.223][000000054.573] I/user.AirGPIO_1000.set output 3 255 254
[2025-09-24 16:15:09.228][000000054.573] I/user.gpio_int_callback
[2025-09-24 16:15:09.290][000000054.635] I/user.AirGPIO_1000.set enter 3 0
[2025-09-24 16:15:09.290][000000054.636] I/user.AirGPIO_1000.set output 2 254 246
[2025-09-24 16:15:09.295][000000054.636] I/user.AirGPIO_1000.set enter 19 0
[2025-09-24 16:15:09.300][000000054.637] I/user.AirGPIO_1000.set output 3 254 246
[2025-09-24 16:15:09.300][000000054.638] I/user.gpio_int_callback
[2025-09-24 16:15:09.305][000000054.639] I/user.P04_int_cbfunc 4 0
[2025-09-24 16:15:09.310][000000054.640] I/user.P14_int_cbfunc 20 0
[2025-09-24 16:15:10.184][000000055.532] I/user.AirGPIO_1000.set enter 0 1
[2025-09-24 16:15:10.187][000000055.533] I/user.AirGPIO_1000.set output 2 246 247
[2025-09-24 16:15:10.228][000000055.573] I/user.air_gpio.get(0x11) 0
[2025-09-24 16:15:10.228][000000055.574] I/user.AirGPIO_1000.set enter 16 1
[2025-09-24 16:15:10.233][000000055.575] I/user.AirGPIO_1000.set output 3 246 247
[2025-09-24 16:15:10.238][000000055.575] I/user.gpio_int_callback
[2025-09-24 16:15:10.288][000000055.638] I/user.AirGPIO_1000.set enter 3 1
[2025-09-24 16:15:10.288][000000055.639] I/user.AirGPIO_1000.set output 2 247 255
[2025-09-24 16:15:10.293][000000055.639] I/user.AirGPIO_1000.set enter 19 1
[2025-09-24 16:15:10.298][000000055.640] I/user.AirGPIO_1000.set output 3 247 255
[2025-09-24 16:15:10.298][000000055.641] I/user.gpio_int_callback
[2025-09-24 16:15:10.305][000000055.642] I/user.P04_int_cbfunc 4 1
[2025-09-24 16:15:10.308][000000055.643] I/user.P14_int_cbfunc 20 1
[2025-09-24 16:15:11.190][000000056.534] I/user.AirGPIO_1000.set enter 0 0
[2025-09-24 16:15:11.200][000000056.535] I/user.AirGPIO_1000.set output 2 255 254
八、总结
通过本章内容的学习,你可以学习到Air8000核心板+AirGPIO_1000配件板,通过I2C转16路GPIO功能(输出、输入和中断)的应用。