尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
GPIO不够用?I2C IO扩展芯片选型避坑指南
主控GPIO不够用聊聊I2C IO扩展选型的那些坑干嵌入式这行迟早会遇到这么一天板子画完了固件调得差不多了突然发现主控的GPIO引脚全用完了但还差三四个输入要接、五六个输出要控。这个时候脑子里冒出来的第一个方案大概率是I2C IO扩展——一挂挂一片一根SDA一根SCL走天下听起来无比美好。但这东西真用起来坑比想象中多得多。我这两年帮人评估过不少IO扩展方案从PCF8574到PCA9535从MCP23017到TCA系列的再加上最近比较火的带呼吸灯驱动的AW9523多多少少都趟过一遍。今天干脆把选型时要考虑的维度、芯片间的差异、以及实际调试中让人皱眉的细节一次性说清楚。IO扩展芯片市场非常成熟几乎每个模拟/逻辑大厂都有自己的系列NXP的PCF8574和PCA9535系列、Microchip的MCP23008/MCP23017系列、TI的TCA9535/TCA6424系列甚至国产的AiP、XW等品牌也有兼容型号。乍一看大家引脚都长差不多了数据手册里也都是8位、16位IO好像随便挑一个就行。但真要这么想后面大概率会吃大亏。不同芯片的IO结构、上电状态、中断机制、地址位数量、速度等级甚至I2C时序要求都不一样这些细节恰恰决定了这个芯片在你的具体项目里好不好用。正好最近后台也有人留言问主控引脚不够了I2C扩展芯片到底怎么选我觉得这个问题特别值得展开写一写。毕竟我踩过的那些坑全部是拿着数据手册看了三遍也看不出来的——文档上写的都是等电位零延时高电平有效可真正接到示波器上就完全是另一回事了。1. 为什么首选I2C扩展而不是SPI或者移位寄存器先聊一个比较宏观的问题同样是扩展IO市面上的方案并不少74HC595串转并、74HC165并转串、SPI接口的MCP23S17、单总线的DS2408P甚至直接换一颗引脚更多的MCU哪个不能用为什么最终大家想到的往往是I2C1.1 I2C扩展的天然优势I2C在这类场景里胜出的原因很朴素一是引脚占用极低两个引脚就能挂一堆芯片理论上I2C总线上可以挂128个设备就算地址扩展有限制挂个8片16位IO扩展芯片也是轻轻松松这可比SPI的CS片选信号从PA0一直引到PC15好看多了。二是速度够用标准模式100kbps、快速模式400kbps哪怕按最保守的方式去翻一次IO状态几百微秒也完成了绝大多数按键扫描、LED控制、继电器驱动场景压根不需要更快。三是几乎所有MCU都把I2C外设做成了标配STM32的硬件I2C虽然口碑起起伏伏但用软件模拟、或者换用CubeMX生成代码也基本没什么障碍。1.2 为什么不能完全替代原生GPIO但也得说实话I2C扩展IO有它无法回避的先天短板——慢和异步。一次完整的IO操作要先发设备地址、寄存器地址再写数据或者读数据大多数情况下主控还得等应答。用示波器看实际时序翻转一次输出几百纳秒不存在能跑到几十微秒级别就算不错了。所以I2C扩展的IO根本不适合做高频PWM输出、也不适合对时序敏感的总线类协议模拟。另外I2C是地址化通信主控代码里对IO的每一次读写本质上都是一次寻址命令数据的事务过程换句话说它天生不具备GPIO那种写一个寄存器点一下引脚的直接性和确定性。你用来做照明控制、做拨码读取、做设备使能信号完全没问题但如果你计划用扩展IO去驱动一个软串口或者做高精度的脉冲计数我建议趁早打消这个念头。1.3 什么时候会用到IO扩展结合实际项目IO扩展芯片的高频使用场景其实非常固定按键矩阵扫描尤其是多组按键需要同时监测的场景LED状态指示板级电源指示、网口link/act指示、运行状态灯一大排拨码开关配置读取设备地址、波特率、工作模式这些需要现场配置的参数继电器/电磁阀等开环驱动控制信号MCU只给高低电平真正驱动由后级功率器件完成切换模拟开关、模拟多路复用器或者给传感器供电做时序控制的VDD开关。在这些场景里I2C扩展芯片不仅好用甚至是唯一合理的选择——因为它们的共同特征是IO数量多、单点速度要求低、逻辑简单、不需要实时性保障。2. 主流I2C IO扩展芯片选型对比与关键参数解读确定走I2C这条路之后真正折磨人的环节就来了具体选哪一款。下面这张表是我自己整理的主流芯片对照基本覆盖了市面上最常见的选择先把大框架铺开后面再逐项拆解。芯片型号位宽输出结构中断引脚地址数量最高频率输入逻辑典型价格区间(参考)PCF8574/8574A8位准双向(开漏强上拉)INT8/8100kHz读前需写10.5-1.5元PCA9535/953816位/8位推挽/开漏可配INT8400kHz配置为输入后直读2-5元MCP2301716位推挽/开漏可配INT81.7MHz配置为输入后直读5-12元TCA953516位推挽/开漏可配INT8400kHz配置为输入后直读2-4元TCA6424A24位推挽/开漏可配INT81MHz配置为输入后直读5-8元AW952316位推挽/开漏可配INT2400kHzLED驱动/GPIO混合3-6元PCA968516路开漏/推挽LED驱动无需61MHz仅输出(PWM)3-8元74HC595(串转并)8位推挽无由CS决定30MHz仅输出0.3-1元这表里有几个细节值得单独拎出来讲。2.1 准双向结构和推挽结构是天壤之别PCF8574属于准双向IO数据手册里那句开漏输出内部强上拉听起来好像人畜无害实际用起来却容易出问题。作为输出使用它输出低电平靠内部MOS管拉低输出高电平靠内部几十千欧上拉电阻带一个LED电流稍大点电压就掉下来了带一个NMOS的栅极关断速度勉强可以开通速度也要看电容大小。更麻烦的是作为输入使用必须先对对应位写1才能松开输出级的控制权去读外部电平否则你读到的永远是低电平。而PCA9535、MCP23017这类设计则完全不同它的每个引脚可以被独立配置为推挽输出或者高阻输入输出高电平时是真正的强驱动输出电流能力是不一样。输入方向不需要写1这一步直接配置方向寄存器后读取即可逻辑上清晰很多。我在实际项目中遇到过PCF8574输出高电平驱动一颗MOS管栅极结果因为上拉电流太小MOS栅极电压爬升慢导致管子一直工作在线性区发热惨重。换用PCA9535的推挽输出后这个问题直接消失。2.2 上电默认状态决定你的板子会不会误动作这一条是我认为选型时最容易被忽略的坑值得单独拿出来警告。绝大多数IO扩展芯片上电复位后IO默认是输入高阻状态个别型号内部带弱上拉。还有少数芯片尤其是一些国产兼容料上电默认状态是输出低电平。想象一下这个场景你扩展IO上接的是一个继电器驱动三极管的基极电阻如果芯片上电瞬间默认输出低电平三极管导通继电器吸合如果继电器后面又带了一个接触器、电磁阀、或者大功率加热棒整个系统在MCU还没运行初始化代码之前就已经开始动作了。这绝对不是危言耸听我见过不止一个项目因为这个问题造成过现场事故。所以在选型时务必去数据手册里查一下Power-On Reset那一节确认IO上电状态。如果可能最好在硬件设计时给扩展IO的输出端加上默认状态保证电路比如继电器的驱动管基极加下拉电阻配合芯片上电高阻特性确保复位期间驱动管可靠关断。同时MCU初始化代码里IO扩展芯片的配置必须在初始化列表里的最前面越快越好。2.3 中断引脚:有和没有完全两种体验PCF8574、PCA9535、MCP23017都有INT引脚但TCA6424A的有些版本、以及一些国产直替型号居然省掉了这个脚。IO扩展芯片主要用于按键矩阵的话中断引脚直接决定了你的按键响应方式有多舒服没有中断引脚就得定时轮询整个扩展芯片的所有输入通道哪怕只有一路变化也要读完整包数据有了中断引脚输入状态一变INT脚拉低主控外部中断一触发精准读取即可。中断功能的差异也很大。PCF8574的中断是只要输入和上次读到的输出状态不一致就会触发它其实无法区分本次变化发生在哪个通道MCP23017则带有比较严格的中断条件寄存器可以配置成高电平触发、低电平触发或者边沿变化触发还能按引脚单独使能中断。如果你的系统对低功耗有要求比如电池供电、经常休眠MCP23017这类支持引脚级中断配置的芯片更合适——它能让MCU一直睡有按键变化再唤醒。2.4 I2C地址数量决定了你最多能挂几片I2C总线通过设备地址区分不同从机PCF8574的地址是1000A2A1A0A2A1A0三根引脚决定具体地址单个I2C总线上最多只能挂8片。PCF8574A则是0111A2A1A0又是8个地址。两套地址加起来16片这是I2C 7位地址架构下的天然限制。你要是想在一个总线上挂16片PCF8574那就要同时兼容8574和8574A两套地址这种操作虽然可行但极其不推荐——代码里的设备地址表会非常混乱。MCP23017和PCA9535同样是3位地址引脚只能挂8片。TCA6424A是24位宽度挂4片就有96个IO一般也够用了。如果没有特殊必要不要设计超过4片的I2C IO扩展芯片总线。总线电容、上拉电阻、从机地址冲突这些问题会在多片挂载的时候一下全冒出来排查起来非常痛苦。2.5 频率上限与上拉电阻的联动很多人在选型时只看芯片是否支持400kHz却忽略了一个基本物理常识I2C总线的最高实际稳定频率不只看从机芯片还得看总线电容和上拉电阻的RC时间常数。挂的芯片越多、走线越长总线电容越大如果上拉电阻选的又太大波形上升沿就变得平缓400kHz模式下极容易出现数据错误。标准I2C规范建议100kHz模式用10kΩ上拉400kHz模式用2.2kΩ到4.7kΩ上拉但具体数值要结合总线上所有设备的输入电容和寄生电容来算。板级设计时如果IO扩展芯片数量多、分布散最好在靠近主控的地方放一组较强的上拉比如2.2kΩ在总线末端再放一组补偿上拉形成阻抗匹配。这个细节在后面调试I2C不通的问题时非常关键。3. I2C IO扩展在固件层面的设计逻辑与告别神坑的心法芯片选定了、硬件也画完了接下来就是固件的正面对刚。网上很多I2C扩展芯片的驱动代码其实都写得很粗糙——能用但谈不上健壮。实际产品里IO扩展芯片的固件设计逻辑跟裸机点个灯完全不是一个量级。3.1 状态缓存和读改写机制使用PCF8574这类准双向芯片时如果要单独把某个输出引脚翻转一下正确做法是先将当前输出状态读回来、修改对应位、再写出去也就是经典的读-改-写操作。但如果固件没有做状态缓存这个过程就会有问题在你读状态的瞬间某个输入引脚的电平可能刚好变化或者另一个输出位被中断服务程序改了读回来的状态本身就是错的再改下去就把别的位也带偏了。我的习惯是在I2C扩展芯片驱动内部维护一份软件缓存每次写操作都基于缓存值进行修改而不是每次读芯片。只有输入模式才真正发起I2C读操作。这样输出引脚的翻转操作只需要一次写事务而且不依赖芯片内部寄存器的实时状态逻辑干净且不容易出错。3.2 读操作时I2C协议的Restart与Stop选择这个是I2C扩展芯片驱动里最容易踩的坑之一读寄存器数据时正确流程是先发设备地址写命令、指定寄存器地址然后发Restart信号再发设备地址读命令读取数据。但有些驱动库的书写得很随意在写地址和读地址之间用了Stop信号而不是Restart。对PCF8574这类没有寄存器寻址的芯片来说影响不明显但对PCA9535、MCP23017这类有寄存器地址的芯片缺了Restart就会导致从机不响应读请求或者读取的数据错位。STM32的HAL库里面HAL_I2C_Mem_Read函数已经封装好了Restart逻辑只要你传入寄存器地址就自动处理。但如果是你自己模拟I2C时序或者移植了一个精简版驱动一定要检查这个细节。我遇到过不止一次代码从PCF8574迁移到PCA9535后读数据怎么都不对最终定位就是原来的模拟I2C库发送读命令前用的是Stop不是Restart。3.3 初始化时序与上电自检的必要性I2C扩展芯片的初始化比普通外设更讲究时序。芯片上电后内部复位需要一段时间不同型号从几百微秒到几毫秒不等。MCU如果在芯片还没完全跑起来之前就发起I2C配置事务大概率会收到NACK然后驱动就报错了。好的做法是初始化时先做一次设备探测扫描I2C总线上对应地址是否存在。代码流程是发送设备地址写命令等待ACK收到ACK则说明芯片已就绪如果没有ACK延时几毫秒再试连续失败后记录错误日志并进入降级模式。这个探测逻辑不仅在上电时有用在运行过程中遇到I2C错误时也可以用来判断到底是总线故障、芯片掉电还是芯片锁死。3.4 I2C错误处理和总线恢复I2C总线有一种非常讨厌的故障模式某个从机在通信中途拉死了SDA线导致整个总线处于总线忙状态所有设备都无法通信。这种故障在正常运行时不多见但在干扰严重、电源抖动、或者主控和扩展芯片供电不同步的场景下时不时就会出现。遇到这种情况标准的恢复手段是对SCL线产生9个时钟脉冲让处于异常状态的从机释放SDA总线。多数I2C扩展芯片在收到9个SCL脉冲后都会复位内部状态机最终释放SDA。STM32的HAL库在HAL_I2C_Init里面虽然做了不少错误恢复机制但最有效的还是主控GPIO模拟这9个时钟脉冲。我建议在工程里加一个i2c_bus_recover函数在初始化失败或连续多次错误时主动调用能省下很多现场运维的麻烦。3.5 软件模拟I2C和硬件I2C的取舍对于IO扩展这种低速率器件软件模拟I2C和硬件I2C在实际效果上差距不大。软件模拟最大的好处是引脚选择自由、调试方便硬件I2C的效率更高但一旦引脚复用配置出错或者和别的外设共享总线问题定位起来更困难。我的经验是如果是简单的按键扫描、LED控制这类低速率场景软件模拟完全够用如果总线上还有其他设备比如传感器、EEPROM并且通信频率较高那么必须用硬件I2C外设并且要确保IO扩展芯片的速率等级不低于总线上的最高速率。4. 项目实战中的血泪教训三个最典型的选型失误案例这是我不断在朋友圈、技术群里强调要提前预防的部分。每次帮人排查问题最后发现大部分都是选型阶段埋下的雷。挑三个最常见的案例出来说吧。4.1 案例一PCF8574做输入读取时的电平假象有个朋友做一个智能家居网关预留了一排拨码开关用于配置设备模式和ID号。他选的是PCF8574然后在读输入之前先写了一遍0xFF让所有IO输出高电平。按数据手册来看这个操作没问题。结果现场发现有些拨码开关拨到ON位置后读到的仍旧是1。排查链路非常折磨人先用万用表量开关两侧电压发现ON时确实到地了然后量PCF8574的引脚电压居然还有2.8V。用示波器看波形发现引脚电压在拨到ON时根本就没降到0而是掉到2.5V左右就稳定住了。最终查明白了PCF8574的准双向IO内部结构里输出高电平靠的是一颗几十千欧的弱上拉作为输入时引脚通过这个上拉电阻接VCC。拨码开关到地之间如果串了一颗保护电阻或者线缆阻抗比较大分压结果就是引脚电平被拉到2.5V左右而这个电压在高电平阈值之上芯片读到的自然是1。解决办法是外部加一颗足够强的下拉电阻不对正确做法是确认驱动能力PCF8574的准双向IO的弱上拉是为了兼容输入场景才存在的做输入时外部应该尽量确保信号源的驱动能力足够强解决方法是把拨码开关的地线直接、可靠接到芯片的GND减少线缆电阻或者在引脚到地之间并一颗1kΩ左右的电阻强制把电压拉到0。这个案例给我们的教训是选型时如果已经确定某个扩展IO只做输入用途那就尽量避免选准双向结构的芯片优先选带方向寄存器的PCA9535或者MCP23017它们的输入模式下引脚是高阻态不存在弱上拉打架的问题。4.2 案例二16路LED指示灯的电流预算超限另一个项目是做一个网络通信设备的面板需要驱动16颗LED指示灯。一开始选的也是PCF8574主控通过它同时控制16个LED。硬件工程师觉得PCF8574是开漏输出低电平点灯很合适于是在IO上串了820Ω限流电阻直接接LED到VCC。麻烦很快就来了PCF8574数据手册写的每个IO最大灌电流是25mA但整个芯片的地引脚极限电流GND pin current不是所有IO电流的简单相加。实际上总电流到了80mA之后芯片内部的地电位就开始抬升逻辑判断开始紊乱有些LED变暗甚至有几路LED不受控。更崩溃的是这种损坏是渐进的一开始不容易察觉板子跑几天后问题才暴露。后来改成PCA9535单引脚输出电流能力只有10mA在3.3V供电下典型灌电流10mA、源电流10mA但它的地引脚能承受更大的总电流再把16颗LED分成两组、每组由不同的GND路径回流问题就解决了。这里的教训有两个一是选型时要看芯片的总电流极限和热阻不能只看单引脚指标二是IO数量多、同时开启率高、单路电流也不小的场景必须考虑总功率预算必要时给LED加三极管阵列或者恒流驱动芯片来做功率解耦。4.3 案例三MCP23017的地址引脚浮空导致随机丢设备第三个案例是MCP23017挂I2C总线总线上同时还有一颗温度传感器和一颗EEPROM。MCP23017的A0、A1、A2三个地址引脚在原理图上标了地址选择但板上只是预留了0Ω电阻的位置默认不焊等于悬空。按照MCP23017的数据手册A0-A2引脚内部有下拉电阻悬空应该等效于地址000和设计一致。但实际测试发现每次断电重启后有大约20%的概率扫描不到这颗MCP23017而温度传感器和EEPROM都正常。反复排查发现MCP23017的数据手册在不同版本之间对地址引脚内部上下拉的描述居然有矛盾且芯片在电源上电瞬间如果引脚悬空且耦合了干扰内部逻辑可能跳到非预期状态导致总线上出现两个地址都不应答的情况。这事的最终解决方案最土也最有效PCB上把这几个引脚加2.2kΩ下拉电阻硬件上强制固定地址。从这之后我再也没有在I2C扩展芯片上让地址引脚悬空过不管数据手册写没写内部上下拉。5. 选型决策树与硬件设计当中的几个隐藏加分项前面讲了芯片差异也讲了固件要点再综合出一条快速的选型路径。很多刚接触I2C扩展的朋友喜欢拿着一堆型号反复对比其实只要按下面的逻辑一步步过滤答案几轮下来就出来了。5.1 给我的选型决策路径先看第一层需求——这路IO是只做输入、只做输出还是输入输出混合且需要动态切换只有输出并且数量不大8-16路直接看PCF8574或者TCA9535都行PCF8574成本最低只有输入选择带方向寄存器的高阻输入芯片PCA9535、MCP23017、TCA9535不要选PCF8574输入输出混合且需要运行中切换建议MCP23017它的IOCON寄存器可以配置多种工作模式引脚中断也最灵活需要LED呼吸、PWM调光效果选AW9523或者PCA9685前者带恒流LED驱动后者支持12位PWM输出。再看第二层需求——主控对实时性要求高吗按键类应用选择带中断引脚的芯片并且确保固件里中断引脚边沿触发配置正确纯粹点灯、做状态指示中断引脚无所谓IO数量才重要有低功耗休眠需求必须选择支持引脚级中断唤醒的MCP23017系列其他芯片要么不支持、要么唤醒后还需要全总线扫描。最后看第三层需求——工作环境有没有干扰、电源干净不干净工业现场、走线较长、电机继电器在附近选择推挽输出、内建ESD保护更好的TCA系列3.3V和5V混接的总线上注意用双向电平转换芯片把I2C总线拉到同一逻辑电平不能直接靠上拉硬怼。5.2 硬件设计里容易被忽视的细节扩展芯片的硬件设计有一些容易踩坑的细节值得专门列一下。VCC和GND去耦电容别省每颗芯片的VCC引脚旁边至少放一个100nF陶瓷电容如果PCB空间允许再加一个10μF钽电容或者电解电容。IO扩展芯片在批量翻转引脚时内部电流瞬变不小没有去耦电容的话电源毛刺直接通过I2C总线耦合到主控侧轻则通信错误重则主控复位。地址引脚不要悬空哪怕是数据手册明确写了内部有下拉也必须用外部电阻固定。原因前面案例已经讲了悬空引脚在干扰环境下有概率跳到非预期状态。中断引脚尽量用主控的独立外部中断输入不要和普通GPIO复用更不要接到I2C总线上。否则按键按下时中断标志被I2C总线主设备读取的过程中发生冲突数据包会错乱这是非常隐蔽的bug。如果板上的I2C总线上还有其他传感器务必确认所有设备的地址没有冲突。I2C设备地址是7位但具体到某个型号可能只用到部分地址位或者芯片内部默认地址和高两位的组合不同。别偷懒用I2C扫描逻辑把所有设备地址一次性打印出来检查有没有重号。5.3 一个推荐的I2C扩展芯片初始化函数框架下面这个函数是我在STM32上惯用的一个I2C扩展初始化自检流程它的思路是通用的可以直接迁移到其他MCU平台typedef struct { uint8_t addr; uint16_t out_cache; // 当前输出状态的软件缓存 uint8_t err_count; // 连续通信错误计数 } iox_dev_t; int iox_init(iox_dev_t *dev) { HAL_StatusTypeDef status; uint8_t tmp; // 1. 多尝试几次地址探测等待芯片上电就绪 for (int i 0; i 5; i) { status HAL_I2C_IsDeviceReady(hi2c1, dev-addr, 3, 10); if (status HAL_OK) break; HAL_Delay(2); } if (status ! HAL_OK) { return IOX_ERR_NODEV; } // 2. 对MCP23017这类带方向寄存器的芯片先配置所有引脚为输入 // 对PCF8574这类准双向结构写0xFF让所有引脚处于高电平输入态 // 3. 初始化软件缓存全为输入态/关断态 dev-out_cache 0xFFFF; // 4. 可选开启中断配置中断触发条件 // ... dev-err_count 0; return IOX_OK; } // 输出翻转示例带缓存保护 int iox_set_output(iox_dev_t *dev, uint8_t pin, uint8_t level) { uint16_t cache dev-out_cache; if (level) cache | (1U pin); else cache ~(1U pin); // 写回芯片 // HAL_I2C_Mem_Write(hi2c1, dev-addr, 0x00, I2C_MEMADD_SIZE_16BIT, // (uint8_t*)cache, 2, 10); // 如果写成功了再更新软件缓存 dev-out_cache cache; return IOX_OK; }这套代码的结构本质上把软件状态和芯片状态做了一层隔离每一次输出操作都基于缓存不依赖芯片内部寄存器回读既能避免上面讲的读改写不一致问题也方便在通信故障时做降级处理。6. 绕过IO扩展什么时候应该换一条技术路线IO扩展芯片很好用但有时候它并不是最优解。与其在一颗扩展芯片上死磕不如先退一步想想这个IO需求能不能从源头上减少6.1 用串行协议芯片替代并行IO扩展如果项目里的LED灯数量特别多、呼吸灯效果也多本质上还是在做花式点灯那PCA9685这种专门为LED设计的PWM驱动芯片明显更合适。如果需求是几十个按键占用I2C总线去扩展键盘矩阵可能是浪费直接用专用的键盘控制芯片比如TCA8418这种带26个IO和按键扫描逻辑的器件不仅省I2C带宽固件也简单很多。它内部有自己的按键消抖和FIFO读一次寄存器就能获得一整个按键事件。6.2 是否有必要直接换大引脚主控当IO需求超过32路并且又有不少对速度、实时性有要求的信号I2C扩展芯片带来的软件复杂度会急剧上升。这种情况下直接换一颗更多引脚的MCU常常是更经济的选择——虽然芯片单价高了几块钱但省掉了一堆IO扩展芯片、去耦电容、上拉电阻、PCB走线的布局成本固件结构也简单了至少一个量级。我见过一个案例原本用STM32F103C8T6设计了8颗PCF8574做64路DI光故障排查就花了两周。后来换成STM32F103RCT6144引脚版本直接原生IO一版就打样成功。在这个场景里I2C扩展方案不是不能用而是引入的系统复杂度远超节省的那点成本。6.3 权衡表格什么时候能用I2C扩展什么时候该换最终再给一个简单的判断维度应用场景是否适合I2C扩展替代方案按键数量少于40个适合带中断的I2C扩展很舒服键盘矩阵扫描芯片TCA8418纯LED显示且数量多适合PCA9685是神器移位寄存器恒流源继电器驱动适合但注意上电状态专用IO扩展大功率驱动高速PWM输出不适合定时器原生GPIO软串口/时序敏感信号不适合换大引脚MCU或用UART扩展模拟量采集不适合I2C ADC芯片如PCF8591核心原则就一句话需要的是开关级别逻辑的IOI2C扩展是好帮手需要的是时序或者高速信号的IO别指望扩展芯片老老实实换主控或者用专用通信芯片。实际项目里我个人的习惯是先把IO需要做哪些事、各自的速度和时序要求列成一张表再决定哪些IO放在主控原生引脚上哪些放I2C扩展芯片上哪些用串行协议芯片替代。这个方法看起来老土却能在原理图设计阶段省掉后面所有没有意义的折腾。最后再分享一个小习惯拿到一颗新的I2C扩展芯片先别急着画原理图先在开发板上用逻辑分析仪抓一遍它上电后的完整I2C启动时序确认地址探测能过然后逐位翻转所有IO再读回输入全部过完再动设计。这一步多花一个小时后面至少省一个星期。
RELATED

相关推荐

Rust周刊2026W36 | rustup 1.29.1 更名 target tuple、Wasmi 2.0 提速 2.2 倍、Box map 稳定化、aarch64 FFI 传参修复…

Rust周刊2026W36 | rustup 1.29.1 更名 target tuple、Wasmi 2.0 提速 2.2 倍、Box map 稳定化、aarch64 FFI 传参修复…

rustup 1.29.1 弃用 target triple;编译内存降至 4GiB、智能指针 map 稳定化;修复标准库 UB 与 FFI 传参;Wasmi 2.0发布,Rustdoc 快 33%。 🦀 Rust 工具链更新 🔧 编译器 🆕 新功能 safestac…

📅 2026/9/9 5:15:03
用定时IC替代单片机:小家电固定档位定时的低成本方案

用定时IC替代单片机:小家电固定档位定时的低成本方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/9 5:15:03
轻量级消息代理 hermes-agent 实践:从部署调优到生产避坑

轻量级消息代理 hermes-agent 实践:从部署调优到生产避坑

做消息中间件选型的时候,我一度被搞得非常头疼。团队里几个服务之间需要异步通知,数据量不算大,但业务方对实时性要求很高,我们又不想为这点流量引入一套完整的重型消息队列——毕竟那意味着要维护好几个新组件,光权限…

📅 2026/9/9 5:10:03
MORE NEWS

更多资讯

📰

PHP后端进阶:掌握PHP-FPM生命周期、异常处理与依赖管理

做了十年PHP后端,带过不少人,也看过太多人在同一个地方卡住。很多人写了三五年业务代码,增删改查很溜,可一旦遇到线上性能问题、疑难Bug、别人写的烂代码,就手足无措。问题出在哪?不是PHP语法不熟&#xff…

📰

STM32从源码到烧录:编译原理、固件生成与烧录实操全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

国赛 9 月 10 日开赛、研赛 9 月 23 日接棒:两场连打的窗口里,研究生场报名只剩 11 天

国赛 9 月 10 日开赛、研赛 9 月 23 日接棒:两场连打的窗口里,研究生场报名只剩 11 天 2026 年下半年最大的一场数学建模赛事马上开赛。全国大学生数学建模竞赛(高教社杯)定于 9 月 10 日 18 时发题,9 月 13 日 20 时收…

📰

时变啮合刚度计算方法详解:基于石川公式的MATLAB实现与工程应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

MODBUS RTU调试实战:从协议原理到freemodbus移植

1. 为什么MODBUS至今仍是嵌入式现场调试的“硬通货”?你手头那块刚焊好的STM32F103开发板,串口线一插,示波器上跳着不规则的方波,Modbus Poll发出去的0x03读寄存器请求在Wireshark里抓不到回包——这时候翻遍Keil工程里的freemodb…

📰

测试用例设计Day2:等价类、边界值与场景法实战解析

1. 从“会写用例”到“写好用例”:第一阶段Day2到底在练什么如果你点进这篇内容,大概率正处于测试用例设计的学习爬坡期。昨天还在纠结测试用例的格式、字段、模板长得什么样,今天就开始被等价类、边界值、场景法这些名词砸得晕头转向——没错…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