硬件接口基础:GPIO、UART、I2C、SPI 协议原理与对比

做嵌入式开发这些年,我接触最多的就是这四种接口。说句实话,很多新手一上来就盯着协议细节看,反而忽略了最本质的东西——这些接口到底解决什么问题?

今天咱们就掰开揉碎了聊聊。我不会给你堆砌寄存器手册,而是从一个工程师的实战视角,带你真正理解它们。

1. GPIO:最朴素的“开关”

GPIO 全称是 General Purpose Input Output,通用输入输出口。说白了,它就是芯片上的一根引脚,你可以控制它输出高电平或低电平,也可以读取它当前的电平状态。

核心原理:

  • 输出模式:写寄存器,引脚就变成高(通常 3.3V 或 1.8V)或低(0V)
  • 输入模式:读寄存器,就知道外部电路是拉高了还是拉低了
  • 复用功能:很多 GPIO 引脚可以切换成 UART、I2C 等专用功能

实战经验:

我做过一个温控项目,用 GPIO 直接驱动继电器。结果发现继电器吸合瞬间,电源被拉低,MCU 直接复位了。后来才意识到——GPIO 驱动能力有限,一般只能输出几毫安。驱动继电器必须加三极管或光耦隔离。

我的习惯:

设计电路时,我会给每个 GPIO 串一个 100Ω 电阻。不是为了限流,而是为了调试时方便挂示波器探头,同时防止误操作烧引脚。

2. UART:最经典的“对话”

UART(Universal Asynchronous Receiver/Transmitter)是异步串行通信。它只需要两根线——TX(发送)和 RX(接收),就能实现两个设备之间的双向通信。

为什么叫“异步”?

因为没有独立的时钟线。收发双方得提前约定好“说话速度”,也就是波特率。常见的波特率有 9600、115200 等。

数据帧结构:

起始位(1bit) + 数据位(5~8bit) + 校验位(可选) + 停止位(1~2bit)

举个例子,发送一个字节 0x55(二进制 01010101),波形就是:

空闲高电平 → 拉低1bit(起始) → 01010101(数据) → 拉高1bit(停止)

我曾经踩过的坑:

有一次调试 GPS 模块,数据总是乱码。折腾了半天,发现是波特率设置错了——模块默认 9600,我代码里配的是 115200。记住:UART 通信双方波特率误差不能超过 ±2%,否则就会出现丢帧或乱码。

3. I2C:多设备“总线”的优雅方案

I2C(Inter-Integrated Circuit)只需要两根线:SCL(时钟线)和 SDA(数据线)。但它可以挂载多个设备,每个设备有唯一的地址。

工作原理:

  • 主设备(通常是 MCU)产生时钟信号,发起通信
  • 从设备(传感器、存储器等)响应地址
  • 数据在 SDA 线上逐位传输,SCL 时钟同步

通信流程:

起始信号 → 发送从设备地址(7bit) + 读写位(1bit) → 从设备应答(ACK) → 数据字节 + ACK → ... → 停止信号

个人经验:

I2C 最让我头疼的是“总线锁死”。有一次传感器在通信中途掉电,SDA 线被拉低再也释放不了。解决办法是:在代码里实现超时复位,或者硬件上给 SCL 和 SDA 加上拉电阻(典型值 4.7kΩ)。

速度等级:

模式 速率 典型应用
标准模式 100 kbit/s 温湿度传感器
快速模式 400 kbit/s 加速度计
高速模式 3.4 Mbit/s 图像传感器

4. SPI:速度至上的“全双工”选手

SPI(Serial Peripheral Interface)是同步串行通信。它需要四根线:

  • SCLK:时钟线,由主设备产生
  • MOSI:主设备输出,从设备输入
  • MISO:主设备输入,从设备输出
  • CS:片选线,低电平有效,选中某个从设备

为什么快?

因为 SPI 是全双工——发送和接收可以同时进行。而且没有 I2C 那种地址和应答开销,数据可以连续传输。

四种模式:

SPI 有四种模式,由时钟极性(CPOL)和时钟相位(CPHA)决定:

模式 CPOL CPHA 数据采样边沿
模式0 0 0 上升沿采样
模式1 0 1 下降沿采样
模式2 1 0 上升沿采样
模式3 1 1 下降沿采样

避坑指南:

我曾经调试一个 SPI 闪存芯片,死活读不到数据。后来用示波器一看,发现 CS 片选信号在传输过程中有毛刺。原因是 CS 引脚没有做去抖处理。解决办法:在 CS 线上加一个 10nF 电容到地,或者代码里在操作前后加延时。

5. 四种接口的对比与选型

你想想看,实际项目中该怎么选?我一般按这个思路来:

特性 GPIO UART I2C SPI
线数 1根 2根 2根 4根(可减少)
速度 取决于软件 最高约 1Mbps 最高 3.4Mbps 最高 50Mbps+
通信方式 单线 异步全双工 同步半双工 同步全双工
多设备支持 需额外引脚 需额外引脚 总线式,地址区分 片选区分
典型应用 按键、LED、中断 GPS、蓝牙、调试串口 传感器、EEPROM 闪存、显示屏、ADC

选型建议:

  • 控制简单设备(按键、LED):用 GPIO,最直接
  • 远距离或无线模块:用 UART,简单可靠
  • 挂载多个低速传感器:用 I2C,省引脚
  • 需要高速传输(显示、存储):用 SPI,性能优先

我的经验总结:

做项目时,我习惯先看数据手册里外设支持什么接口。如果芯片同时支持 I2C 和 SPI,我会优先选 SPI——因为速度更快,时序更简单,调试起来也方便。但如果是接多个传感器,I2C 的地址机制确实省心。

6. 知识体系结构图

下面这张图,是我自己梳理的四种接口的核心逻辑。你看一眼就能明白它们之间的区别和联系:

四种硬件接口核心逻辑对比 GPIO 通用输入输出 1根线 电平高低 无协议 速度由软件决定 按键、LED、中断 UART 异步串行 2根线 (TX/RX) 异步无时钟 波特率约定 全双工 GPS、蓝牙、调试 I2C 同步串行总线 2根线 (SCL/SDA) 同步有时钟 地址区分设备 半双工 传感器、EEPROM SPI 同步串行 4根线 同步有时钟 片选区分设备 全双工 闪存、显示屏、ADC 选型决策树 需要多少根线? 1根 → GPIO 2根 → 需要时钟吗? 不需要 → UART 需要 → 多设备? 是 → I2C 否 → 看速度 低速 → I2C 高速 → SPI 4根 → SPI

嗯,这张图基本把四种接口的定位说清楚了。你选型的时候,先问自己三个问题:需要几根线?需要多快?挂几个设备?答案自然就出来了。

最后说一句:

别被协议细节吓到。实际开发中,大部分 MCU 都提供了硬件外设驱动库,你只需要配置几个寄存器。真正考验人的,是时序匹配和信号完整性——这些才是实战中的硬功夫。


可可精品资料库