3、数据采集硬件:微控制器(ESP32/STM32)介绍、GPIO与ADC接口、I2C/SPI通信协议、硬件连接实战

好,咱们进入硬件环节。说实话,很多做物联网的同学,软件写得飞起,一到硬件就发怵。我当年也是这样,总觉得硬件是玄学。后来踩的坑多了,才明白——硬件其实比软件更讲逻辑。你只要摸清它的脾气,它就不会给你捣乱。

这一章,咱们聊聊数据采集的「前线部队」——微控制器。说白了,就是那些小芯片,负责把物理世界的信号变成数字世界的0和1。我重点讲两个主流选手:ESP32和STM32。再配合GPIO、ADC、I2C、SPI这些接口,最后带大家走一遍硬件连接实战。

3.1 微控制器选型:ESP32 vs STM32

先说说我的个人习惯。做原型验证、快速出Demo的时候,我首选ESP32。为什么?因为它自带Wi-Fi和蓝牙,你不需要额外加通信模块。一块板子,传感器一接,数据就能往云端发。我在一个智能农业项目里,从焊板子到看到数据上云,只用了半天。这速度,STM32做不到。

但STM32也有它的主场。工业场景、对稳定性要求极高的场合,我肯定选STM32。它的外设资源丰富,定时器精度高,抗干扰能力强。我记得有一次做工厂设备数据采集,现场电机一启动,ESP32就死机。换成STM32后,稳如老狗。

对比项 ESP32 STM32
无线通信 自带Wi-Fi + 蓝牙 需外接模块
处理能力 双核240MHz,够用 从Cortex-M0到M7,选择多
功耗 偏高,约80mA 可低至几μA
开发难度 Arduino IDE上手快 HAL库/标准库,学习曲线陡
价格 约15-30元 从几元到上百元
典型场景 智能家居、原型验证 工业控制、汽车电子
我的建议: 如果你刚开始学物联网,先玩ESP32。成本低、资料多、社区活跃。等你把数据采集的流程跑通了,再考虑用STM32做产品化。

3.2 GPIO与ADC接口

GPIO,全称通用输入输出口。你想想看,微控制器怎么跟外界打交道?就是靠这些引脚。你可以把它设成高电平(3.3V)或低电平(0V),也可以读取外部信号是高还是低。

但这里有个坑——GPIO只能读数字信号。什么叫数字信号?就是只有0和1。那如果我想读一个温度传感器的模拟电压呢?比如0V到3.3V之间的任意值。这时候就需要ADC了。

ADC,模数转换器。它能把连续的模拟电压,转成离散的数字值。ESP32的ADC是12位的,什么意思?就是把0-3.3V分成4096份。0V对应0,3.3V对应4095。中间的值按比例映射。

核心公式: 实际电压 = (ADC读数 / 4095) × 3.3V

我曾经在一个水质监测项目里,用ESP32的ADC读PH值传感器的输出。一开始读数跳得厉害,后来发现是电源纹波太大。加了个100nF的滤波电容,数据就稳了。嗯,这里要注意——ADC对电源质量很敏感。

3.3 I2C与SPI通信协议

好,现在问题来了。一个微控制器只有几个ADC引脚,但我要接十几个传感器怎么办?总不能每个传感器都占一个ADC吧?这时候就需要通信协议了。

I2C和SPI,是物联网里最常用的两种总线协议。它们让微控制器通过两根线或四根线,就能挂载一堆外设。

3.4.1 I2C协议

I2C只用两根线:SDA(数据线)和SCL(时钟线)。所有设备都挂在这两根线上,每个设备有一个唯一的地址。微控制器作为主机,通过地址来寻址不同的从机。

我刚开始用I2C时,总遇到通信失败。后来发现是上拉电阻没加。I2C总线需要外接4.7kΩ的上拉电阻到VCC,否则信号拉不起来。这是新手最容易犯的错误。

避坑指南: 我曾经因为忘记加上拉电阻,排查了整整一个下午。后来养成习惯——画原理图时第一件事就是检查I2C的上拉电阻。

3.4.2 SPI协议

SPI比I2C快,但线也多。它用四根线:MOSI(主机输出从机输入)、MISO(主机输入从机输出)、SCLK(时钟)、CS(片选)。每个从机需要一根独立的CS线。

SPI的优势是速度快,适合传输大量数据。比如SD卡读写、显示屏刷新,都用SPI。但它的缺点是占引脚多——每多一个设备,就得多一根CS线。

