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 线,任何设备都可以将总线拉低。
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 中断,实现实时响应。
- 系统控制:复位外设、电源管理、唤醒信号、看门狗喂狗。
1.4 GPIO 的软件抽象层次
在 Linux 内核中,GPIO 的软件抽象分为三个层次,驱动开发者需要理解每一层的职责:
- 硬件层:SoC 芯片内部的 GPIO 寄存器组,包括方向寄存器、数据寄存器、上下拉配置寄存器等。
- 内核层(gpiolib):提供统一的 API 接口(
gpio_request、gpio_direction_output、gpio_set_value等),屏蔽不同芯片的寄存器差异。 - 驱动层:设备驱动通过 gpiolib API 操作 GPIO,实现具体的功能逻辑。
关键认知:编写 GPIO 驱动时,你几乎不需要直接操作寄存器——gpiolib 已经封装好了。你只需要调用标准 API,并确保在设备树(Device Tree)中正确描述 GPIO 资源。
1.5 本章小结
- GPIO 是软件可编程的数字引脚,通过寄存器实现输入/输出控制。
- 推挽输出驱动能力强,适合点对点通信;开漏输出支持多设备“线与”,适合共享总线。
- 上下拉电阻为高阻引脚提供确定的默认电平,防止浮空导致的误触发。
- GPIO 在嵌入式系统中承担状态指示、用户输入、外设控制、中断源、系统控制等多种角色。
- Linux 内核通过 gpiolib 提供统一的 GPIO 操作接口,驱动开发者应优先使用标准 API。