欢迎光临
我们一直在努力

从 I2C 的开漏输出说起:一文搞懂推挽输出、开漏输出与上拉电阻

从 I2C 的开漏输出说起:一文搞懂推挽输出、开漏输出与上拉电阻

前言:最近在学 I2C 通信,资料里反复出现一句"I2C 的 SDA/SCL 必须配置为开漏输出,外接上拉电阻"。为什么要"必须"?开漏到底是什么?它和最常用的推挽输出有什么区别?顺着这条线,我把 GPIO 的几种常见输出方式(推挽、开漏、开集、上拉/下拉、准双向口)一次梳理清楚,做成这篇学习笔记,配了多张示意图,希望能帮你把这块知识一次打通。


一、问题的起点:引脚为什么需要"输出结构"?

单片机的 GPIO 引脚,本质上是一个可以由程序控制的"电子开关"。但我们对外输出的不只是"通/断"两个状态,而是高电平、低电平两种电压,有时还需要"高阻态"(什么都不驱动)。

要实现这些能力,就要靠引脚内部的输出驱动级。不同时代的芯片、不同的应用场景,给出了不同的驱动级方案,于是就有了:

  • 推挽输出(Push-Pull)——最常用、驱动能力最强的方案
  • 开漏输出(Open-Drain)——多设备共享总线的方案(I2C 的选择)
  • 开集输出(Open-Collector)——开漏的三极管"前辈"
  • 准双向口——51 单片机的经典方案
  • 以及配合它们使用的上拉/下拉电阻

下面从最常用的推挽输出讲起。


二、推挽输出(Push-Pull):两管轮流导通,又"推"又"挽"

2.1 电路结构

推挽输出的驱动级由**一只 P-MOS(上管)+ 一只 N-MOS(下管)**串联组成:

  • P-MOS 的源极接 VDD,漏极接输出引脚;
  • N-MOS 的漏极接输出引脚,源极接 GND;
  • 两管的栅极接同一个控制信号(P-MOS 侧经过反相器),保证两管永远相反:一个导通,另一个必然截止。
    在这里插入图片描述

2.2 工作原理

控制输入P-MOS(上管)N-MOS(下管)引脚电平
输出 1 导通 截止 VDD(电流从 VDD 经 P 管"推"向负载)
输出 0 截止 导通 0V(电流经 N 管"挽"回 GND,也叫灌电流)

所谓"推挽",就是这个名字的字面含义:输出高电平时,上管把电流"推"出去(拉电流);输出低电平时,下管把电流"拉"回来(灌电流)。两个管子像拔河一样轮流发力、互补工作,任何时刻都只有一个导通。

2.3 优缺点

