1. 课程导入

GPIO,全称 General-Purpose Input/Output,通用输入输出口。说白了,就是芯片上那些可以编程控制的引脚。你可以让它输出高电平或低电平,也可以读取外部信号是高还是低。

我刚开始做嵌入式那会儿,觉得 GPIO 不就是点个灯、读个按键嘛,有啥好学的?后来踩的坑多了才明白——GPIO 用不好,轻则信号不稳定,重则烧芯片。这一章,咱们就把 GPIO 的底裤扒干净。

1.1 GPIO 工作原理

每个 GPIO 引脚内部,其实是一堆 MOS 管、触发器和控制寄存器。你通过写寄存器,告诉芯片这个引脚是输入还是输出,输出什么电平。

一个典型的 GPIO 模块包含:

  • 控制寄存器:配置方向(输入/输出)、模式(推挽/开漏)、上下拉等
  • 数据寄存器:存放要输出的值,或读取到的输入值
  • 输出驱动器:由 PMOS 和 NMOS 组成的推挽结构,或只有 NMOS 的开漏结构
  • 输入缓冲器:通常是施密特触发器,用来整形信号

核心要点:GPIO 的输入输出,本质上是读写寄存器。写 1 输出高电平,写 0 输出低电平。读引脚就是读输入寄存器的值。

1.2 推挽输出与开漏输出

这是 GPIO 最核心的两个输出模式。我见过不少工程师搞混,结果项目翻车。

推挽输出(Push-Pull)

推挽输出内部有两个 MOS 管:上边的 PMOS 负责“推”,下边的 NMOS 负责“挽”。输出高电平时,PMOS 导通,NMOS 截止,引脚被拉到 VDD;输出低电平时,PMOS 截止,NMOS 导通,引脚被拉到 GND。

特点:

  • 输出高低电平都很强,驱动能力好
  • 不能将多个推挽输出直接连在一起——会打架,一个想拉高,一个想拉低,直接短路
  • 适合驱动 LED、蜂鸣器、继电器等

开漏输出(Open-Drain)

开漏输出只有下边的 NMOS 管,上边是空的。输出低电平时,NMOS 导通,引脚拉低;输出高电平时,NMOS 截止,引脚处于高阻态——这时候需要外部上拉电阻把电平拉高。

特点:

  • 可以实现“线与”功能:多个开漏输出连在一起,只要有一个输出低,总线就是低
  • 可以输出比 VDD 更高的电压(通过外部上拉到其他电压)
  • I²C 总线就是典型应用
对比项 推挽输出 开漏输出
内部结构 PMOS + NMOS 只有 NMOS
高电平输出 强驱动,直接拉到 VDD 高阻态,需外部上拉
低电平输出 强驱动,直接拉到 GND 强驱动,直接拉到 GND
多引脚并联 不允许 允许(线与)
典型应用 LED、普通信号输出 I²C、电平转换

我的习惯:做 I²C 总线时,一定用开漏输出加外部上拉。曾经有个同事用推挽输出做 I²C,结果两个从机同时应答时直接短路,烧了一个芯片。

1.3 上拉电阻与下拉电阻

上拉电阻把引脚拉到高电平,下拉电阻把引脚拉到低电平。它们的作用是:

  • 防止引脚浮空:输入引脚如果不接任何东西,电平是不确定的,容易受干扰
  • 提供默认电平:按键按下时拉低,松开时靠上拉回到高电平
  • 配合开漏输出:开漏输出高电平时,靠上拉电阻提供高电平

电阻值怎么选?我一般遵循这个原则:

  • 4.7kΩ ~ 10kΩ:通用上拉/下拉,适合按键、复位引脚
  • 1kΩ ~ 4.7kΩ:强上拉,适合高速信号或长线传输
  • 10kΩ ~ 100kΩ:弱上拉,适合低功耗场景

注意:MCU 内部通常有可编程的上拉/下拉电阻,但阻值一般较大(30kΩ~50kΩ),驱动能力有限。需要强上拉时,还是得外接电阻。

1.4 GPIO 电气特性

这部分是硬核知识,也是容易出问题的地方。我见过太多因为电气特性没搞懂导致的故障。

关键参数

参数 说明 典型值(3.3V MCU)
VOH 输出高电平的最小值 ≥ 2.4V(负载下)
VOL 输出低电平的最大值 ≤ 0.4V(负载下)
VIH 输入高电平的最小值 ≥ 2.0V
VIL 输入低电平的最大值 ≤ 0.8V
IOL 输出低电平时的最大灌电流 8~20mA(因引脚而异)
IOH 输出高电平时的最大拉电流 8~20mA(因引脚而异)

这里有个坑:VOH 和 VOL 是在特定负载电流下测的。你输出高电平,但接了重负载,电压会被拉低。我曾经用 GPIO 直接驱动一个 5V 继电器,结果电压被拉到 1.8V,继电器吸合不了,还差点烧了引脚。

驱动能力与负载

每个 GPIO 的驱动能力有限,一般不超过 20mA。整个芯片的总电流也有上限,比如 STM32F103 所有 GPIO 的总电流不能超过 150mA。

驱动 LED 时,一定要串限流电阻。计算公式:

R = (V<sub>OH</sub> - V<sub>LED</sub>) / I<sub>LED</sub>

举例:V<sub>OH</sub> = 3.3V,LED 压降 2.0V,电流 10mA
R = (3.3 - 2.0) / 0.01 = 130Ω
实际选 150Ω 或 220Ω

避坑指南:我曾经用 GPIO 直接驱动一个蜂鸣器,没加三极管,结果蜂鸣器声音很小,查了半天发现是驱动电流不够。后来加了个 NPN 三极管做开关,问题解决。

1.5 知识结构总览

下面这张图把 GPIO 的核心知识点串起来了。你对照着看,心里就有谱了。

GPIO 知识体系总览 GPIO 基础 工作原理 控制寄存器 数据寄存器 输出驱动器 输入缓冲器 输出模式 推挽输出 开漏输出 线与功能 电平转换 上拉/下拉 防止浮空 提供默认电平 配合开漏输出 电气特性 驱动能力

这张图把 GPIO 的四个核心维度串起来了。你从中心出发,往四个方向看:工作原理是基础,输出模式是配置,上下拉是辅助,电气特性是约束。做项目时,这四个方面都得考虑到。