1. GPIO 基础概念

1.1 GPIO 定义

GPIO(General Purpose Input/Output,通用输入输出)是嵌入式系统中最基础、最灵活的硬件接口。它允许软件通过寄存器配置来控制芯片引脚的电平状态,实现数字信号的输入检测或输出驱动。

从软件视角看,GPIO 表现为一组可读写的寄存器;从硬件视角看,GPIO 是芯片与外部世界交互的物理引脚。Linux 内核通过 gpiolib 子系统对 GPIO 进行统一管理,屏蔽了不同 SoC 的寄存器差异。

核心要点:GPIO 的本质是“软件可编程的数字引脚”——通过写寄存器输出高/低电平,或读寄存器获取外部电平状态。

1.2 GPIO 电气特性

理解 GPIO 的电气特性是驱动开发的基础。不同的输出模式、上下拉配置直接影响信号质量、功耗和外部电路设计。

1.2.1 输出模式:推挽 vs 开漏

特性 推挽输出(Push-Pull) 开漏输出(Open-Drain)
高电平驱动 由 PMOS 管直接驱动到 VDD 无高电平驱动能力,需外部上拉电阻
低电平驱动 由 NMOS 管直接驱动到 GND 由 NMOS 管驱动到 GND
输出电平 明确的高(VDD)或低(GND) 低(GND)或高阻(Hi-Z)
典型应用 普通 LED、蜂鸣器、SPI/CLK I²C 总线、多设备共享线、电平转换
功耗 静态时无额外功耗 高电平时有上拉电阻漏电流
实战提示:I²C 总线强制使用开漏模式,这是由协议本身决定的——多个设备通过“线与”方式共享 SDA/SCL 线,任何设备都可以将总线拉低。
推挽输出 vs 开漏输出 结构对比 推挽输出 PMOS 上拉管 NMOS 下拉管 引脚 输出明确高/低电平 无需外部上拉电阻 开漏输出 NMOS 下拉管 外部上拉电阻 引脚 低电平:NMOS 导通 高电平:Hi-Z,由上拉电阻拉高

1.2.2 上下拉电阻

当 GPIO 配置为输入模式或开漏输出时,引脚处于高阻状态,外部噪声容易导致电平不确定。上下拉电阻为引脚提供一个确定的默认电平。

配置 默认电平 典型阻值 适用场景
上拉(Pull-Up) 高电平(VDD) 4.7kΩ ~ 100kΩ 按键输入、中断引脚、开漏总线
下拉(Pull-Down) 低电平(GND) 4.7kΩ ~ 100kΩ 复位引脚、使能引脚、安全锁定
浮空(Floating) 不确定 — 已由外部电路确定电平的场景
常见陷阱:浮空输入引脚在电磁干扰环境下会随机跳变,导致软件误判。除非外部有强驱动源,否则务必启用内部上拉或下拉。

1.3 GPIO 在嵌入式系统中的作用

GPIO 是嵌入式系统中最通用的“数字胶水”,承担着以下关键角色:

  • 状态指示:驱动 LED 指示系统运行状态、网络连接、错误告警。
  • 用户输入:读取按键、拨码开关、触摸传感器的数字电平。
  • 外设控制:控制继电器的通断、MOSFET 开关、电机使能。
  • 通信协议:软件模拟 I²C、SPI、UART、1-Wire 等低速总线。
  • 中断源:外部事件触发 CPU 中断,实现实时响应。
  • 系统控制:复位外设、电源管理、唤醒信号、看门狗喂狗。
GPIO 在嵌入式系统中的作用全景 GPIO 控制器 LED 指示 按键输入 外设控制 软件模拟总线 外部中断 系统控制 电源管理 看门狗喂狗 一个 GPIO 引脚可同时承担多种角色,通过复用功能寄存器切换 (如:同一引脚可配置为 GPIO 输出、外部中断或 SPI 时钟)

1.4 GPIO 的软件抽象层次

在 Linux 内核中,GPIO 的软件抽象分为三个层次,驱动开发者需要理解每一层的职责:

  1. 硬件层:SoC 芯片内部的 GPIO 寄存器组,包括方向寄存器、数据寄存器、上下拉配置寄存器等。
  2. 内核层(gpiolib):提供统一的 API 接口(gpio_request、gpio_direction_output、gpio_set_value 等),屏蔽不同芯片的寄存器差异。
  3. 驱动层:设备驱动通过 gpiolib API 操作 GPIO,实现具体的功能逻辑。
关键认知:编写 GPIO 驱动时,你几乎不需要直接操作寄存器——gpiolib 已经封装好了。你只需要调用标准 API,并确保在设备树(Device Tree)中正确描述 GPIO 资源。

1.5 本章小结

  • GPIO 是软件可编程的数字引脚,通过寄存器实现输入/输出控制。
  • 推挽输出驱动能力强,适合点对点通信;开漏输出支持多设备“线与”,适合共享总线。
  • 上下拉电阻为高阻引脚提供确定的默认电平,防止浮空导致的误触发。
  • GPIO 在嵌入式系统中承担状态指示、用户输入、外设控制、中断源、系统控制等多种角色。
  • Linux 内核通过 gpiolib 提供统一的 GPIO 操作接口,驱动开发者应优先使用标准 API。