优点:

  • 驱动能力强:高低电平都由 MOS 管主动驱动,输出阻抗低(典型几十欧姆),既能输出大电流也能吸收大电流;
  • 开关速度快:边沿陡峭,高低电平切换无需等待,适合高速信号(SPI、UART、普通 GPIO 翻转);
  • 无需外部元件:接上就能用,省 PCB 面积。
  • 缺点:

  • 输出不能并联:这是致命限制。假设两个推挽输出接到同一根线上,A 输出高、B 输出低,那么 A 的 P-MOS 和 B 的 N-MOS 就会同时导通——电流从 A 的 VDD 直接穿过两个管子流进 B 的 GND,形成近似短路的"直通电流",轻则电平错误,重则烧毁芯片;
  • 高电平被锁死:输出高电平恒等于芯片自己的 VDD,3.3V 的 MCU 只能输出 3.3V,没法直接输出 5V。
  • 一句话总结:推挽输出是"单人驾驶"——力气大、速度快,但一条路上只能有一辆车。


    三、开漏输出(Open-Drain):只保留"拉低"的能力

    3.1 电路结构:把上管拿掉

    开漏输出的思路非常直接:把推挽结构里的 P-MOS 上管去掉,只留下 N-MOS 下管,并且把它的漏极(Drain)直接引出到引脚——“开漏”(漏极开路)这个名字就是这么来的。

    在这里插入图片描述

    3.2 为什么必须接上拉电阻?

    去掉上管之后,引脚只剩两种状态:

    • 输出 0:N-MOS 导通,引脚被牢牢接到 GND,输出稳定的低电平;
    • 输出 1:N-MOS 截止,引脚既不接 VDD 也不接 GND,悬空了——这就是"高阻态",引脚上的电压完全不确定。

    所以开漏输出天生不能主动输出高电平,必须外接一个上拉电阻 Rp 到电源:

    • N-MOS 截止时,没有电流流过 Rp,引脚被电阻"温和地"拉到 VDD_PU,输出高电平;
    • N-MOS 导通时,电流从 VDD_PU 经 Rp 流入 N-MOS 到地,电阻分压后引脚≈0V(低电平)。

    注意一个关键细节:高电平的电压值由上拉电源 VDD_PU 决定,而不是芯片自己的 VDD——这是开漏输出最重要的特性,后面讲电平转换会用到。

    3.3 优缺点

    优点:

  • 多个输出可以安全并联(线与)——这是开漏存在的核心理由,下一节细讲;
  • 高电平电压可自由定义:上拉到 5V 就输出 5V,上拉到 1.8V 就输出 1.8V,天然支持电平转换;
  • 无直通短路风险:即使两个设备状态"打架",最坏情况也只是 VDD/Rp 的有限电流,被电阻限制住了,不会烧芯片。
  • 缺点:

  • 高电平驱动弱、上升沿慢:高电平是靠电阻"被动"拉起来的,引脚和走线都有寄生电容 C,上升时间 ≈ Rp × C。Rp 越大,边沿越缓,通信速率上不去;
  • 输出低时有静态功耗:N-MOS 常通、总线常为低时,Rp 上持续流过 VDD²/Rp 的电流;
  • 需要外接电阻:多一个元件,PCB 多占一点面积。
  • 一句话总结:开漏输出是"只能踩刹车,不能踩油门"——油门(高电平)交给外接的上拉电阻来踩。


    四、线与逻辑(Wired-AND):为什么 I2C 非用开漏不可?

    现在回到开头的问题。I2C 是一条多设备共享总线:多个主机的 SDA 都接在同一根线上,任何设备都要既能发数据又能让出总线。

    如果用推挽输出会怎样?假设设备 A 要发"1"、设备 B 要发"0",A 的 P-MOS 输出 3.3V、B 的 N-MOS 拉到 0V,两个低阻抗输出顶在一条线上——这就是第二节说的直通短路,电流只受两个 MOS 内阻限制,总线直接冒烟。

    换成开漏 + 上拉后,情况完全不同:

    在这里插入图片描述

    • 任何一个设备导通拉低 → 总线就是低电平(其他设备根本拉不动它,因为它们是高阻态);
    • 只有全部设备都释放(截止)→ 上拉电阻才把总线拉成高电平。

    从逻辑上看:总线 = 设备A输出 AND 设备B输出 AND 设备C输出——把几根输出线直接接在一起,就"免费"得到了一个与门,所以叫线与(Wired-AND)。

    线与特性正是 I2C 协议的两大机制的物理基础:

  • 多主仲裁:两个主机同时发数据时,谁发 0 谁赢得总线;发 1 的主机检测到总线是 0,自动退让;
  • 时钟拉伸(Clock Stretching):慢速从机可以把 SCL 摁在低电平,强迫主机等待,主机毫无脾气。
  • 此外,共享中断线(多个传感器的 INT 引脚并联接到 MCU 一个 GPIO)、One-Wire 单总线、SMBus,用的都是同一套思路。很多电压比较器(如 LM393)的输出也做成开集结构,就是为了方便并联和跨电平驱动。


    五、开漏的第二大杀手锏:免费的电平转换

    3.3V 的 MCU 要驱动一个需要 5V 高电平的旧外设,推挽输出直接傻眼(它最高只能输出 3.3V)。而开漏输出只需把上拉电阻接到 5V:

    在这里插入图片描述

    • 输出 0 时:MCU 拉低,总线 = 0V;
    • 输出 1 时:MCU 释放进入高阻态,5V 电源经 Rp 把总线拉到 5V,外设可靠识别。

    MCU 内部的 N-MOS 全程只承受 0~3.3V 一段的电压,高电压由电阻"扛"了。

    ⚠️ 重要前提:必须确认 MCU 引脚是 5V 耐压(FT / 5V-tolerant) 引脚。"开漏"只是说明芯片不会主动驱动高电平,不代表输出管能承受任意高的漏极电压——普通引脚上拉到 5V 时,漏极-衬底的寄生二极管会导通钳位,甚至损坏芯片。设计前务必查数据手册的绝对最大额定值。

    顺带一提:双向信号(如 I2C 的 SDA)跨电压域时,简单的单向上拉不够用,常用 BSS138 之类的 MOS 管搭建双向电平转换电路,I2C 电平转换模块用的就是它。


    六、上拉/下拉电阻详解:小小电阻,三重身份

    上拉电阻把引脚"拉"向高电平,下拉电阻把引脚"拉"向低电平,它们在电路中有三重身份:

  • 确定默认电平:MCU 复位瞬间引脚是浮空的,容易受干扰乱跳。上拉/下拉给按键、使能脚、I2C 总线一个确定的默认状态;
  • 开漏输出的"高电平发生器":如前所述,没有它开漏输出就没有高电平;
  • 限流与抗干扰:限制冲突电流,抑制引脚浮空拾取的噪声。
  • 阻值怎么选?

    上拉电阻的选择是功耗与速度的折中:

    阻值优点缺点
    太小(如 1kΩ) 拉高快、驱动强、抗干扰好 输出低时电流大(3.3V/1k≈3.3mA),功耗高
    太大(如 100kΩ) 省电 Rp×C 时间常数大,上升沿缓慢,抗干扰差

    经验值:

    • I2C 标准模式(100kHz):4.7kΩ 左右;快速模式(400kHz)可减到 2.2kΩ~3.3kΩ;总线电容大、设备多时适当减小;
    • 普通按键、使能、默认电平:10kΩ~100kΩ 都很常见。

    一个实用的检查公式:Rp_max ≈ trise / (0.8473 × Cbus)(trise 为协议允许的上升时间,Cbus 为总线总电容)。对 I2C 来说,设备越多、走线越长,就要用越小的上拉电阻。


    七、其他输出方式补充

    7.1 开集输出(Open-Collector)

    开漏的"三极管版本":把 N-MOS 换成 NPN 三极管,集电极开路引出。特性与开漏几乎一样(线与、电平转换、需上拉),常见于比较器输出、老式器件(如 PC 的中断请求线、某些驱动芯片)。现在新设计中 MOS 结构(开漏)是主流。

    7.2 开源输出(Open-Source)

    镜像操作:只保留 P-MOS,源极开路,需要下拉电阻才能输出低电平。实际中非常少见,了解即可。

    7.3 高阻态(三态)

    严格说高阻态不是"输出电平",而是第三种状态:不驱动。引脚内部的上管下管全部截止,仿佛从电路上断开。推挽输出可以配置成三态(用于总线复用),开漏输出的"输出 1"本质上就是高阻态。它让多个设备的引脚可以分时复用同一条总线——谁需要说话谁退出高阻。

    7.4 准双向口:51 单片机的经典设计

    51 单片机的 I/O 是个很有年代感的方案:内部只有一个 N-MOS 拉低 + 一个很弱的内部上拉(几十~几百 kΩ):

    • 输出 0:N-MOS 导通,强拉低;
    • 输出 1:N-MOS 截止,靠弱上拉"虚挂"在高电平——能输出高,但驱动能力很弱;
    • 读引脚前先写 1(释放总线),所以叫"准双向"。

    经典问题:51 的 P0 口为什么必须外接上拉电阻?——因为 P0 口作为通用 I/O 时是开漏结构,内部根本没有上拉,不外接电阻就无法输出高电平。学完本文再回头看这个面试题,就是开漏原理的直接应用。


    八、总结对比

    在这里插入图片描述

    对比项推挽输出开漏输出
    输出状态 高 / 低(两态主动驱动) 低 / 高阻态(高电平靠上拉)
    高电平来源 内部 P-MOS,= 芯片 VDD 外部上拉电源,值可自由选择
    高电平驱动 强,边沿快 弱,受 Rp×C 限制,上升沿慢
    低电平驱动
    多设备共线 ❌ 会短路冲突(直通电流) ✅ 天然支持线与(I2C 基础)
    电平转换 不行,高电平锁死为 VDD 可以,换上拉电源即可
    静态功耗 输出高/低都几乎不耗电 输出低时 Rp 持续耗电 VDD²/Rp
    典型应用 LED、SPI、UART 等点对点高速输出 I2C/SMBus、共享中断线、电平转换

    如何选择?

    • 点对点、高速、电平一致 → 推挽输出,闭眼选;
    • 多设备共享一条线 → 开漏 + 上拉,没得选(协议决定的);
    • 需要跨电平输出 → 开漏 + 高压上拉(确认引脚耐压)。

    九、写在最后

    回顾整条知识线:

  • 推挽输出 = P-MOS"推" + N-MOS"挽",强驱动、快边沿,但不能并联;
  • 开漏输出 = 砍掉上管、只留"拉低"能力,换来线与与电平自由两大杀手锏;
  • 上拉电阻是开漏输出的最佳拍档:提供高电平、限制冲突电流,阻值在速度与功耗间权衡;
  • I2C 选择开漏 + 上拉,不是设计者的偏好,而是多设备共享总线必须线与的物理必然。
  • 理解了"为什么要开漏",再去看 I2C 的仲裁、时钟拉伸、总线死锁恢复(9 个时钟脉冲释放总线)等机制,都会有豁然开朗的感觉。

    参考资料:
    [1] 野火 STM32 系列开发指南——《GPIO 输出模式:P-MOS 与 N-MOS 工作方式》
    [2] NXP《I2C-bus specification and user manual》(UM10204)
    [3] Shutdown Circuit,《Open Drain vs. Push-Pull Outputs: What Your Textbook Left Out》

    本文为个人学习笔记,如有理解偏差欢迎评论区指正交流。觉得有帮助的话,点个赞让更多正在啃 I2C 的同学看到吧~

    赞(0)
    未经允许不得转载:171主机测评 » 从 I2C 的开漏输出说起:一文搞懂推挽输出、开漏输出与上拉电阻
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址