第三章 系统架构概览:硬件系统框图、核心模块划分
好,咱们进入正题。这一章我带你从高空俯瞰整个血压计的硬件系统。说白了,就是先画一张「地图」,搞清楚每个模块在哪儿、干什么、怎么连。
我刚开始做这个项目时,也犯过「先焊板子再想架构」的毛病。结果呢?电源纹波干扰传感器,气路密封不严导致测量偏差,折腾了两周才改回来。所以啊,架构设计这一步,千万别省。
3.1 硬件系统框图
先给你看一个我常用的系统框图。它不算复杂,但每个模块都经过实际项目验证。
┌─────────────────────────────────────────────────────────┐
│ 血压计硬件系统 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ 气路模块 │───▶│ 传感器 │───▶│ MCU 主控 │ │
│ │ (气泵+阀) │ │ (压力+脉搏)│ │ (STM32L0系列) │ │
│ └──────────┘ └──────────┘ └───────┬──────────┘ │
│ │ │
│ ┌──────────┐ ┌──────────┐ │ │
│ │ 电源模块 │───▶│ 显示模块 │◀──────────┘ │
│ │ (电池+LDO) │ │ (段码LCD) │ │
│ └──────────┘ └──────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 按键模块 │───▶│ 存储模块 │ │
│ │ (3个按键) │ │ (EEPROM) │ │
│ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
这个框图里,箭头代表数据流和控制流。你看,传感器采集到的模拟信号,经过MCU内部的ADC转换成数字量,然后算法算出收缩压和舒张压,最后送到显示模块。
核心设计原则:每个模块之间用「使能引脚」隔开。不工作时,MCU直接关掉传感器和气泵的电源。这是低功耗的关键。
3.2 核心模块划分
我把整个系统拆成5个核心模块。每个模块都有它的脾气,咱们一个一个说。
3.2.1 传感器模块
传感器是整个系统的「眼睛」。我一般选两种传感器:
- 压力传感器:测量袖带内的气压,范围0~300mmHg。我常用的是MPS20N0040D,精度0.5%FS,价格适中。
- 脉搏传感器:其实很多压力传感器内部集成了脉搏检测功能。比如XGZP6847,它同时输出压力和脉搏信号,省一个芯片。
这里有个坑:传感器输出的是差分信号,MCU的ADC通常是单端输入。所以中间要加一级运放。我习惯用AD8605,它功耗低(每个通道才1mA),而且轨到轨输出,很适合电池供电。
我的经验:传感器和MCU之间加一个RC低通滤波器,截止频率设在100Hz左右。可以滤掉气泵的机械振动噪声。我第一版没加,结果波形上全是毛刺,算法根本没法跑。
3.2.2 MCU主控模块
MCU是大脑。选型时我主要看三点:功耗、ADC性能、休眠模式。
我个人偏爱STM32L0系列。为什么?
- 休眠电流低至0.4μA,比很多专用MCU还省电
- 内置12位ADC,采样率足够(1Msps)
- 有硬件RTC,可以定时唤醒做自检
你看这个代码片段,是MCU进入休眠前的配置:
// 进入Stop模式前的准备
HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); // 关闭不需要的唤醒源
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 醒来后,先稳定时钟,再开传感器
SystemClock_Config(); // 重新配置时钟
HAL_ADC_Start(&hadc); // 启动ADC采集
嗯,这里要注意:从休眠醒来后,时钟需要重新稳定。我遇到过醒来后ADC采样值飘了10%的情况,就是因为时钟没稳定就开采集。后来加了50ms的延时,问题解决。
3.2.3 电源模块
电源是命脉。血压计用两节AAA电池(3V),但传感器和运放需要3.3V。所以需要升压。
我推荐用TPS61099,它效率高达95%,而且静态电流只有1μA。升压到3.3V后,再用一个LDO给MCU供电,纹波控制在10mV以内。
| 供电轨 | 电压 | 最大电流 | 用途 |
|---|---|---|---|
| V_BAT | 2.0~3.2V | 200mA | 气泵电机(直接供电) |
| V_3V3 | 3.3V | 50mA | MCU、传感器、运放 |
| V_LCD | 3.0V | 5mA | 段码LCD显示 |
警告:气泵启动瞬间电流可达150mA,会导致电池电压瞬间跌落。我建议在气泵供电线上并联一个470μF的钽电容。否则MCU可能会复位,测量到一半突然重启,你说气不气人?
3.2.4 气路模块
气路是机械部分,但电气设计也得配合。核心部件就三个:气泵、泄气阀、袖带。
- 气泵:我用的是微型隔膜泵,工作电压3V,最大气压300mmHg。注意选型时看「流量」参数,一般200mL/min就够了。
- 泄气阀:电磁阀,常闭型。测量结束后打开,快速放气。我吃过亏:第一次选的阀响应时间50ms,结果放气太慢,患者不舒服。后来换成10ms的。
- 袖带:标准成人袖带,气囊尺寸22~32cm。袖带和传感器之间用硅胶管连接,长度不超过50cm,否则压力信号会衰减。
气路控制逻辑其实很简单:
// 气路控制状态机
typedef enum {
IDLE, // 待机
INFLATE, // 充气
MEASURE, // 测量(缓慢放气)
DEFLATE, // 快速放气
DONE // 完成
} PumpState;
void Pump_Control(PumpState state) {
switch(state) {
case INFLATE:
HAL_GPIO_WritePin(PUMP_GPIO, GPIO_PIN_SET); // 开气泵
HAL_GPIO_WritePin(VALVE_GPIO, GPIO_PIN_RESET); // 关泄气阀
break;
case MEASURE:
HAL_GPIO_WritePin(PUMP_GPIO, GPIO_PIN_RESET); // 关气泵
// 泄气阀用PWM控制,实现缓慢放气
TIM1->CCR1 = 50; // 占空比20%,放气速度约3mmHg/s
break;
case DEFLATE:
HAL_GPIO_WritePin(VALVE_GPIO, GPIO_PIN_SET); // 全开放气
break;
default:
break;
}
}
你想想看,测量阶段为什么要用PWM控制泄气阀?因为放气速度直接影响测量精度。放太快,脉搏信号采不到;放太慢,患者手臂会麻。我一般控制在2~5mmHg/s。
3.2.5 显示模块
显示我用段码LCD,不是TFT彩屏。为什么?省电啊!段码LCD功耗只有几十μA,TFT动不动就几十mA。
我常用的型号是HT1621驱动的段码屏,3V供电,显示3位数字(收缩压、舒张压、心率)和几个图标(电池、错误、单位)。
驱动代码很简单:
// 显示收缩压 120
void LCD_Display_SYS(uint16_t value) {
uint8_t digits[3];
digits[0] = value / 100; // 百位
digits[1] = (value % 100) / 10; // 十位
digits[2] = value % 10; // 个位
HT1621_Write_Digit(0, digits[0]); // 写入段码
HT1621_Write_Digit(1, digits[1]);
HT1621_Write_Digit(2, digits[2]);
HT1621_Update(); // 刷新显示
}
这里有个小技巧:段码LCD刷新频率不用太高,30Hz就够了。我见过有人用60Hz刷新,白白多耗一倍的电流。其实人眼对静态数字的闪烁不敏感,30Hz完全够用。
3.3 模块间的交互流程
最后,我画一个典型的测量流程,帮你把模块串起来:
- 用户按下「开始」键,MCU从休眠中唤醒
- MCU打开传感器电源,等待100ms稳定
- MCU打开气泵,开始充气,同时ADC实时监测压力值
- 当压力达到180mmHg(或比上次收缩压高30mmHg),关闭气泵
- 打开泄气阀(PWM控制),开始缓慢放气,同时采集脉搏波
- 算法实时计算收缩压和舒张压
- 测量完成,快速放气,显示结果
- MCU保存数据到EEPROM,然后进入休眠
你看,整个流程里,每个模块各司其职,配合得严丝合缝。这就是架构设计的意义——让每个模块只做自己的事,互不干扰。
总结一下:系统架构不是画几张图就完事了。它决定了你的产品能不能稳定工作、功耗能不能做低、后期好不好改。我建议你动手之前,先在纸上把每个模块的接口、时序、功耗都列清楚。磨刀不误砍柴工,这话一点不假。
下一章,咱们深入传感器模块,聊聊压力传感器和脉搏传感器的选型细节。到时候我会分享一个我踩过的坑——传感器输出信号漂移的问题,折腾了我整整一周才找到原因。