3、传感器选型与接口:压力传感器选型(MPS20N0040D等)、信号调理电路设计、I2C/SPI接口通信

好,咱们进入第三章。这一章聊的是硬件选型和接口,说白了就是血压计的心脏和血管——传感器和通信。我做了这么多年嵌入式,发现很多算法问题其实根源都在前端信号没处理好。你想想看,后端算法再牛,传感器给的数据是脏的,那也白搭。

3.1 压力传感器选型:为什么我偏爱MPS20N0040D

先说说传感器。市面上用于血压计的压力传感器不少,但MPS20N0040D是我个人用得最多的。为什么?

第一,量程合适。 人体血压测量范围一般在0~300 mmHg,换算成kPa大约是0~40 kPa。MPS20N0040D的型号后缀“0040”就代表40 kPa,刚好覆盖。我见过有人用100 kPa的传感器,精度反而浪费了。

第二,输出信号干净。 它内部集成了压阻式惠斯通电桥,输出的是差分模拟电压。我在项目中遇到过用便宜传感器的情况,那噪声大得离谱,滤波都救不回来。MPS20N0040D的共模抑制比(CMRR)不错,能省不少调理电路的功夫。

当然,也有其他选择,比如MPXV5050GP。但MPS20N0040D的封装更小,适合做便携式设备。我建议你优先考虑它。

关键参数速查表:

参数 MPS20N0040D MPXV5050GP
量程 0~40 kPa (300 mmHg) 0~50 kPa (375 mmHg)
输出类型 差分模拟电压 差分模拟电压
灵敏度 约 2.5 mV/kPa 约 2.0 mV/kPa
封装 SOP-8 (小) DIP-8 (大)

3.2 信号调理电路设计:别让噪声毁了你的数据

传感器出来的信号很微弱,只有几毫伏。直接送ADC?不行。必须经过调理电路。我刚开始做的时候,就吃过这个亏——信号直接进单片机,结果读数跳得像心电图。

调理电路的核心就三步:放大、滤波、偏置

3.2.1 放大:用仪表放大器,别用普通运放

普通运放放大差分信号,共模噪声也会被放大。仪表放大器(如AD620、INA128)天生就是干这个的。我习惯用AD620,增益通过一个电阻设置:

// 增益计算公式
G = 49.4kΩ / Rg + 1

// 例如,想要增益100倍
Rg = 49.4kΩ / (100 - 1) ≈ 499Ω

嗯,这里要注意:增益别设太高。100倍左右就够了。太高会把直流偏置也放大,导致ADC饱和。

3.2.2 滤波:二阶低通,截止频率10 Hz

血压信号的频率成分主要在0.5~5 Hz。脉搏波的高频分量也就10 Hz左右。所以低通滤波器的截止频率设在10 Hz就够用了。我一般用二阶巴特沃斯滤波器,用运放搭一个Sallen-Key结构。

我的小技巧: 如果你不想用分立元件,可以直接用集成滤波器芯片,比如MAX7400。省地方,也省调试时间。我在一个量产项目中就这么干过,效果很稳定。

3.2.3 偏置:把信号抬到ADC的中间

传感器输出有正有负,但单片机的ADC只能采0~Vref。所以得加一个偏置电压,把信号抬到Vref/2附近。我常用一个简单的电阻分压加电压跟随器来实现。

警告: 偏置电压的参考源一定要干净。我曾经直接用VDD分压,结果VDD上的纹波全耦合进去了。后来改用TL431稳压,问题才解决。

3.3 I2C/SPI接口通信:选哪个?看场景

调理完的信号,要么直接进ADC(如果单片机有片内ADC),要么通过外部ADC芯片转成数字量,再用I2C或SPI传给主控。这里我聊聊这两种接口的选择。

3.3.1 I2C:省引脚,但慢

I2C只需要两根线(SDA、SCL),适合引脚紧张的场景。但速度一般只有100 kHz或400 kHz。对于血压计这种低速采样(每秒100个点以内),I2C完全够用。

我常用的外部ADC是ADS1115,16位精度,I2C接口。代码示例:

// 初始化I2C
void i2c_init() {
    // 设置SCL频率为100kHz
    TWBR = 0x48;
}

// 读取ADS1115
uint16_t ads1115_read(uint8_t addr) {
    // 发送转换命令
    i2c_start(addr << 1);
    i2c_write(0x01); // 配置寄存器
    i2c_write(0xC2); // 高字节:连续转换,±4.096V
    i2c_write(0x83); // 低字节:128 SPS
    i2c_stop();

    delay(10); // 等待转换完成

    // 读取结果
    i2c_start(addr << 1);
    i2c_write(0x00); // 转换寄存器
    i2c_stop();

    i2c_start((addr << 1) | 0x01);
    uint8_t high = i2c_read_ack();
    uint8_t low = i2c_read_nack();
    i2c_stop();

    return (high << 8) | low;
}

3.3.2 SPI:快,但占引脚

SPI需要四根线(MOSI、MISO、SCK、CS),速度可以到几MHz甚至更高。如果你的系统里还有其他高速外设(比如显示屏),SPI是更好的选择。

我推荐用MCP3201,12位精度,SPI接口。它的时序很简单:

// SPI读取MCP3201
uint16_t mcp3201_read() {
    uint16_t value = 0;

    // 拉低片选
    CS_LOW();

    // 发送空字节,同时接收数据
    SPDR = 0x00;
    while(!(SPSR & (1<<SPIF)));
    value = SPDR << 8;

    SPDR = 0x00;
    while(!(SPSR & (1<<SPIF)));
    value |= SPDR;

    // 拉高片选
    CS_HIGH();

    // 只取高12位
    return (value >> 1) & 0x0FFF;
}

选型建议:

  • 如果主控引脚少,采样率要求不高 → 选I2C + ADS1115
  • 如果追求速度,或者需要同步采样 → 选SPI + MCP3201
  • 如果主控自带12位以上ADC,且噪声控制得好 → 直接用片内ADC,省成本

3.4 避坑指南:我踩过的几个坑

最后分享几个实战中容易忽略的问题:

  • 传感器安装方向: MPS20N0040D的背面有个小孔,那是气压参考口。千万别堵住!我见过有人用胶水固定传感器,结果把参考口糊死了,读数直接飘到天上。
  • 气路密封: 袖带和传感器之间的气管,接头处一定要用密封圈。漏气的话,压力曲线会变得很平缓,算法算不出收缩压和舒张压。
  • 电源去耦: 传感器和运放的电源脚,一定要加0.1μF和10μF的去耦电容。我吃过这个亏——没加电容,结果50Hz工频干扰全进来了,滤波都滤不干净。

嗯,这一章就到这里。传感器选型和接口设计,是血压计硬件的基础。基础打好了,后面的算法才能发挥威力。下一章咱们聊聊ADC采样和数字滤波,到时候我会分享一些实时处理的技巧。