对比项 I2C SPI
引脚数 2根(SDA + SCL) 4根(MOSI + MISO + SCLK + CS)
速度 标准100kHz,快速400kHz 可达几十MHz
设备寻址 软件地址(7位或10位) 硬件片选(每设备一根CS)
通信方式 半双工 全双工
适合场景 传感器、EEPROM 显示屏、SD卡、高速ADC
选型建议: 如果传感器数量多但数据量小,用I2C。如果数据量大或需要高速传输,用SPI。我个人的经验是——温度、湿度、气压这类传感器用I2C;摄像头、麦克风、显示屏用SPI。

3.5 硬件连接实战:ESP32 + 温湿度传感器

光说不练假把式。咱们来一个实战——用ESP32通过I2C读取温湿度传感器(SHT30)的数据。

3.5.1 硬件连接

SHT30是一个I2C接口的温湿度传感器。它的引脚定义很简单:VCC、GND、SDA、SCL。咱们把它接到ESP32上。

ESP32引脚     SHT30引脚
3.3V    ——>   VCC
GND     ——>   GND
GPIO21  ——>   SDA
GPIO22  ——>   SCL

注意,SHT30的I2C地址是0x44(ADDR引脚接GND时)。如果你把ADDR接VCC,地址就变成0x45。这个细节我在项目里吃过亏——买了两批传感器,地址不一样,代码死活读不到数据。

3.5.2 代码实现

我用MicroPython来写,因为调试方便。你可以在ESP32上刷入MicroPython固件,然后用串口工具运行以下代码。

from machine import Pin, I2C
import time

# 初始化I2C,使用GPIO21作为SDA,GPIO22作为SCL
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)

# 扫描I2C总线上的设备
devices = i2c.scan()
print("检测到的设备:", [hex(addr) for addr in devices])

# SHT30的I2C地址
SHT30_ADDR = 0x44

# 发送测量命令
i2c.writeto(SHT30_ADDR, b'\x2C\x06')
time.sleep(0.5)

# 读取6字节数据
data = i2c.readfrom(SHT30_ADDR, 6)

# 解析温湿度
temp_raw = (data[0] << 8) | data[1]
temp = -45 + 175 * temp_raw / 65535

hum_raw = (data[3] << 8) | data[4]
hum = 100 * hum_raw / 65535

print(f"温度: {temp:.2f}°C")
print(f"湿度: {hum:.2f}%")
运行结果示例:
检测到的设备: ['0x44']
温度: 25.34°C
湿度: 58.72%

3.5.3 常见问题排查

如果你运行代码后,扫描不到设备,或者读到的数据全是0,别慌。我列几个最常见的坑:

  • 接线错误: SDA和SCL有没有接反?VCC是不是3.3V?GND共地了吗?
  • 上拉电阻: 有些传感器模块自带4.7kΩ上拉电阻,有些没有。如果没有,你需要外接两个4.7kΩ电阻到3.3V。
  • 地址不对: 确认传感器的ADDR引脚电平。用i2c.scan()扫描一下,看实际地址是多少。
  • 电源问题: 传感器供电不足也会导致通信失败。我遇到过用面包板供电,接触不良导致电压掉到2.8V,传感器直接罢工。
曾经的血泪教训: 有一次我在实验室调试,I2C死活不通。换了传感器、换了线、换了板子,都不行。最后发现是杜邦线内部断了——外表完好,里面铜丝断了。从那以后,我包里常备万用表,先测通断再上电。

3.6 本章小结

这一章咱们聊了不少干货。从ESP32和STM32的选型对比,到GPIO和ADC的基本原理,再到I2C和SPI的通信细节,最后亲手连了一个温湿度传感器。你想想看,这些知识串联起来,就是一个完整的数据采集链路——传感器感知物理量,ADC或通信协议把数据传给微控制器,微控制器再通过Wi-Fi或串口把数据送出去。

下一章,咱们会深入数据采集的软件层面,聊聊如何用定时器、中断和DMA来高效采集数据。到时候你会发现,硬件和软件配合好了,才能发挥出系统的最大性能。

好,今天就到这里。如果你在硬件连接中遇到问题,欢迎随时交流。记住——硬件调试,耐心是第一位的。我曾经为了一个I2C的时序问题,盯着示波器看了三个小时。但当你看到数据正确显示的那一刻,一切都值了。