1. 项目背景与设计初衷
血压作为人体健康的重要指标之一,其监测对于高血压患者尤为重要。传统水银血压计虽然测量准确,但存在体积大、操作复杂、易碎且可能造成汞污染等问题。而市面上的电子血压计往往价格昂贵,维修成本高。基于这些痛点,我决定设计一款基于51单片机的家用电子血压计。
选择51单片机作为核心控制器主要基于三点考量:首先,STC89C51价格低廉(市场价约5-8元),大幅降低整机成本;其次,其35个GPIO口完全满足传感器、显示器和外设控制需求;最后,成熟的开发环境和丰富的学习资源降低了开发门槛。实测表明,这套方案整机成本可控制在50元以内,仅为品牌产品的1/5。
2. 系统架构设计
2.1 整体硬件框架
系统采用模块化设计,主要包含以下核心模块:
code复制[传感器层]
├─ MPX5050DP压力传感器(0-50kPa量程)
├─ DS18B20温度传感器(±0.5℃精度)
└─ 4x4矩阵键盘(设置/控制)
[控制层]
└─ STC89C51RC(11.0592MHz晶振)
[执行层]
├─ LCD1602液晶屏(16x2字符)
├─ 微型气泵(0-300mmHg工作压力)
└─ 蜂鸣器/LED状态指示
[电源层]
└─ LM2596-5.0(输入7-36V,输出5V/3A)
2.2 血压测量原理实现
采用示波法进行血压测量,其物理模型基于以下公式:
code复制P(t) = P0 + ΔP·sin(2πft)
其中P0为平均压,ΔP为脉动压幅度。通过气压传感器采集袖带压力振荡波,提取包络线后:
- 收缩压判定:当振荡波幅值达到最大幅值的50%(Ks=0.5)时对应的袖带压力
- 舒张压判定:当振荡波幅值下降至最大幅值的80%(Kd=0.8)时对应的袖带压力
实际算法实现时,采用滑动窗口滤波(窗口宽度15个采样点)消除高频噪声,再通过三点差分法检测拐点位置。
3. 关键硬件设计详解
3.1 传感器信号调理电路
压力传感器输出为模拟信号,需经过两级处理:
c复制// 第一级:仪表放大器(AD620)
Vout1 = G*(Vp - Vn) + Vref
// G=100(Rg=499Ω),Vref=2.5V(TL431基准)
// 第二级:有源低通滤波(截止频率10Hz)
fc = 1/(2πRC) = 10Hz (R=16kΩ, C=1μF)
温度传感器采用单总线协议,硬件连接需注意:
提示:DS18B20的数据线必须接4.7kΩ上拉电阻,否则无法正常通信
3.2 电源系统设计
采用LM2596开关稳压方案,其效率曲线如下图所示:
code复制[效率曲线]
输入12V时:
| 负载电流 | 效率 |
|----------|-------|
| 0.5A | 92% |
| 1A | 94% |
| 2A | 91% |
关键布局要点:
- 续流二极管(1N5822)距芯片不超过1cm
- 反馈电阻(R1=1kΩ,R2=3kΩ)靠近FB引脚
- 输出电容采用低ESR的47μF钽电容
3.3 PCB设计陷阱规避
在首版PCB调试中发现以下问题:
- 晶振问题:11.0592MHz晶振走线过长导致起振失败
- 解决:缩短走线至<1cm,并包地处理
- ADC干扰:数字信号线平行于模拟走线导致读数波动
- 解决:采用"井"字形布局,模拟/数字分区
经验:51单片机的P0口必须接10kΩ上拉电阻,否则无法正常驱动LCD1602
4. 软件系统实现
4.1 主程序流程图
c复制void main() {
硬件初始化();
while(1) {
if(测量按键按下) {
气泵充气(至180mmHg);
缓慢放气(3mmHg/s);
实时采样(50Hz);
计算血压();
显示结果();
}
温度检测(每10s);
}
}
4.2 关键算法实现
血压计算核心代码:
c复制// 寻找脉搏波包络极值点
uint16_t findPeaks(uint16_t *data, uint16_t len) {
uint16_t maxVal = 0;
for(uint16_t i=5; i<len-5; i++) {
if(data[i]>data[i-1] && data[i]>data[i+1]) {
if(data[i] > maxVal) maxVal = data[i];
}
}
return maxVal;
}
// 计算收缩压/舒张压
void calcBP(uint16_t maxAmp) {
uint16_t sp=0, dp=0;
for(uint16_t p=180; p>60; p--) {
uint16_t amp = getAmpAtPressure(p);
if(!sp && amp>=maxAmp*0.5) sp = p;
if(!dp && amp>=maxAmp*0.8) dp = p;
}
saveResult(sp, dp);
}
4.3 抗干扰措施
-
软件滤波:采用复合滤波算法
c复制// 中值滤波+滑动平均 uint16_t filter(uint16_t newVal) { static uint16_t buf[5]; // 更新缓冲区 for(uint8_t i=4; i>0; i--) buf[i] = buf[i-1]; buf[0] = newVal; // 中值滤波 sort(buf, 5); uint16_t mid = buf[2]; // 滑动平均 return (mid + buf[1] + buf[3])/3; } -
异常处理:当检测到以下情况时自动重启测量:
- 充气时间超过30秒未达目标压力
- 放气过程中压力持续1秒无变化
- 计算结果收缩压<60或>250mmHg
5. 系统调试与优化
5.1 校准流程
使用标准压力源进行三点校准:
code复制1. 零点校准:通大气时调整VR1使ADC读数为0
2. 中点校准:施加150mmHg压力,调整运放增益使读数=1500
3. 满量程校准:施加300mmHg压力,验证线性度
5.2 实测数据对比
与欧姆龙HEM-7121对比测试结果(单位:mmHg):
code复制| 测试者 | 本设计(SYS/DIA) | 欧姆龙(SYS/DIA) | 误差 |
|--------|------------------|------------------|------|
| A | 118/76 | 120/78 | -2/-2|
| B | 132/84 | 135/85 | -3/-1|
| C | 145/92 | 148/90 | -3/+2|
5.3 功耗优化
通过以下措施将待机功耗从85mA降至12mA:
- 气泵采用PWM控制(30kHz)
- LCD背光自动关闭(30秒无操作)
- 单片机空闲模式(IDLE)下关闭ADC
6. 使用注意事项
-
测量姿势:
- 袖带中心与心脏保持同一水平面
- 手臂自然平放,掌心向上
- 测量前静坐5分钟
-
维护要点:
- 每月用酒精棉清洁气袖内衬
- 避免传感器接触液体
- 长期不用时取出电池
-
典型故障处理:
code复制现象:显示"Err1" 原因:压力传感器异常 处理:检查传感器连接线 现象:测量值明显偏高 原因:气路漏气 处理:更换袖带或连接管
在实际使用中发现,早晨起床后1小时内测量结果最为稳定。建议用户建立测量日志,记录每日相同时段的血压变化趋势。对于硬件改进,下一步计划增加蓝牙模块,实现测量数据自动上传手机APP的功能。