一、硬件接口与协议基础:GPIO、SPI、I2C、UART

做数据采集这些年,我接触最多的就是这四种接口。说实话,刚入行那会儿,我也被这些协议搞得晕头转向。但后来我发现,只要抓住几个关键点,理解起来其实没那么复杂。

今天我就把这四种接口掰开揉碎了讲给你听。咱们不搞那些虚的,直接上干货。

1.1 GPIO——最基础的“开关”

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

工作原理

GPIO内部其实就是一个三态门电路。输出模式下,寄存器写1,引脚就输出高电平;写0,就输出低电平。输入模式下,你读到的就是外部电路加在引脚上的电平。

核心要点:

  • 输出模式:控制外部设备(如LED、继电器)
  • 输入模式:读取外部信号(如按键、传感器状态)
  • 中断模式:引脚电平变化时触发CPU中断

我在项目中遇到过一个问题:用GPIO模拟一个简单的PWM波形控制电机。当时没注意GPIO的翻转速度,结果波形失真严重。后来查手册才发现,普通GPIO的翻转频率也就几MHz,想模拟高频PWM根本不行。

避坑指南:

我曾经踩过一个坑——GPIO直接驱动大电流负载。GPIO的驱动能力一般只有几mA到20mA,直接接电机或继电器,轻则烧引脚,重则烧芯片。一定要加驱动电路或光耦隔离。

1.2 UART——最经典的串行通信

UART,通用异步收发传输器。这玩意儿太经典了,从单片机到PC,从调试口到GPS模块,到处都有它的身影。

协议原理

UART通信只需要两根线:TX(发送)和RX(接收)。数据以帧为单位传输,一帧包含起始位(1位低电平)、数据位(5-8位)、校验位(可选)、停止位(1-2位高电平)。

波特率是UART的灵魂。常见的波特率有9600、115200等。收发双方的波特率必须一致,否则数据就乱码了。

// UART初始化示例(伪代码)
void uart_init(int baudrate) {
    // 设置波特率寄存器
    UBRR = F_CPU / 16 / baudrate - 1;
    // 使能发送和接收
    UCSRB |= (1 << TXEN) | (1 << RXEN);
    // 设置数据格式:8位数据,1位停止位
    UCSRC |= (1 << UCSZ1) | (1 << UCSZ0);
}

你想想看,UART为什么叫“异步”?因为它没有单独的时钟线。收发双方靠各自的时钟来采样,所以对时钟精度有要求。一般要求误差在2%以内。

个人经验:调试UART时,我习惯先用示波器看波形。起始位、数据位、停止位一目了然。如果波形不对,先检查波特率设置,再检查电平是否匹配(3.3V vs 5V)。

1.3 SPI——高速同步通信

SPI,串行外设接口。这玩意儿速度快,结构简单,是我做数据采集时的首选。

协议原理

SPI需要4根线:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。主设备产生时钟,从设备在时钟边沿采样数据。

SPI有4种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)决定。说白了就是:时钟空闲时是高还是低?数据在上升沿还是下降沿采样?

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

我记得有一次调试一个SPI接口的ADC芯片,数据死活读不对。折腾了半天,最后发现是SPI模式没对上。芯片手册要求模式1,我默认用了模式0。嗯,从那以后我养成了习惯:先看手册,再写代码。

SPI的优势:

  • 速度快:可达几十MHz甚至更高
  • 全双工:可以同时收发数据
  • 硬件简单:没有复杂的协议开销

1.4 I2C——两线制总线

I2C,Inter-Integrated Circuit。这玩意儿只用两根线(SDA数据线、SCL时钟线)就能挂载多个设备,非常节省引脚。

协议原理

I2C是半双工通信。所有设备都挂在SDA和SCL上,通过地址来区分。通信流程是这样的:

  1. 主设备发送起始条件(SCL高电平时,SDA从高变低)
  2. 主设备发送7位从设备地址 + 1位读写位
  3. 从设备应答(ACK)
  4. 传输数据(每字节后跟ACK)
  5. 主设备发送停止条件(SCL高电平时,SDA从低变高)

I2C的速率分几种:标准模式100kHz,快速模式400kHz,高速模式3.4MHz。速率越高,对总线上拉电阻的要求越严格。

避坑指南:我曾经在一个项目里,I2C总线上挂了5个设备,结果通信时好时坏。查了半天,发现是总线电容太大,上拉电阻没选对。总线电容超过400pF时,信号上升沿会变缓,导致通信失败。解决办法是减小上拉电阻,或者降低通信速率。

1.5 四种协议对比

做数据采集时,选哪种接口?我一般这么看:

特性 GPIO UART SPI I2C
线数 1根/引脚 2根 4根 2根
速度 几MHz 最高几Mbps 几十MHz 最高3.4MHz
通信方式 单线 异步 同步全双工 同步半双工
多设备 不支持 点对点 一主多从 多主多从
距离 板级 可达十几米 板级 板级
典型应用 按键、LED GPS、蓝牙 ADC、LCD 传感器、EEPROM

1.6 数据采集中的应用场景

做数据采集,说白了就是把物理世界的模拟信号变成数字信号,然后读进处理器。不同的传感器,接口也不同。

GPIO场景:读取开关量传感器,比如门磁、红外对射。这种信号只有0和1,用GPIO中断最合适。我做过一个项目,用GPIO中断采集编码器的脉冲,精度能达到微秒级。

UART场景:很多工业传感器都带UART接口,比如GPS模块、激光测距仪。数据以字符串或二进制帧格式传输。我建议用DMA接收,避免CPU被频繁中断。

SPI场景:高速ADC、DAC、LCD屏。SPI速度快,适合采集高频信号。比如用SPI接口的ADC采集音频信号,采样率能到几百kHz。

I2C场景:温湿度传感器、加速度计、陀螺仪。这类传感器数据量不大,但功耗低,引脚少。I2C非常适合。

我的选择原则:

  • 需要高速(>1MHz)→ 选SPI
  • 需要多设备、低引脚 → 选I2C
  • 需要远距离、简单 → 选UART
  • 只需要开关量 → 选GPIO

1.7 知识体系结构图

下面这张图,是我自己总结的四种接口在数据采集中的定位。你一看就明白了。

数据采集驱动开发 - 硬件接口知识体系 数据采集系统 GPIO 开关量采集 按键、编码器 UART 异步串行 GPS、蓝牙模块 SPI 高速同步 ADC、LCD、SD卡 I2C 两线制总线 温湿度、加速度计 核心对比维度 速度 GPIO < I2C < UART < SPI 引脚数 GPIO(1) < I2C(2) = UART(2) < SPI(4) 复杂度 GPIO < UART < SPI < I2C

这张图把四种接口的核心特性都标出来了。你选型的时候,对着这张图看,基本不会选错。

1.8 小结

好了,这一章的内容就这些。四种接口,各有各的脾气。GPIO简单直接,UART经典耐用,SPI高速高效,I2C灵活省线。

做数据采集,没有最好的接口,只有最合适的接口。关键是要搞清楚你的传感器是什么接口,你的处理器支持什么接口,你的系统对速度和功耗有什么要求。

我个人建议,新手先从UART和GPIO入手,这两个最容易上手。等熟练了,再啃SPI和I2C。别贪多,一口吃不成胖子。

记住一句话:接口是死的,人是活的。协议只是工具,解决问题才是目的。


公众号:蓝海资料掘金营,微信deep3321