3. 传感器基础与接口:常见传感器类型与通信协议详解

大家好,我是你们的老朋友。今天我们来聊聊嵌入式多传感器融合里最基础、也最绕不开的一环——传感器本身和它们怎么跟主控“说话”。

说实话,我见过太多项目,算法写得天花乱坠,最后栽在传感器数据读不上来、或者读出来全是噪声。嗯,这章我们就来把这些坑填平。

3.1 常见传感器类型:各怀绝技的“侦察兵”

一个多传感器融合系统,说白了就是一群不同专长的传感器在协同工作。我习惯把它们分成四类:

3.4.1 IMU(惯性测量单元)

IMU 是“闷声干大事”的典型。它包含加速度计和陀螺仪,有的还带磁力计。加速度计测的是比力(包含重力),陀螺仪测的是角速度。

我个人习惯:在无人机项目里,IMU 的数据更新率我一般设到 400Hz 以上。低于 200Hz,姿态解算就会明显滞后。

我曾经踩过的坑:IMU 的零偏会随温度漂移。有一次在户外测试,中午温度升到 40℃,无人机直接“抽风”。后来我加了温度补偿模型,才稳住。

3.4.2 摄像头

摄像头是信息量最大的传感器,没有之一。它输出的是图像帧,本质上是二维光强分布。但要注意,它没有直接的深度信息。

你想想看,一个 640x480 的灰度图,一帧就有 307200 个像素点。如果跑 30fps,每秒要处理 9MB 数据。这对嵌入式平台是个不小的挑战。

我的建议:在资源受限的 MCU 上,优先用 VGA(640x480)分辨率,别一上来就上 1080p。帧率控制在 15-30fps 之间,再高意义不大,反而把 CPU 吃光。

3.4.3 激光雷达(LiDAR)

激光雷达直接输出距离信息,精度高、抗干扰强。单线雷达常用于避障,多线雷达(如 16线、32线)用于建图。

我记得第一次调 16 线激光雷达时,被它的点云数据量吓了一跳——每秒 30 万个点。用 UART 传?想都别想。必须上以太网或 USB。

3.4.4 超声波传感器

超声波是“老黄牛”型传感器。成本低、功耗小,但精度一般,而且有盲区(通常 2-3cm 以内测不准)。

我一般用它做近距离辅助测距,比如机器人离墙 20cm 以内时,用超声波补激光雷达的盲区。

3.2 通信协议:传感器与主控的“语言”

传感器再好,数据传不出来也是白搭。嵌入式里最常用的三种协议:I2C、SPI、UART。我一个个说。

3.2.1 I2C(Inter-Integrated Circuit)

I2C 是两线制:SCL(时钟线)和 SDA(数据线)。支持多主多从,但速度偏慢——标准模式 100kHz,快速模式 400kHz,高速模式 3.4MHz。

适用场景:IMU、温度传感器、气压计这类数据量小、更新率不高的器件。

关键点:I2C 有 7 位和 10 位地址模式。7 位地址最多挂 128 个设备,但实际要考虑总线电容限制,一般不超过 10 个。

代码示例:读取 MPU6050(IMU)的加速度计数据

// I2C 读取 MPU6050 加速度计 X 轴高字节
uint8_t reg_addr = 0x3B;  // ACCEL_XOUT_H 寄存器地址
uint8_t data[2];
HAL_I2C_Mem_Read(&hi2c1, 0xD0, reg_addr, I2C_MEMADD_SIZE_8BIT, data, 2, 100);
int16_t accel_x = (data[0] << 8) | data[1];

3.2.2 SPI(Serial Peripheral Interface)

SPI 是四线制:MOSI、MISO、SCLK、CS(片选)。全双工,速度可以跑到几十 MHz。我常用它接高速 ADC、显示屏、SD 卡。

为什么我偏爱 SPI?因为它没有 I2C 那种“应答”机制,数据流是连续的。在需要高速读取大量数据时(比如摄像头原始数据),SPI 是首选。

注意:SPI 没有标准的设备地址,全靠片选线 CS 来区分。所以每多一个设备,就要多占一个 GPIO 做 CS。我曾经在一个板子上接了 5 个 SPI 设备,GPIO 差点不够用。

代码示例:SPI 读取 LSM6DS3(IMU)的 WHO_AM_I 寄存器

uint8_t tx_data = 0x8F;  // 读命令 + 寄存器地址 0x0F
uint8_t rx_data = 0;
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);  // 拉低片选
HAL_SPI_TransmitReceive(&hspi1, &tx_data, &rx_data, 1, 100);
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);    // 拉高片选
// rx_data 应为 0x69,表示 LSM6DS3 正常

3.2.3 UART(通用异步收发器)

UART 是异步串口,只需要 TX 和 RX 两根线。速度一般从 9600bps 到 115200bps,高的也能到 1Mbps 以上。

我最常用的场景:调试日志输出、GPS 模块、某些低端激光雷达。

UART 有个好处——硬件简单,几乎所有的 MCU 都有。但坏处也明显:没有时钟线,双方必须约定好波特率,而且一帧只能传 5-8 位数据。

避坑指南:我曾经用 UART 接一个 115200bps 的 GPS 模块,结果数据偶尔乱码。查了半天,发现是 MCU 的时钟源精度不够,导致波特率误差超过 2%。后来换了外部晶振,问题解决。

代码示例:UART 发送字符串

char msg[] = "Hello from STM32\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 1000);

3.3 协议对比与选型建议

我整理了一张表,方便你快速决策:

协议 线数 速度 全双工 多设备 典型应用
I2C 2 ~3.4MHz 是(地址寻址) IMU、温湿度、气压计
SPI 4+ ~80MHz 是(片选) 高速 ADC、显示屏、SD 卡
UART 2 ~1Mbps 否(点对点) GPS、调试口、蓝牙模块

我的选型口诀:

  • 数据量小、设备多 → I2C
  • 数据量大、要高速 → SPI
  • 简单、距离远、点对点 → UART

3.4 多传感器融合中的接口资源规划

最后聊点实战的。一个典型的融合系统可能同时挂:IMU(I2C)、激光雷达(UART 或 SPI)、摄像头(DCMI 或 SPI)、超声波(GPIO 模拟或 UART)。

你想想看,MCU 的外设资源是有限的。我见过有人把 3 个 I2C 设备挂到同一个总线上,结果因为地址冲突,死活读不到其中一个。后来我建议他用 I2C 多路复用器(如 TCA9548A),才解决。

资源优化建议:
  • 优先用硬件外设(硬件 I2C/SPI/UART),别用 GPIO 模拟,除非资源实在不够。
  • 高速传感器(如摄像头)独占一个 SPI 或 DCMI 接口。
  • 低速传感器(如温湿度)可以共享 I2C 总线,但注意地址不能冲突。
  • UART 尽量用 DMA 接收,避免中断频繁打断主循环。

嗯,这一章的内容就到这里。传感器接口这块,说白了就是“选对协议、配好资源、避开坑”。下一章我们会深入讲传感器数据的时间同步问题——那可是多传感器融合里最容易出幺蛾子的地方。