十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

I2C开漏输出与上拉电阻选型:从物理层到调试实战

I2C开漏输出与上拉电阻选型:从物理层到调试实战 1. 从一次诡异的通信失败说起几年前调一块传感器板子主控和从设备离得不到三厘米走线也规规矩矩结果上电之后总线死活拉不起来示波器一抓波形高电平只有1.2V左右低电平倒是干净利落。当时第一反应是上拉电阻焊错了拆下来一量4.7k没毛病。换了个1.5k的上去波形勉强能看但一挂第二个从设备又崩了。折腾了大半天才反应过来——问题根本不在电阻值而在于我对I2C物理层开漏这件事的理解一直是模糊的。这个经历让我意识到很多人学I2C是从时序图和数据帧格式入手的知道起始条件、应答位、7位地址但一问到为什么SDA和SCL必须接上拉电阻为什么不能像SPI那样直接推挽驱动就答不上来了。而恰恰是这个物理层的设计决定了I2C能挂几十个设备、能做双向通信、能容忍不同电压域混接。不理解开漏后面所有关于上拉电阻计算、总线电容、上升沿时间的讨论都是空中楼阁。这篇内容就是想把两线制物理层这件事从头讲透。适合已经会用I2C但没深究过硬件层的人也适合刚接触嵌入式、被时序图绕晕的新手。我会从开漏输出的结构讲起把为什么必须开漏这个问题拆成几个层次再落到上拉电阻怎么选、总线电容怎么算、实际调试中怎么用逻辑分析仪定位物理层问题。全程不堆公式但该算的地方一定给你算清楚。2. 开漏输出到底是个什么结构2.1 从推挽输出的尴尬讲起要理解开漏先得知道它的对立面——推挽输出。推挽结构说白了就是一对互补的MOS管上面一个PMOS接电源下面一个NMOS接地输出端从两个管子中间引出来。输出高电平时PMOS导通、NMOS截止引脚被拉到VCC输出低电平时PMOS截止、NMOS导通引脚被拉到GND。上下两个管子一推一拉所以叫推挽。推挽的好处是驱动能力强上升沿和下降沿都很陡适合高速信号。但它有个致命问题两个设备的推挽输出不能直接接在一起。假设设备A输出高电平PMOS导通引脚接VCC设备B输出低电平NMOS导通引脚接GND那么从VCC到GND之间就形成了一条低阻抗通路瞬间大电流流过两个管子轻则发热、重则烧毁。这就是所谓的总线冲突。SPI之所以能用推挽是因为它的拓扑是一主多从加独立的片选线同一时刻只有被选中的从设备和主设备在通信不会出现两个输出端同时驱动一根线的情况。但I2C不一样它是真正的多主多从总线任何时刻都可能有多个设备想说话而且SDA线是双向的——主设备发数据的时候从设备要能拉低它做应答从设备发数据的时候主设备也要能拉低它。这种场景下推挽结构根本没法用。2.2 开漏输出的工作原理开漏输出Open-Drain的结构其实很简单只有下面一个NMOS管没有上面的PMOS。NMOS的栅极接内部驱动逻辑漏极接到引脚源极接地。当内部逻辑输出高电平时NMOS截止引脚处于高阻态Hi-Z相当于悬空既不输出高也不输出低。当内部逻辑输出低电平时NMOS导通引脚被拉到GND输出低电平。问题来了高阻态的时候引脚是悬空的怎么产生高电平答案是外部上拉电阻。在SDA和SCL线上各接一个电阻到VCC当所有设备都处于高阻态时上拉电阻把线拉到VCC这就是高电平只要有任何一个设备把NMOS导通线就被拉到GND这就是低电平。所以I2C的物理层本质是一个**线与逻辑**总线为高当且仅当所有设备都释放总线只要有一个设备拉低总线就是低。这个特性天然解决了总线冲突问题——两个设备同时驱动一个想拉高一个想拉低结果就是低电平不会有短路电流。而且这个线与逻辑正好实现了I2C的仲裁机制多个主设备同时发起传输时谁先发出低电平谁就赢得总线发出高电平的那个发现自己读回的电平和发出的一致就继续不一致就退出。2.3 为什么不能用推挽替代有人可能会想既然开漏这么麻烦还要外接电阻能不能用推挽加个方向控制理论上可以但实际不可行。原因有三第一方向切换的时机无法精确控制。I2C的SDA线在一个时钟周期内可能要经历主设备驱动→从设备应答→主设备驱动的多次方向切换如果每次都要软件或硬件切换引脚方向时序根本对不上。开漏结构天然支持双向不需要任何方向控制。第二多设备仲裁无法实现。推挽结构下如果两个主设备同时输出一个高一个低直接短路。开漏的线与特性让仲裁变得自然——不需要额外的仲裁电路物理层就完成了。第三电压域兼容。开漏输出的高电平由外部上拉电阻决定上拉到3.3V就是3.3V逻辑上拉到5V就是5V逻辑。这意味着一个3.3V的主控可以和一个5V的从设备挂在同一根总线上只要上拉到5V主控引脚需要容忍5V或者做电平转换。推挽输出做不到这一点因为它的高电平被内部VCC固定死了。注意虽然开漏让电压域兼容成为可能但实际混接时一定要确认低压侧引脚的耐压值。3.3V的MCU引脚如果上拉到5V长期工作可能会损坏这种场景建议用专用的I2C电平转换芯片。3. 上拉电阻选大了不通信选小了烧管子3.1 上拉电阻的双重角色上拉电阻在I2C总线里扮演两个角色提供高电平和限制低电平时的电流。这两个角色是矛盾的——电阻越大低电平时流过NMOS的电流越小但高电平时给总线电容充电的速度越慢上升沿越缓电阻越小上升沿越陡但低电平时电流越大可能超过NMOS的灌电流能力。所以选上拉电阻本质上是在上升沿时间和灌电流之间找平衡。I2C标准里给了一个经典值4.7kΩ但这个值不是万能的它对应的是100kHz标准模式、总线电容约200pF的场景。实际项目里必须根据你的速率和总线电容重新计算。3.2 上升沿时间的计算I2C的上升沿不是理想的阶跃而是RC充电曲线。总线电容包括PCB走线电容、引脚电容、器件电容和上拉电阻构成一个RC网络上升时间常数τ R × C。标准规定上升沿时间从0.3VDD到0.7VDD不能超过一定值模式速率最大上升沿时间标准模式100kHz1000ns快速模式400kHz300ns快速模式1MHz120nsRC充电从0.3VDD到0.7VDD的时间约为0.847τ所以R_max t_r / (0.847 × C_bus)举个例子总线电容200pF跑400kHz快速模式t_r最大300ns那么R_max 300ns / (0.847 × 200pF) ≈ 1.77kΩ。也就是说如果你用4.7kΩ上升沿会超标波形会变成圆角高速下可能被误判为无效电平。反过来如果总线电容很小比如只有50pF跑100kHzR_max 1000ns / (0.847 × 50pF) ≈ 23.6kΩ这时候用4.7kΩ绰绰有余甚至可以用10kΩ省电。3.3 灌电流的限制上拉电阻的下限由NMOS的灌电流能力决定。当总线被拉低时电流从VCC经过上拉电阻流过NMOS到GND这个电流不能超过器件的额定灌电流IOL。I2C标准规定标准模式和快速模式下IOL最大3mA快速模式下最大20mA但实际器件往往只有3mA左右。R_min (VDD - V_OL) / IOL其中V_OL是低电平输出电压通常取0.4V。以3.3V系统、IOL3mA为例R_min (3.3 - 0.4) / 3mA ≈ 967Ω。所以上拉电阻不能小于约1kΩ否则灌电流超标。3.4 实际选型的经验值把上面两个约束合起来上拉电阻的合理范围是R_min ≤ R ≤ R_max实际项目中我一般这样选100kHz、总线电容200pF4.7kΩ最稳妥的默认值。400kHz、总线电容100pF2.2kΩ到3.3kΩ。400kHz、总线电容100~200pF1.5kΩ到2.2kΩ。1MHz快速模式通常需要1kΩ以下同时要严格控制总线电容走线尽量短。低功耗场景可以适当加大到10kΩ但速率要降下来。提示如果总线上挂了多个设备每个设备的引脚电容通常5~10pF和PCB走线电容约1pF/cm都要算进去。一根10cm的走线加上5个设备电容可能就到100pF了。这也是为什么I2C总线不能拉太长的原因——电容太大上升沿根本起不来。3.5 一个反直觉的现象上拉电阻小了反而不通信热词里有个i2c上拉电阻小了不通信这个现象确实存在而且很多人想不通——电阻小不是驱动能力更强吗怎么会不通信原因通常有两个。第一灌电流超标导致低电平抬高。如果上拉电阻太小NMOS导通时流过的电流超过额定值NMOS可能进入饱和区漏源电压V_DS升高低电平不再是0.4V而是1V甚至更高从设备可能识别不到低电平。第二多个设备同时拉低时电流叠加。如果总线上有多个设备同时输出低电平每个设备分担的电流可能不均匀某个设备承受的电流过大导致其低电平异常。还有一种情况是上拉电阻太小导致上升沿过冲。电阻小、电容小的时候RC时间常数很小上升沿极快可能引起信号反射和振铃波形上出现尖峰逻辑分析仪可能误判。这种问题在长走线、阻抗不匹配的场景下更明显。所以电阻小不通信不是玄学而是灌电流、电平阈值、信号完整性综合作用的结果。遇到这种情况先用示波器看低电平的实际电压值如果高于0.4V基本就是灌电流问题。4. 总线电容I2C速率的隐形天花板4.1 总线电容从哪来I2C标准规定总线电容不能超过400pF这个数字不是随便定的它直接限制了上拉电阻的最小值和总线的最大长度。总线电容主要来自三部分器件引脚电容每个I2C设备的SDA和SCL引脚都有输入电容典型值5~10pF。挂10个设备就是50~100pF。PCB走线电容取决于走线宽度、层叠结构和介质材料经验值约1pF/cm微带线。一根20cm的走线约20pF。连接器和线缆电容如果用排线或连接器引出电容会显著增加排线可能达到几十pF。把这些加起来如果超过400pF即使上拉电阻选得很小上升沿也起不来。这时候有几个解决思路第一降低速率。100kHz对上升沿的要求比400kHz宽松得多同样的电容下可以用更大的电阻。第二缩短走线、减少设备。把总线电容控制在400pF以内是最直接的办法。第三用I2C缓冲器/中继器。这类芯片把总线分成多段每段独立驱动等效降低了单段电容。常见的有PCA9515、TCA9517等。第四改用其他总线。如果设备太多、距离太远I2C本身就不适合考虑SPI点对点、推挽、高速或CAN差分、抗干扰、长距离。4.2 用逻辑分析仪看物理层问题逻辑分析仪是调I2C的利器但很多人只用它看协议解码忽略了物理层信息。实际上逻辑分析仪抓到的波形能告诉你很多上升沿是否圆角如果高电平上升缓慢说明RC时间常数太大要么电阻太大要么电容太大。低电平是否干净如果低电平有毛刺或抬高可能是灌电流问题或地线干扰。时钟占空比是否正常SCL的占空比应该接近50%如果高电平时间明显偏长可能是上拉太弱。是否有总线冲突如果SDA在非预期时刻被拉低可能是多主仲裁或设备异常。用逻辑分析仪的时候采样率要足够高。100kHz的I2C采样率至少1MHz才能看清细节400kHz的话建议10MHz以上。另外逻辑分析仪的输入电容也会加载到总线上如果探头电容较大比如10pF以上可能会让原本勉强能用的总线变得更糟。这种时候用示波器的高阻探头通常10pF左右更合适。4.3 一个容易忽略的细节地线I2C是单端信号参考地。如果主设备和从设备之间的地线阻抗较大或者地线上有噪声低电平的参考点就会漂移导致逻辑误判。长距离连接时地线要足够粗最好和SDA、SCL一起走减少回路面积。如果总线上有电机、继电器等大电流设备地线噪声可能直接干扰I2C通信这时候要考虑隔离或者改用差分总线。5. 开漏带来的那些副作用与应对5.1 上升沿慢导致的速率瓶颈开漏结构最大的代价就是上升沿慢。推挽输出的上升沿由管子的驱动能力决定可以做到纳秒级开漏输出的上升沿由RC充电决定微秒级是常态。这就是为什么I2C的速率远低于SPI——SPI可以轻松跑到几十MHzI2C标准模式只有100kHz快速模式400kHz快速模式1MHz高速模式3.4MHz但高速模式下用了额外的电流源辅助上拉已经不是纯开漏了。理解这一点你就明白为什么I2C不适合传大量数据。它适合的是控制类通信——配置寄存器、读传感器值、访问EEPROM数据量小、速率要求不高、但需要多设备共享总线。如果你要传图像、音频I2C绝对不是好选择。5.2 总线锁死与恢复开漏结构还有一个经典问题总线锁死。如果从设备在传输过程中复位或者主设备在某个时刻异常SDA可能被某个设备一直拉低总线就卡死了。这时候主设备发什么从设备都不响应因为SDA一直是低。恢复的办法是手动发送时钟脉冲。主设备把SCL配置为推挽输出或者用GPIO模拟发送9个以上的时钟脉冲让从设备把剩余的数据位移出去释放SDA。然后发送一个停止条件总线就恢复了。这个技巧在实际项目中非常有用尤其是从设备可能随时上下电的场景。提示很多MCU的I2C外设支持总线恢复功能本质上就是自动发送时钟脉冲。如果你的MCU不支持可以用GPIO模拟I2C来做恢复恢复完再切回硬件I2C。5.3 电平转换与电压域混接开漏的另一个好处是方便做电平转换。一个经典的电路是低压侧3.3V和高压侧5V各接一个上拉电阻SDA和SCL线通过一个N沟道MOS管连接栅极接低压侧VCC源极接低压侧SDA漏极接高压侧SDA。当低压侧拉低时MOS管导通高压侧也被拉低当高压侧拉低时MOS管的体二极管先导通然后MOS管导通低压侧也被拉低。这个电路不需要额外的方向控制成本极低是I2C电平转换的标配。但要注意这种电路对MOS管的选型有要求阈值电压要低于低压侧VCC导通电阻要小结电容要小。如果MOS管选得不好上升沿会变得更慢高速下可能不工作。5.4 与推挽输出的对比总结特性开漏输出推挽输出高电平驱动依赖外部上拉内部PMOS驱动低电平驱动内部NMOS驱动内部NMOS驱动上升沿速度慢受RC限制快多设备共享支持线与逻辑不支持会短路双向通信天然支持需要方向控制电平转换方便困难功耗低电平时有静态电流低电平时也有静态电流典型应用I2C、SMBus、PMBusSPI、UART、GPIOPMBus和I2C的区别也在这里——PMBus是基于I2C的电源管理协议物理层完全一样都是开漏加两线制区别在协议层。所以理解了I2C的物理层PMBus的物理层也就通了。6. 从物理层到实际调试几个真实案例6.1 案例一上拉电阻位置放错有一次画板子上拉电阻放在了主设备旁边从设备在板子另一端走线20cm。结果100kHz都跑不稳波形上升沿明显变缓。原因是上拉电阻到从设备之间的走线电容和电阻构成了额外的RC延迟等效于上拉电阻变大。正确的做法是把上拉电阻放在总线中间或者靠近从设备让充电电流的路径最短。如果总线很长可以在两端各放一组上拉电阻等效减小充电电阻。6.2 案例二多个上拉电阻并联另一个常见错误是每个设备模块上都带了上拉电阻插到同一根总线上结果多个电阻并联等效电阻变得很小。比如4个模块各带4.7kΩ并联后只有1.175kΩ灌电流可能超标。这时候要么去掉多余的上拉电阻要么换成更大的值。实际项目中上拉电阻应该只在总线的一端或两端放不要每个设备都放。6.3 案例三逻辑分析仪探头电容导致通信失败调试的时候用逻辑分析仪抓波形结果一接上探头通信就失败拔掉就正常。这是因为逻辑分析仪的输入电容可能10~20pF加载到总线上让原本勉强满足上升沿要求的总线超标了。解决办法是换用低电容探头或者用示波器的高阻探头或者把上拉电阻适当减小。这个坑很隐蔽因为你会以为是代码问题实际上是测试设备改变了总线特性。6.4 案例四EEPROM写入时的总线电容变化I2C EEPROM在写入周期内会拉低SDA表示忙状态这时候总线电容可能因为EEPROM内部电路的变化而改变。如果上拉电阻选得临界写入时可能通信失败读取时正常。这种问题需要用示波器观察写入周期的波形确认上升沿是否满足要求。解决方法是适当减小上拉电阻或者降低速率。7. 写在最后的一些个人体会调I2C这么多年最大的感受是物理层的问题往往比协议层更难查。协议层的问题逻辑分析仪一抓就知道地址错了、应答丢了、时序不对一目了然。但物理层的问题——上升沿慢、低电平抬高、总线电容超标——需要示波器、需要计算、需要对开漏结构的深刻理解。我的建议是每次画I2C板子的时候先把这几个数算一遍总线电容大概多少、上拉电阻选多大、上升沿时间是否满足速率要求、灌电流是否超标。这几个数花十分钟算清楚能省掉后面几天的调试时间。另外手边常备一个示波器逻辑分析仪看协议示波器看物理层两个配合用I2C的问题基本无处遁形。最后分享一个小技巧如果你不确定上拉电阻选多大可以先焊一个可调电阻或者几个电阻的并联焊盘调试的时候用示波器看上升沿边调边看找到最合适的值再固定下来。这个方法比纯计算更靠谱因为实际总线电容往往和估算有出入。
返回列表