exs_pcf8574 扩展库
作者:沈园园 | 最后修改:2026-08-03
一、概述
exs_pcf8574 是 NXP PCF8574 8 位 I2C GPIO 扩展芯片的 LuatOS 扩展库。PCF8574 提供 8 位并行 I/O 扩展,通过 I2C 串行接口与主控通信,广泛应用于需要少量额外 GPIO 的场景。
PCF8574 提供 1 个 8 位端口(P0~P7),共 8 个 GPIO,采用准双向 IO 设计,无需单独配置方向寄存器,支持输入、输出和中断三种工作模式。
1.1 主要特性
-
8 个 I/O 引脚(P0~P7),采用准双向 IO 设计,无需方向配置
-
内置上拉电阻,输入模式时引脚默认高电平
-
支持 INT 中断引脚,输入电平变化时触发中断通知主控
-
支持批量读写所有 GPIO 端口数据(read_all / write_all)
-
I2C 接口速率可达 100kHz(标准模式)
-
3 个硬件地址引脚(A0、A1、A2),支持 8 种 I2C 地址(0x20~0x27)
-
工作电压 1.8V~5.5V
-
工作温度 -40℃~+85℃
1.2 加载方式
-- 扩展库需要 require 加载后才能调用
local exs_pcf8574 = require "exs_pcf8574"
1.3 注意事项
-
I2C 上拉电阻:SDA 和 SCL 需外接 4.7kΩ~10kΩ 上拉电阻到 VCC
-
INT 引脚:PCF8574 的 INT 引脚为开漏输出,需外接上拉电阻
-
GPIO ID 编码规则:
-
0x00~0x07:P0 ~ P7 -
准双向 IO 模式:PCF8574 没有独立的方向配置寄存器,写入 0 时引脚输出低电平(强驱动),写入 1 时引脚变为高阻状态(内部上拉,可被外部驱动),读取时返回引脚实际电平
-
中断模式:使用中断功能时,必须在
init()中传入gpio_int_id参数,并将 PCF8574 的 INT 引脚连接到主机的对应 GPIO -
多设备支持:通过 A0、A1、A2 引脚配置不同 I2C 地址,最多可在同一 I2C 总线上连接 8 个 PCF8574 设备
1.4 硬件连接
┌──────────────┐ ┌──────────────────┐
│ 主控 │ │ PCF8574 │
│ (AirXXX) │ │ GPIO 扩展芯片 │
│ │ │ │
│ I2C_SDA ─────┼────────────────────┼──→ SDA │
│ │ │ (需外接上拉电阻)│
│ I2C_SCL ─────┼────────────────────┼──→ SCL │
│ │ │ (需外接上拉电阻)│
│ GPIO_INT ←───┼────────────────────┼──→ INT │
│ │ │ (开漏输出, │
│ │ │ 需外接上拉电阻)│
│ │ │ │
│ VCC 3V3 ─────┼────────────────────┼──→ VDD │
│ │ │ │
│ GND ────┼────────────────────┼──→ GND │
│ │ │ │
│ │ │ A0~A2 ──────────┼──→ 地址配置
│ │ │ │
│ │ │ P0~P7 ──────────┼──→ 扩展 GPIO 端口
└──────────────┘ └──────────────────┘
1.5 寄存器映射
PCF8574 没有 I2C 寄存器地址的概念。I2C 通信时,直接读写一个字节数据:写入的一个字节控制 8 个引脚的输出状态,读取的一个字节反映 8 个引脚的实际电平。
| 操作 | I2C 命令 | 数据长度 | 位定义 |
|---|---|---|---|
| 读取输入 | 主机读取 | 1 字节 | bit7~bit0 对应 P7~P0 |
| 写入输出 | 主机写入 | 1 字节 | bit7~bit0 对应 P7~P0 |
准双向 IO 说明: - 写入
0:引脚输出低电平(强驱动拉低) - 写入1:引脚变为高阻状态(内部上拉,可被外部驱动) - 读取:返回引脚实际电平(无论输出还是输入模式)
二、核心示例
-
核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码
-
核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单
-
更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/sensor/pcf8574
2.1 GPIO 输出示例
-- 加载扩展库
local exs_pcf8574 = require "exs_pcf8574"
-- 应用主函数
local function pcf8574_output_demo()
-- 初始化 PCF8574(使用 I2C1)
local result = exs_pcf8574.init(1)
if not result then
log.error("exs_pcf8574", "PCF8574 初始化失败")
return
end
log.info("exs_pcf8574", "PCF8574 初始化成功")
-- 配置 P0 为输出模式,初始输出低电平
exs_pcf8574.setup(0x00, 0)
-- 循环切换 P0 电平
while true do
exs_pcf8574.set(0x00, 0) -- 输出低电平
sys.wait(1000)
exs_pcf8574.set(0x00, 1) -- 输出高电平
sys.wait(1000)
end
end
-- 启动任务
sys.taskInit(pcf8574_output_demo)
2.2 GPIO 输入示例
-- 加载扩展库
local exs_pcf8574 = require "exs_pcf8574"
-- 应用主函数
local function pcf8574_input_demo()
-- 初始化 PCF8574
local result = exs_pcf8574.init(1)
if not result then
log.error("exs_pcf8574", "PCF8574 初始化失败")
return
end
-- 配置 P1 为输出模式(用于产生测试信号)
exs_pcf8574.setup(0x01, 0)
-- 配置 P2 为输入模式(准双向 IO,内部上拉)
exs_pcf8574.setup(0x02)
-- 循环读取 P2 电平
-- 注意:需将 P1 和 P2 短接
while true do
exs_pcf8574.set(0x01, 0)
sys.wait(1000)
local level = exs_pcf8574.get(0x02)
log.info("exs_pcf8574", "P2 电平:", level)
exs_pcf8574.set(0x01, 1)
sys.wait(1000)
level = exs_pcf8574.get(0x02)
log.info("exs_pcf8574", "P2 电平:", level)
end
end
sys.taskInit(pcf8574_input_demo)
2.3 GPIO 中断示例
-- 加载扩展库
local exs_pcf8574 = require "exs_pcf8574"
-- P3 中断回调函数
-- id:触发中断的 GPIO ID
-- level:触发中断后读取到的电平(0=低,1=高)
local function P3_int_cbfunc(id, level)
log.info("exs_pcf8574", "P3 中断触发,ID:", id, "电平:", level)
end
-- 应用主函数
local function pcf8574_int_demo()
-- 初始化 PCF8574,使用 GPIO2 作为中断引脚
local result = exs_pcf8574.init(1, 2)
if not result then
log.error("exs_pcf8574", "PCF8574 初始化失败")
return
end
-- 配置 P2 为输出模式(用于触发 P3 中断)
exs_pcf8574.setup(0x02, 0)
-- 配置 P3 为中断模式
-- 注意:需将 P2 和 P3 短接
exs_pcf8574.setup(0x03, P3_int_cbfunc)
-- 循环切换 P2 电平,触发 P3 中断
while true do
exs_pcf8574.set(0x02, 0)
sys.wait(1000)
exs_pcf8574.set(0x02, 1)
sys.wait(1000)
end
end
sys.taskInit(pcf8574_int_demo)
2.4 批量读写示例
-- 加载扩展库
local exs_pcf8574 = require "exs_pcf8574"
-- 应用主函数
local function pcf8574_batch_demo()
-- 初始化 PCF8574
local result = exs_pcf8574.init(1)
if not result then
log.error("exs_pcf8574", "PCF8574 初始化失败")
return
end
-- 循环批量读写
while true do
-- 写入:P0~P3 输出低,P4~P7 输出高
exs_pcf8574.write_all(0xF0)
sys.wait(1000)
-- 读取所有引脚状态
local data = exs_pcf8574.read_all()
if data ~= false then
log.info("exs_pcf8574", string.format("端口数据: 0x%02X", data))
end
-- 写入:全部输出低
exs_pcf8574.write_all(0x00)
sys.wait(1000)
-- 读取所有引脚状态
data = exs_pcf8574.read_all()
if data ~= false then
log.info("exs_pcf8574", string.format("端口数据: 0x%02X", data))
end
end
end
sys.taskInit(pcf8574_batch_demo)
三、常量解释
扩展库常量,顾名思义是由合宙 LuatOS 扩展库中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用,本扩展库没有常量。
四、函数详解
4.1 初始化与控制
4.1.1 exs_pcf8574.init(i2c_id, gpio_int_id)
功能
初始化 PCF8574,配置 I2C 通信参数,自动识别从设备地址
参数
i2c_id
参数含义:主机使用的 I2C ID,用来控制 PCF8574
数据类型:number
取值范围:平台有效的 I2C 总线编号(如 0 或 1)
是否必选:是
注意事项:调用前必须先用 i2c.setup(i2c_id, i2c.FAST) 初始化该总线
参数示例:1
gpio_int_id
参数含义:主机使用的中断引脚 GPIO ID,与 PCF8574 的 INT 引脚相连
PCF8574 上任意配置为输入模式的 GPIO 状态发生变化时,会通过 INT 引脚通知主机
数据类型:number
取值范围:有效的 GPIO 编号
是否必选:否
注意事项:可选,不传则不使用中断通知功能。传入后,PCF8574 上配置为中断模式的 GPIO 电平变化时,会通过 INT 引脚触发主机中断
参数示例:2
返回值
local init_result = exs_pcf8574.init(i2c_id, gpio_int_id)
init_result
含义说明:初始化是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:初始化失败时请检查接线、供电和 I2C 地址配置
返回示例:true
示例
-- 基础初始化(不使用中断)
local result = exs_pcf8574.init(1)
-- 使用中断功能(主机 GPIO2 作为中断引脚)
local result = exs_pcf8574.init(1, 2)
4.1.2 exs_pcf8574.deinit()
功能
关闭 PCF8574 通信,释放所有资源(I2C、GPIO、中断表)
参数
无
返回值
local result = exs_pcf8574.deinit()
result
含义说明:释放是否成功
数据类型:boolean
取值范围:true(成功)
注意事项:释放后所有 GPIO 配置将失效,如需使用需重新 init
返回示例:true
示例
exs_pcf8574.deinit()
4.2 GPIO 配置与操作
4.2.1 exs_pcf8574.setup(gpio_id, gpio_mode)
功能
配置 PCF8574 扩展 GPIO 管脚功能,支持输出、输入和中断三种模式
参数
gpio_id
参数含义:PCF8574 上的扩展 GPIO ID
数据类型:number
取值范围:0x00 ~ 0x07,对应 P0 ~ P7
是否必选:是
注意事项:超出范围将返回错误
参数示例:0x00
gpio_mode
参数含义:GPIO 工作模式,支持三种类型
数据类型:number | function | nil
取值说明:
- number (0):输出模式,输出低电平(引脚拉低)
- number (1):输出模式,输出高电平(准双向,内部上拉)
- nil 或不传:输入模式(内部上拉,外部驱动)
- function:中断模式,参数为回调函数
回调函数格式:function cb_func(id, level) end
- id:触发中断的 GPIO ID(number 类型)
- level:触发中断后读取到的电平(0=低,1=高)
是否必选:是
注意事项:中断模式需要在 init() 中传入 gpio_int_id 参数
参数示例:0
返回值
local result = exs_pcf8574.setup(gpio_id, gpio_mode)
result
含义说明:配置是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:配置中断模式时,需确保 init() 已配置 gpio_int_id
返回示例:true
示例
-- GPIO 0x00 配置为输出模式,输出低电平
exs_pcf8574.setup(0x00, 0)
-- GPIO 0x01 配置为输入模式
exs_pcf8574.setup(0x01)
-- GPIO 0x04 配置为中断模式
local function P04_int_cbfunc(id, level)
log.info("P04_int_cbfunc", id, level)
end
exs_pcf8574.setup(0x04, P04_int_cbfunc)
4.2.2 exs_pcf8574.set(gpio_id, output_level)
功能
设置 PCF8574 扩展 GPIO 的输出电平
参数
gpio_id
参数含义:PCF8574 上的扩展 GPIO ID
数据类型:number
取值范围:0x00~0x07
是否必选:是
注意事项:必须先通过 setup() 配置为输出模式
参数示例:0x03
output_level
参数含义:输出电平
数据类型:number
取值范围:0(低电平)或 1(高电平)
是否必选:是
注意事项:只有配置为输出模式的 GPIO 才能设置电平
参数示例:1
返回值
local result = exs_pcf8574.set(gpio_id, output_level)
result
含义说明:设置是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:
返回示例:true
示例
-- GPIO 0x03 输出高电平
exs_pcf8574.set(0x03, 1)
-- GPIO 0x05 输出低电平
exs_pcf8574.set(0x05, 0)
4.2.3 exs_pcf8574.get(gpio_id)
功能
读取 PCF8574 扩展 GPIO 的输入电平
参数
gpio_id
参数含义:PCF8574 上的扩展 GPIO ID
数据类型:number
取值范围:0x00~0x07
是否必选:是
注意事项:
参数示例:0x02
返回值
local level = exs_pcf8574.get(gpio_id)
level
含义说明:GPIO 输入电平
数据类型:number 或 boolean
取值范围:0(低电平),1(高电平);读取失败返回 false
注意事项:读取的是引脚实际电平状态
返回示例:1
示例
-- 读取 GPIO 0x02 的输入电平
local level = exs_pcf8574.get(0x02)
if level ~= false then
log.info("exs_pcf8574", "GPIO 0x02 电平:", level)
end
4.2.4 exs_pcf8574.close(gpio_id)
功能
关闭 PCF8574 扩展 GPIO 功能,恢复为默认输入模式
参数
gpio_id
参数含义:PCF8574 上的扩展 GPIO ID
数据类型:number
取值范围:0x00~0x07
是否必选:是
注意事项:
参数示例:0x03
返回值
local result = exs_pcf8574.close(gpio_id)
result
含义说明:关闭是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:
返回示例:true
示例
exs_pcf8574.close(0x03)
4.3 批量读写
4.3.1 exs_pcf8574.read_all()
功能
读取 PCF8574 所有 GPIO 端口数据,一次性读取 8 个引脚的状态
参数
无
返回值
local port_data = exs_pcf8574.read_all()
port_data
含义说明:8 位端口数据
数据类型:number 或 boolean
取值范围:0x00~0xFF,bit0=P0, bit7=P7;读取失败返回 false
注意事项:返回值反映 8 个引脚的实际电平状态
返回示例:0xF0
示例
-- 读取所有 GPIO 端口数据
local port_data = exs_pcf8574.read_all()
if port_data ~= false then
log.info("exs_pcf8574", string.format("端口数据: 0x%02X", port_data))
end
4.3.2 exs_pcf8574.write_all(data)
功能
写入 PCF8574 所有 GPIO 端口数据,一次性设置 8 个引脚的输出状态
参数
data
参数含义:8 位端口数据,每位对应一个 GPIO
数据类型:number
取值范围:0x00~0xFF,bit0=P0, bit7=P7
是否必选:是
注意事项:写入 0 的位输出低电平,写入 1 的位变为高阻(内部上拉)
参数示例:0xF0
返回值
local result = exs_pcf8574.write_all(data)
result
含义说明:写入是否成功
数据类型:boolean
取值范围:true(成功), false(失败)
注意事项:
返回示例:true
示例
-- 设置 P0~P3 输出低,P4~P7 输出高
exs_pcf8574.write_all(0xF0)
-- 设置全部输出低
exs_pcf8574.write_all(0x00)
-- 设置全部输出高
exs_pcf8574.write_all(0xFF)
4.4 版本管理
4.4.1 exs_pcf8574.version()
功能
获取 exs_pcf8574 库的版本号
参数
无
返回值
local ver = exs_pcf8574.version()
ver
含义说明:版本号字符串
数据类型:string
取值范围:格式 "yyyymmddhhmm",表示 yyyy年mm月dd日hh时mm分发布的版本
注意事项:无
返回示例:"202607311200"
示例
local ver = exs_pcf8574.version()
log.info("exs_pcf8574", "版本号:", ver)
五、版本更新说明
版本号:202607311200
- 更新时间:2026-07-31
-
更新内容:
-
第一版,实现 PCF8574 基础驱动功能
-
自动识别从设备地址功能(扫描 0x20~0x27)
-
支持 8 个 GPIO 的输入、输出、中断配置
-
支持批量读写端口数据(read_all / write_all)
-
支持 GPIO 中断模式(通过 INT 引脚 + sys.publish 机制)
-
支持准双向 IO 模式(无需单独配置方向)
-
六、产品支持说明
所有支持 luatos 二次开发的模块,具体可以查看选型手册。