一、硬件接口与协议基础: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上,通过地址来区分。通信流程是这样的:
- 主设备发送起始条件(SCL高电平时,SDA从高变低)
- 主设备发送7位从设备地址 + 1位读写位
- 从设备应答(ACK)
- 传输数据(每字节后跟ACK)
- 主设备发送停止条件(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 知识体系结构图
下面这张图,是我自己总结的四种接口在数据采集中的定位。你一看就明白了。
这张图把四种接口的核心特性都标出来了。你选型的时候,对着这张图看,基本不会选错。
1.8 小结
好了,这一章的内容就这些。四种接口,各有各的脾气。GPIO简单直接,UART经典耐用,SPI高速高效,I2C灵活省线。
做数据采集,没有最好的接口,只有最合适的接口。关键是要搞清楚你的传感器是什么接口,你的处理器支持什么接口,你的系统对速度和功耗有什么要求。
我个人建议,新手先从UART和GPIO入手,这两个最容易上手。等熟练了,再啃SPI和I2C。别贪多,一口吃不成胖子。
记住一句话:接口是死的,人是活的。协议只是工具,解决问题才是目的。
公众号:蓝海资料掘金营,微信deep3321