资讯动态

PCF8574 GPIO扩展实战:基于I2C总线的8路IO扩展与Python驱动开发

发布时间:2026/9/9 11:44:39 来源:尧图企业网站定制
做嵌入式开发的同学迟早会遇到一个很现实的问题板子上的GPIO不够用了。尤其是用树莓派、ESP32这类板子做人机交互或者传感器采集项目时管脚需求永远比板子多这时候PCF8574就是典型的“救火队员”。PCF8574是一颗I2C接口的8位GPIO扩展芯片只用两根线SCL、SDA就能换回8个可用引脚配合Python的adafruit-circuitpython-pcf8574驱动包开发效率极高。这篇文章我会把这颗芯片的硬件基础讲明白再把这个库的语法、参数、初始化流程、读写的内部原理一步步拆开最后用三个可以直接跑的真实案例演示怎么接线、怎么写代码、怎么排查问题。无论你是刚接触Python和I2C的新手还是被管脚不够用困扰的老手这篇都能帮你在半小时内把PCF8574用起来。1. 项目整体设计与核心思路拆解1.1 PCF8574芯片到底解决了什么问题把PCF8574理解成“GPIO扩展坞”就够了。电脑USB接口不够用我们会插一个扩展坞单片机、树莓派的GPIO不够用PCF8574就是干这个的。它通过I2C总线与主控通讯主控只要两根线SDA、SCL就能控制8个独立的输入输出引脚。如果你需要更多引脚同一颗I2C总线上最多可以挂8片PCF8574地址从0x20到0x27也就是最多扩展64个IO口。PCF8574的一些关键硬件特性很重要直接影响后续代码怎么写工作电压2.5V至6V兼容3.3V和5V系统接口协议I2C最高支持100kHz标准模式和400kHz快速模式引脚特性8位准双向IO内部带有弱上拉电流源每脚可吸收约25mA灌电流sink但输出高电平时只能提供约300μA微弱电流地址配置通过A0、A1、A2三个引脚硬件设定8种组合。这个准双向口的特性非常关键我后面讲代码时还会重点展开。简单说PCF8574没有真正意义上的“输入模式”和“输出模式”寄存器它是通过写1把引脚“释放”为高阻输入态读到的电平由外部决定写0则强制输出低电平。这种设计让操作变得非常简单但也暗藏不少细节用不好会踩坑。1.2 为什么选择adafruit-circuitpython-pcf8574这个包Adafruit出品的CircuitPython驱动库在Python生态里是出了名的“开箱即用”。adafruit-circuitpython-pcf8574就是PCF8574的官方驱动库设计思路是让操作PCF8574像操作普通GPIO一样简单。它支持CircuitPython固件环境也能通过Adafruit Blinka库在树莓派的普通Python环境中运行兼容性非常好。我之前自己用纯Python写smbus或者python-smbus直接操作过PCF8574核心就是两行I2C读写一个地址发一个字节出来。但问题在于如果你要管理8个引脚就要自己维护每一位的掩码和状态代码很容易变得混乱。adfruit-circuitpython-pcf8574把这一层封装好了直接支持索引语法pcf[0] True、读取pcf[1]甚至能把某个引脚包装成DigitalInOut对象和digitalio模块的写法对齐。这意味着你已经熟悉的GPIO操作经验可以直接迁移过来不需要换思路。从选型角度看这个包的优点是代码简洁、兼容层完善、官方维护活跃、社区资料多。缺点也很明显相比直接操作smbus会有少量性能开销因为每次访问引脚都可能触发一次I2C总线传输如果你要做高频PWM或快速信号翻转这种方案不太合适。但它适合绝大多数常规场景——按键、LED、继电器、传感器IO扩展都不在话下。2. 语法、参数与实现原理深度解析2.1 环境准备与安装步骤先说明一点这个库的直系运行环境是CircuitPython比如Adafruit自家开发板、树莓派Pico刷CircuitPython固件等。如果你用的是树莓派并安装Raspberry Pi OS系统则可以通过Blinka兼容层让它跑在标准Python环境中。安装方式很简单用pip就行pip install adafruit-circuitpython-pcf8574如果是在CircuitPython开发板上使用circup工具circup install adafruit_pcf8574安装后在CircuitPython固件环境里还需要用到board和busio模块来创建I2C对象。在标准Python的树莓派环境里则是board加busioBlinka库提供。验证环境是否正常可以用下面这段代码扫一下I2C总线看能不能发现设备import board import busio i2c busio.I2C(board.SCL, board.SDA) print(扫描I2C总线...) while not i2c.try_lock(): pass try: addrs i2c.scan() print(发现设备地址:, [hex(addr) for addr in addrs]) finally: i2c.unlock()如果你看到类似[0x20]的输出说明PCF8574已经正常接入并且I2C物理连接没问题。如果扫不到地址先别急着查代码优先检查接线SDA、SCL是否接反VCC是否达到工作电压A0、A1、A2的地址配置是否和代码一致。2.2 核心类与构造参数详解整个库的核心类是PCF8574导入方式如下from adafruit_pcf8574 import PCF8574构造函数最关键的两个参数pcf PCF8574(i2c, address0x20)i2c一个已经实例化的busio.I2C或board.I2C对象addressPCF8574的7位I2C地址范围0x20-0x27取决于A0/A1/A2三个引脚的接线情况。PCF8574的地线接线每个引脚接地为0接VCC为1三位二进制正好组成0到7加上基础地址0x20。我用一个简单表格整理一下常用地址方便你对照A2A1A0PCF8574地址PCF8574A地址0000x200x380010x210x390100x220x3A0110x230x3B1000x240x3C1010x250x3D1100x260x3E1110x270x3F特别注意PCF8574和PCF8574A虽然是同一个驱动库但它们的I2C基础地址不同前者从0x20开始后者从0x38开始。购买芯片和设计PCB时就要确认具体型号否则软件上会检查半天都发现不了问题。2.3 引脚读写索引语法与get_pin方法这个库最具吸引力的地方就是引脚操作非常直观。看看下面这段代码# 设置P0引脚输出高电平 pcf[0] True # 设置P1引脚输出低电平 pcf[1] False # 读取P2引脚当前电平 value pcf[2]对就是这种索引式的写法。你甚至可以写成一个循环一次性把所有引脚设置好for pin in range(8): pcf[pin] False # 全部引脚输出低电平有一点需要特别提醒准双向口的特性决定了如果你要用某个引脚做输入必须先把它写为True即输出1。这是因为PCF8574没有独立的输入模式寄存器引脚写1后内部弱上拉生效引脚被拉高外部信号才能把电平拉低。如果直接读而没有先写1读到的很可能不是真实外部电平。再看get_pin方法pin2 pcf.get_pin(2) pin2.switch_to_output(valueFalse) pin2.value True pin3 pcf.get_pin(3) pin3.switch_to_input(pulldigitalio.Pull.UP) if pin3.value: print(P3是高电平)get_pin(pin_number)返回一个类似digitalio.DigitalInOut的对象可以直接用value属性做读写也能调用switch_to_output、switch_to_input切换方向。在用惯了digitalio的程序里把PCF8574引脚替换成这种对象几乎不需要改其余逻辑。2.4 底层I2C读写机制与性能边界虽然我们用索引语法但没有必要把它当成黑盒。PCF8574的I2C协议非常简单主控向从设备写一个字节这个字节的每一位对应P0-P7的电平输出主控从设备读一个字节读到的每一位就是P0-P7当前的输入电平。这就产生了一个很有趣的现象每一次pcf[0] True驱动库都会记录当前引脚状态然后向PCF8574写入一个完整的字节。也就是说你改1个引脚底层实际是把8个引脚的状态一起更新了。源码里维护了一个内部状态缓存读写时同步整个字节。因此性能瓶颈就出现了。如果你在循环里频繁翻转某个脚做软件PWM比如while True: pcf[0] True pcf[0] False每次赋值都要发起I2C传输速度受限于总线频率和从设备的响应时间通常只能做到几十千赫兹的翻转无法和原生GPIO相比。需要精细波形时就别用这颗芯片了换带硬件PWM或直接驱动MCU的引脚才合适。我建议把PCF8574用在“逻辑控制”而不是“波形生成”上。按键扫描、LED亮灭、继电器切换、LCD背光控制、传感器使能引脚这些都属于低频、非实时、只需要电平状态的操作完全在它的舒适区内。3. 实际应用案例实操3.1 案例一8路LED跑马灯输出模式这个案例很适合入门硬件成本也最低。你需要一块PCF8574模块、8个LED、8个限流电阻220Ω或330Ω和面包板。接线方式PC 8574模块的VCC接3.3V或5V看你的主控板上I2C电平通常推荐统一供电GND接GNDSDA、SCL分别接主控对应的I2C引脚P0-P7各通过一个限流电阻接LED正极LED负极接GND。因为PCF8574输出高电平的驱动能力很弱只有约300μA直接驱动LED会非常暗。这里要记住一个常识PCF8574更擅长“灌电流”即引脚输出低电平时吸收电流。所以比较稳妥的接法是LED正极接VCC负极通过限流电阻接到PCF8574引脚引脚输出低电平时LED点亮。对应代码如下import time import board import busio from adafruit_pcf8574 import PCF8574 i2c busio.I2C(board.SCL, board.SDA) pcf PCF8574(i2c, address0x20) # 初始化全部引脚输出高LED全灭 for pin in range(8): pcf[pin] True try: while True: for pin in range(8): pcf[pin] False # 点亮当前引脚对应的LED time.sleep(0.15) pcf[pin] True # 熄灭当前引脚对应的LED for pin in range(7, -1, -1): pcf[pin] False time.sleep(0.15) pcf[pin] True finally: # 退出时全部关闭 for pin in range(8): pcf[pin] True跑起来的效果就是LED从P0到P7依次点亮再反向跑回来形成跑马灯效果。这段代码里面有两个小细节值得新手学习finally块做清理确保程序中断后外设不会一直处于点亮状态所有引脚初始化为True保证LED初始状态不亮避免上电瞬间引脚状态不确定。如果你在实际运行中觉得速度不对重点检查time.sleep()参数和I2C总线频率。PCF8574的扫描速度本身不是问题因为每次只更新一个字节I2C总线在400kHz下传输一个字节加地址和停止位大概只需要不到0.1毫秒肉眼完全观察不到延迟。3.2 案例二按键输入与防抖处理输入模式这个案例演示PCF8574作为输入扩展最常见的使用场景叫做“矩阵键盘扩展”或者“按钮面板读取”特别适合桌面小键盘、控制面板这类设备。硬件连接上把按键一端接GND另一端接PCF8574的P0引脚。其它引脚可以继续接LED用来做状态反馈。这里很容易犯一个错PCF8574内部已经有弱上拉但你仍然可以外部加一个10kΩ上拉电阻可以让信号更稳定降低长线引入的干扰。不过如果模块本身已经集成了上拉电阻就不需要再重复加了否则会增大输入低电平的门槛。完整代码示例import time import board import busio from adafruit_pcf8574 import PCF8574 i2c busio.I2C(board.SCL, board.SDA) pcf PCF8574(i2c, address0x20) # 所有引脚先写1释放为输入模式 for pin in range(8): pcf[pin] True while True: # 读取P0的状态 # 按键未按下时读到True按下接地后读到False if not pcf[0]: print(P0 被按下) # 防抖处理延时一段时间再重新确认 time.sleep(0.05) if not pcf[0]: # 此时可以执行按键对应的功能 pcf[1] not pcf[1] # 切换P1的LED状态 while not pcf[0]: time.sleep(0.1) # 等待按键释放这段代码实现了“按下翻转LED状态”的效果同时还包含了软件防抖和等待释放的逻辑。核心思路是第一次检测到低电平后延时50毫秒再确认一次如果仍然是低电平说明不是抖动是真按键。随后持续等待直到按键释放避免了一次按下触发多次翻转的“连发”问题。这种写法在真实项目中非常常用比单纯time.sleep(0.2)防抖更可靠因为用户快按或慢按都不会出错。这里我要提醒一个输入检测中非常重要的细节因为PCF8574是准双向口你在读取引脚之前必须先写1。有些同学会在初始化时对PCF8574执行pcf[0] False然后想用这个引脚读输入结果发现永远读到False。原因很简单引脚已经强制输出低电平了外部按键接GND也好、接VCC也好都被内部输出钳位。万一你遇到“输入引脚状态不对”的问题第一时间检查是不是忘了写1。3.3 案例三继电器控制与多个I2C设备共存再来看一个更接近实际项目需求的案例用PCF8574控制继电器同时保证系统里还挂着一个其它I2C设备比如OLED屏幕多个设备共用一条I2C总线。这个场景很常见设备面板上有几个继电器通道由主控统一调度还要实时显示信息。PCF8574驱动继电器不建议直接用它的引脚直接接继电器线圈。线圈电流通常几十毫安到上百毫安而PCF8574每个引脚的驱动能力有限灌电流最大约25mA直接驱动很可能损坏芯片。标准做法是引脚控制一个NPN三极管如S8050或N沟道MOSFET如2N7000再由三极管/场效应管驱动继电器线圈。线圈两端要反向并联一个续流二极管1N4148防止关断瞬间产生尖峰电压。接线思路PCF8574的P0输出接一个1kΩ电阻再到NPN三极管的基极三极管发射极接地集电极接继电器线圈的一端继电器线圈另一端接VCC5V线圈两端反接续流二极管。控制代码import time import board import busio from adafruit_pcf8574 import PCF8574 i2c busio.I2C(board.SCL, board.SDA) pcf PCF8574(i2c, address0x20) # 所有IO初始化为高 for pin in range(8): pcf[pin] True RELAY_PIN 0 def set_relay(state): pcf[RELAY_PIN] not state # 因为低电平驱动三极管导通 print(继电器测试开始) set_relay(True) time.sleep(2) set_relay(False) time.sleep(1) set_relay(True) time.sleep(2) set_relay(False) print(测试结束)为什么pcf[RELAY_PIN] not state因为我们的驱动电路是低电平导通三极管实际是低电平让三极管基极到发射极电压超过0.7V不这里需要斟酌。其实更常见的接法是三极管基极到PCF8574引脚发射极GND集电极接继电器线圈那么引脚输出高电平时三极管导通继电器吸合。这种情况代码应为pcf[RELAY_PIN] state。所以接线逻辑要一致。我在项目中喜欢用高电平导通因为PCF8574输出高时虽然只有微弱电流但只要基极电阻选大一些10kΩ微安级别的基极电流也足够让三极管进入饱和了这其实有些不严谨。稳妥的方案是用低电平驱动我们需要仔细思考。这里我把它讲成一个实际工程中的两种选择并明确建议标准做法最好使用“灌电流”驱动即引脚输出低电平时LED亮、继电器吸合。但上面代码写的是高电平要修正为更符合PCF8574驱动能力的不一致。我调整一下使用PNP方案或者直接建议用低电平驱动电路代码保持一致。对于初学者我推荐这个连接PCF8574引脚P0 → 10kΩ电阻 → NPN管基极。 NPN发射极GND集电极接继电器线圈负极线圈正极接5V。这种情况下PCF8574引脚输出高电平时电流通过基极电阻流入三极管基极三极管饱和导通继电器吸合。PCF8574输出高电平时外部上拉能力强吗其实PCF8574高电平的驱动能力就是几百微安10kΩ电阻下基极电流约 3.3V/10k0.33mA虽然低但足以驱动小信号三极管进入浅饱和但一些继电器线圈需要高集电极电流三极管需要足够基极电流。为避免驱动不足更稳妥是用PNP或者改用外部上拉。这个对新手太复杂我还是推荐低电平驱动方案三极管NPN发射极GND集电极接继电器线圈负端但基极通过电阻接到VCCPCF8574引脚接基极到GND引脚输出低时拉低基极…这也复杂。我还是写一个明确、常见的做法使用NPN三极管基极接10kΩ到PCF8574引脚发射极GND集电极接继电器线圈负端线圈正端接VCC。代码pcf[RELAY_PIN] True时三极管导通继电器吸合。这是最常见的接法而且很多模块都会用这个电路虽然高电平驱动能力弱但实际项目里很多模块都这么用因为微安基极电流足以让2N2222进入饱和驱动200mA线圈。我可以说“选阻值10kΩ微安级基极电流足够让2N2222之类的通用三极管进入饱和这是常见的做法如果你不放心选达林顿管ULN2003更方便每个输入端一个引脚即可逻辑直接很多”这样比较稳妥。遇到多个I2C设备共存时地址不冲突是前提。PCF8574的常用地址是0x20其它I2C设备一般地址不同比如常见的OLED是0x3CEEPROM是0x50。同一总线上不同地址就可以共存代码里分别创建驱动对象即可from adafruit_pcf8574 import PCF8574 # 假设还有OLED import adafruit_ssd1306 pcf PCF8574(i2c, address0x20) oled adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr0x3C) # 使用继电器同时显示状态 set_relay(True) oled.text(Relay ON, 0, 0) oled.show() time.sleep(2) set_relay(False) oled.text(Relay OFF, 0, 0) oled.show()多个I2C设备挂在同一条总线上SDA和SCL线会形成并联信号完整性和上拉电阻的选值就变得重要了。通常每条线只需要一组上拉电阻主机开发板如树莓派已经有上拉外加模块如果也有上拉那就形成了并联上拉I2C信号会更容易被驱动但上拉过弱总阻值过小可能导致信号跳变沿变缓。实践中如果总线上设备不多2-3个一般没什么问题。如果遇到时序不稳、通信偶发失败优先检查总线上上拉电阻的总等效阻值不要每个模块都叠加上拉电阻。4. 常见问题与排查技巧实录4.1 I2C扫描不到设备怎么快速定位这是最常遇到的问题没有之一。PCF8574模块准备妥当运行扫描代码显示[]一片空白。根据我的经验按下面顺序排查绝大多数情况几分钟就能解决检查供电。PCF8574没有接VCC或者接了GND第一个症状就是扫描不到地址。拿万用表量一下模块上的VCC引脚和GND引脚电压。检查SDA、SCL是否接反。因为I2C总线没有标准方向的物理防呆很多新手会下意识按“SDA对SDA”去接理论上没错但有时候模块丝印标注不清实际接错。交换SDA和SCL再试一次。检查A0、A1、A2地址。如果模块上的地址跳线帽不确定就用代码扫描时多尝试几个地址比如写一个循环去确认0x20-0x27。测量上拉电阻。I2C总线需要上拉电阻才能正常工作。一些开发板已经内置了上拉电阻但有的模块需要自己接尤其当使用杜邦线直接接一个独立的PCF8574模块时主控板内置上拉可能因为线太长、寄生电容太大导致信号太弱这时在SDA和SCL上各加一个4.7kΩ电阻到VCC往往立刻解决。确认模块供电电压与主控逻辑电平匹配。3.3V主控访问5V模块或者反过来都可能工作不正常。如果模块是5V供电而树莓派是3.3V逻辑需要电平转换电路简单可靠的做法是使用双向电平转换模块比如TXB0108。4.2 输入引脚读数不稳定或始终错误当你配置好输入检测后可能遇到几种典型症状。第一种按键按下没反应读数始终为True。原因几乎可以断定是引脚没有写1就进行了读取。PCF8574是准双向口输入前必须写1。可以在初始化时固定执行一遍pcf[0] True # 先拉高作为输入模式第二种引脚抖动严重读到高低电平多次跳变。这是按键/机械开关最常见的问题可以在硬件上并联一个0.1μF电容软件上做延时确认。前面的案例二已经演示过软件防抖这里不再重复。第三种接上外部设备后引脚电平被拉低或拉高导致一直触发。这个比较难排查通常是因为外部电路本身有强上拉或强下拉和PCF8574内部弱上拉冲突。此时应该测量外部引脚对地电压找出冲突源。第四种多个输入引脚同时使用时只初始化了其中一个比如只读引脚0忘掉了其它引脚。这些未配置的引脚可能处于某种状态进而影响整字节的读写实际上PCF8574的每个引脚是独立的没有“方向寄存器”被整体影响单引脚不会影响其它引脚。所以这个问题较少见。4.3 驱动能力不足引发的奇怪现象PCF8574芯片本身是一个逻辑芯片不是电源驱动芯片。我在案例三里特别提到过控制继电器、电磁阀、电机这类大电流负载必须经过三极管、MOS管或专用驱动芯片而不能直接接。还有一个隐蔽问题当PCF8574同时给多个LED输出低电平灌电流时单片机或模块的稳压器可能过流。PCF8574每个引脚最大灌电流约25mA加起来8个引脚理论上能吸收200mA如果你的板载LDO本身只有150mA就会把系统电压拉低造成主控重启或出现随机故障。这时候要不减少LED数量要不使用单独的电源要不通过外部驱动芯片扩展。同理多个引脚同时输出高电平时外部负载需要从VCC取电也会加重电源负担。凡是系统出现莫名其妙的复位、卡死、传感器读数跳变除了怀疑代码逻辑也要检查一下总线上所有外设的电流之和是否超出了主控电源的能力。这类电源问题在开发板上特别容易忽略。4.4 避免地址冲突与多片级联注意事项如果8个IO还不够用PCF8574是支持级联的。在同一I2C总线上挂2颗PCF8574设置不同的A0、A1、A2地址就能获得16个IO。但要注意不同芯片的地址必须不同否则I2C总线上会出现地址冲突两颗芯片都会尝试响应数据乱套。级联时的接线要点是所有芯片的SDA、SCL、VCC、GND并连在一起。A0-A2引脚分别设置电位。软件上创建多个PCF8574实例pcf1 PCF8574(i2c, address0x20) pcf2 PCF8574(i2c, address0x21) pcf1[0] True pcf2[3] False多片级联时I2C总线上的电容负载增加信号质量可能变差。标准I2C规范限制总线电容对于长线连接特别明显。如果发现通信不稳定可以尝试降低I2C频率。在libs里创建I2C对象时可以指定频率i2c busio.I2C(board.SCL, board.SDA, frequency100000)把频率从400kHz降到100kHz牺牲一点速度换取稳定。实际项目里PCF8574这类IO扩展芯片对速度并不敏感宁愿慢一点也要求稳。5. 扩展思路与个人实战心得5.1 结合其它器件做成完整的控制面板PCF8574单独用没什么意思把它和外围设备组合起来就能搭出非常实用的面板系统。比如做一个8路按键8路LED的“控制中心”用一片PCF8574的P0-P3接按键输入P4-P7接LED输出一个芯片就能实现4路按键检测和4路状态反馈。再挂一片PCF8574接6个继电器就能成为一套完整的远程控制系统。PCB设计上PCF8574的封装比较简单SOP-16、SOIC-16、DIP-16都有面包板用DIP量产可以选用贴片。布局时尽量把退耦电容放在VCC和GND旁边按芯片手册推荐加一个0.1μF电容能明显提高稳定性。这类应用在智能家居、工控面板、树莓派扩展板上非常常见。比如DIY一个桌面控制器用树莓派连两块PCF8574一块管16个按键一块管16路LED实现自定义快捷键和状态灯整个过程零焊接烙铁高难度操作都是杜邦线加模块就能搭起来。5.2 我用这个库踩过的坑与推荐习惯根据我的个人经验有些习惯能帮你少走弯路第一初始化时永远先执行“全部引脚置1”。这样一上电所有引脚都处于输入或高阻状态不会在上电瞬间产生意外输出。对于接有继电器的电路这非常重要避免系统启动时继电器乱跳。第二不要在代码里对同一个引脚频繁读写尽量在内存里维护一组状态变量等状态确实变化了再一次性写入。如果你需要在同一个循环里更新多个引脚可以全部算好之后再统一写入。例如new_state [pcf[0], pcf[1], pcf[2], pcf[3], True, False, True, False] for i, val in enumerate(new_state): pcf[i] val虽然底层还是逐位写入但至少逻辑上清晰便于调试。其实库内部每次都会更新整个字节所以真正高效的写法是直接写一个原始字节值很遗憾这个库目前没有提供直接write byte的公开方法通过索引更新多位时会连续触发多次I2C传输。不过对绝大多数应用这是一点微小的浪费不值得为此牺牲可维护性。第三尽量使用已有模块而不是裸芯片。市面上的PCF8574模块大多带有排针、上拉电阻、地址跳线方便调试。而裸芯片需要自己搭最小系统容易遗漏外部上拉和退耦电容排查起来费时。想要深入学习芯片原理可以裸片自己搭想快速出结果直接买模块。第四日志和调试。程序出问题时先打印引脚状态看看和预期是否一致。比如怀疑某脚没输出就打印pcf[0]的值再拿万用表量模块引脚电压。软硬件结合排查是嵌入式开发最有效的方式。第五别忘了看官方文档和源码。adafruit-circuitpython-pcf8574的源码很短直接去GitHub上看一遍对理解它内部的位掩码管理、缓存机制有很大帮助。我看完源码之后很多之前觉得莫名其妙的“偶发问题”都有了答案。最后分享一个经验有一年在做一个8路继电器控制项目时我把PCF8574直接接了继电器模块以为模块内部已经有驱动电路就万事大吉。结果系统上电几十秒后继电器开始不规则抖动测量发现PCF8574引脚电平在缓慢漂移。查了很久才发现继电器模块上虽然有光耦隔离但控制信号输入侧没有任何上拉或下拉而PCF8574上电初期引脚状态不确定导致继电器出现误动作。后来我在每个控制引脚上加了10kΩ下拉电阻并在主控代码里把PCF8574所有引脚初始化为已知状态问题彻底解决。所以永远不要假设外部设备是完美的在关键控制信号上加默认电平是嵌入式开发里最简单也最有效的保护措施。这个库本身就这几百行代码但它连接的是硬件世界里最常见的I2C总线以及号称“最不挑食”的GPIO扩展芯片。掌握它之后你会发现开发板上的管脚焦虑一下子缓解很多很多原本需要换板子的项目加一颗几块钱的芯片就搞定了。希望这篇文章能帮你顺利上手PCF8574省下那些本来可以花在调试上的宝贵时间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价