从 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 工作原理
| 输出 1 | 导通 | 截止 | VDD(电流从 VDD 经 P 管"推"向负载) |
| 输出 0 | 截止 | 导通 | 0V(电流经 N 管"挽"回 GND,也叫灌电流) |
所谓"推挽",就是这个名字的字面含义:输出高电平时,上管把电流"推"出去(拉电流);输出低电平时,下管把电流"拉"回来(灌电流)。两个管子像拔河一样轮流发力、互补工作,任何时刻都只有一个导通。
2.3 优缺点
优点:
缺点:
一句话总结:推挽输出是"单人驾驶"——力气大、速度快,但一条路上只能有一辆车。
三、开漏输出(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 优缺点
优点:
缺点:
一句话总结:开漏输出是"只能踩刹车,不能踩油门"——油门(高电平)交给外接的上拉电阻来踩。
四、线与逻辑(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 协议的两大机制的物理基础:
此外,共享中断线(多个传感器的 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 电平转换模块用的就是它。
六、上拉/下拉电阻详解:小小电阻,三重身份
上拉电阻把引脚"拉"向高电平,下拉电阻把引脚"拉"向低电平,它们在电路中有三重身份:
阻值怎么选?
上拉电阻的选择是功耗与速度的折中:
| 太小(如 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、共享中断线、电平转换 |
如何选择?
- 点对点、高速、电平一致 → 推挽输出,闭眼选;
- 多设备共享一条线 → 开漏 + 上拉,没得选(协议决定的);
- 需要跨电平输出 → 开漏 + 高压上拉(确认引脚耐压)。
九、写在最后
回顾整条知识线:
理解了"为什么要开漏",再去看 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 的同学看到吧~




