跳转至

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

  1. 更新时间:2026-07-31
  2. 更新内容:

    • 第一版,实现 PCF8574 基础驱动功能

    • 自动识别从设备地址功能(扫描 0x20~0x27)

    • 支持 8 个 GPIO 的输入、输出、中断配置

    • 支持批量读写端口数据(read_all / write_all)

    • 支持 GPIO 中断模式(通过 INT 引脚 + sys.publish 机制)

    • 支持准双向 IO 模式(无需单独配置方向)


六、产品支持说明

所有支持 luatos 二次开发的模块,具体可以查看选型手册

搜索
AirMaster 实时解答