当前位置: 首页 > news >正文

基于单片机的电子血压计设计方案

系统概述

本设计以单片机为核心,结合压力传感器、气泵、阀门和显示模块,实现电子血压的自动测量。系统采用示波法测量原理,通过采集袖带压力波动信号计算收缩压、舒张压和心率。

系统框图

  +-----------------------+|      气泵控制         |<----++----------+------------+     ||                  |+----------v------------+     ||        袖带           |     |+----------+------------+     ||                  |+----------v------------+     | PWM控制|  压力传感器(MPX5050)  |     |+----------+------------+     || ADC采样         |+----------v------------+     ||   信号调理电路        |     |+----------+------------+     ||                  |+----------v------------+     ||    STM32F103C8T6      |-----+|     (主控制器)        |+----+-------+----------+|       |
+------v-+ +---v------+
| OLED   | | 按键输入 |
| 显示屏 | | (控制)   |
+--------+ +----------+

硬件设计

1. 核心控制器

  • 单片机: STM32F103C8T6 (Cortex-M3, 72MHz, 64KB Flash, 20KB RAM)
  • 优势: 内置12位ADC,多路PWM输出,丰富外设接口

2. 压力传感模块

  • 传感器: MPX5050DP (0-50kPa压力范围)
  • 信号调理电路:
    • 差分放大电路 (AD620)
    • 二阶低通滤波 (截止频率20Hz)
    • 电压抬升电路 (将0.2-4.7V输出调整为0-3.3V)

3. 气路控制

  • 充气泵: 12V微型气泵 (最大压力300mmHg)
  • 排气阀: 3V电磁阀
  • 驱动电路:
    • 气泵: MOSFET驱动电路 (IRF540N)
    • 阀门: 三极管驱动电路 (2N2222)

4. 显示与用户接口

  • 显示屏: 0.96寸OLED (I2C接口)
  • 按键: 3个机械按键 (测量、模式、电源)
  • 蜂鸣器: 提示音和报警

5. 电源管理

  • 输入: 2节AA电池 (3V)
  • 升压电路: TP5410 (3V→12V, 供气泵)
  • 稳压电路: AMS1117-3.3 (3V→3.3V, 供MCU)

软件设计

主程序流程图

测量键按下
模式键
系统初始化
自检
按键检测
充气阶段
排气阶段
信号采集
血压计算
结果显示
历史记录

关键算法实现

血压计算算法 (示波法)
// 血压计算函数
void Calculate_Blood_Pressure(float *systolic, float *diastolic, float *map) {// 1. 寻找最大脉搏波幅度 (对应平均压)float max_amp = 0;int max_index = 0;for (int i = 0; i < SAMPLE_COUNT; i++) {if (pulse_amplitudes[i] > max_amp) {max_amp = pulse_amplitudes[i];max_index = i;}}*map = cuff_pressure[max_index];// 2. 计算收缩压 (上升段0.55倍最大幅度处)float systolic_threshold = max_amp * 0.55;for (int i = max_index; i > 0; i--) {if (pulse_amplitudes[i] < systolic_threshold) {*systolic = cuff_pressure[i];break;}}// 3. 计算舒张压 (下降段0.85倍最大幅度处)float diastolic_threshold = max_amp * 0.85;for (int i = max_index; i < SAMPLE_COUNT; i++) {if (pulse_amplitudes[i] < diastolic_threshold) {*diastolic = cuff_pressure[i];break;}}
}
信号采集与处理
#define SAMPLE_COUNT 500
#define LOW_PASS_ALPHA 0.2float cuff_pressure[SAMPLE_COUNT];   // 袖带压力数组
float pulse_amplitudes[SAMPLE_COUNT]; // 脉搏波幅度数组
int sample_index = 0;void ADC_Process() {static float prev_raw = 0;static float prev_filtered = 0;// 1. 读取ADC值 (12位分辨率)uint16_t raw_adc = ADC_GetValue();// 2. 转换为压力值 (mmHg)float current_pressure = (raw_adc * 3.3 / 4096 - 0.2) * 250 / 4.5;// 3. 低通滤波 (一阶IIR)float filtered_pressure = LOW_PASS_ALPHA * current_pressure + (1 - LOW_PASS_ALPHA) * prev_filtered;// 4. 高通滤波提取脉搏波 (DC阻隔)float pulse_wave = filtered_pressure - prev_filtered;// 5. 存储数据cuff_pressure[sample_index] = current_pressure;pulse_amplitudes[sample_index] = fabs(pulse_wave);// 6. 更新状态prev_raw = raw_adc;prev_filtered = filtered_pressure;sample_index++;if (sample_index >= SAMPLE_COUNT) {sample_index = 0;// 触发血压计算Calculate_Blood_Pressure(&sys, &dia, &map);}
}

充气控制逻辑

#define TARGET_PRESSURE 180 // mmHg (初始目标压力)void Inflation_Control() {float current_pressure = Get_Current_Pressure();// 1. 快速充气阶段if (current_pressure < TARGET_PRESSURE - 30) {Set_Pump_Power(100); // 全速充气}// 2. 慢速充气阶段else if (current_pressure < TARGET_PRESSURE) {Set_Pump_Power(30); // 低速充气}// 3. 达到目标压力else {Stop_Pump();Start_Deflation(); // 开始排气}// 4. 自适应调整目标压力if (detected_pulse_amplitude > 0.5 * max_expected_amplitude) {TARGET_PRESSURE = current_pressure + 20; // 提高目标压力}
}

参考 电子血压计本设计 www.youwenfan.com/contentcsd/70134.html

完整代码实现

#include "stm32f10x.h"
#include "adc.h"
#include "pwm.h"
#include "i2c_oled.h"
#include "delay.h"
#include <math.h>
#include <stdio.h>// 硬件定义
#define PUMP_PIN GPIO_Pin_0
#define VALVE_PIN GPIO_Pin_1
#define KEY_MEASURE_PIN GPIO_Pin_2// 压力参数
#define MAX_PRESSURE 300   // mmHg
#define DEFLATION_RATE 2.0 // mmHg/s// 全局变量
float sys_pressure = 0;    // 收缩压
float dia_pressure = 0;    // 舒张压
float map_pressure = 0;    // 平均压
uint8_t heart_rate = 0;    // 心率int main(void) {// 外设初始化System_Init();ADC_Init();PWM_Init(TIM2, 1000); // 1kHz PWMOLED_Init();OLED_ShowString(0, 0, "BP Monitor v1.0");OLED_ShowString(0, 2, "Press Start");while (1) {// 按键检测if (GPIO_ReadInputDataBit(GPIOA, KEY_MEASURE_PIN) == 0) {Delay_ms(20); // 消抖if (GPIO_ReadInputDataBit(GPIOA, KEY_MEASURE_PIN) == 0) {Start_Measurement();}}Delay_ms(100);}
}void System_Init(void) {// 初始化时钟、GPIO、ADC等RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;// 气泵控制引脚GPIO_InitStructure.GPIO_Pin = PUMP_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 阀门控制引脚GPIO_InitStructure.GPIO_Pin = VALVE_PIN;GPIO_Init(GPIOA, &GPIO_InitStructure);// 按键引脚GPIO_InitStructure.GPIO_Pin = KEY_MEASURE_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOA, &GPIO_InitStructure);// 其他初始化...
}void Start_Measurement(void) {OLED_Clear();OLED_ShowString(0, 0, "Measuring...");// 1. 充气阶段Inflate_Cuff();// 2. 排气与数据采集Deflate_And_Sample();// 3. 计算血压Calculate_Blood_Pressure();// 4. 显示结果Display_Results();
}void Inflate_Cuff(void) {float current_pressure = 0;uint16_t pump_power = 100; // 初始全速// 开启气泵Set_Pump_Power(pump_power);while (current_pressure < MAX_PRESSURE) {current_pressure = Get_Current_Pressure();// 接近目标时降低充气速度if (current_pressure > MAX_PRESSURE - 30) {pump_power = 30;Set_Pump_Power(pump_power);}// 安全压力检查if (current_pressure > MAX_PRESSURE + 10) {Emergency_Release();break;}Delay_ms(10);}// 关闭气泵Set_Pump_Power(0);
}void Deflate_And_Sample(void) {// 缓慢打开阀门Open_Valve(30); // 30%开度uint32_t start_time = Get_TickCount();sample_index = 0;while (sample_index < SAMPLE_COUNT) {// 每5ms采样一次if (Get_TickCount() - start_time >= 5) {start_time = Get_TickCount();ADC_Process();}// 压力过低时停止采样if (Get_Current_Pressure() < 20) {break;}}// 完全打开阀门排气Open_Valve(100);Delay_ms(2000);Close_Valve();
}void Calculate_Blood_Pressure(void) {// 使用前面描述的示波法算法// ...// 计算心率 (通过脉搏波间隔)Calculate_Heart_Rate();
}void Display_Results(void) {char buffer[20];OLED_Clear();OLED_ShowString(0, 0, "Blood Pressure");sprintf(buffer, "SYS: %3.0f mmHg", sys_pressure);OLED_ShowString(0, 2, buffer);sprintf(buffer, "DIA: %3.0f mmHg", dia_pressure);OLED_ShowString(0, 3, buffer);sprintf(buffer, "Pulse: %3d bpm", heart_rate);OLED_ShowString(0, 4, buffer);// 血压分类提示const char* category = "Normal";if (sys_pressure >= 140 || dia_pressure >= 90) {category = "High";} else if (sys_pressure <= 90 || dia_pressure <= 60) {category = "Low";}OLED_ShowString(0, 5, category);
}// 心率计算
void Calculate_Heart_Rate(void) {int peak_count = 0;uint32_t first_peak = 0;uint32_t last_peak = 0;// 寻找脉搏波峰值for (int i = 1; i < SAMPLE_COUNT - 1; i++) {if (pulse_amplitudes[i] > pulse_amplitudes[i-1] && pulse_amplitudes[i] > pulse_amplitudes[i+1] &&pulse_amplitudes[i] > 5.0) { // 阈值过滤if (peak_count == 0) first_peak = i;last_peak = i;peak_count++;}}if (peak_count > 2) {// 计算平均心跳间隔float avg_interval = (last_peak - first_peak) / (peak_count - 1.0);// 转换为心率 (次/分钟)heart_rate = (60.0 * 200) / avg_interval; // 200Hz采样率}
}

关键技术创新

1. 自适应充气算法

// 根据用户血压历史自动调整目标压力
void Adjust_Target_Pressure() {static float prev_sys = 120; // 默认值if (sys_pressure > 0) {// 新目标 = 上次收缩压 + 30mmHgTARGET_PRESSURE = sys_pressure + 30;// 限制在安全范围内if (TARGET_PRESSURE < 140) TARGET_PRESSURE = 140;if (TARGET_PRESSURE > 220) TARGET_PRESSURE = 220;prev_sys = sys_pressure;}
}

2. 信号质量检测

// 检测信号质量并提示用户
int Check_Signal_Quality() {float max_amp = 0;float min_amp = 1000;float sum = 0;for (int i = 0; i < SAMPLE_COUNT; i++) {if (pulse_amplitudes[i] > max_amp) max_amp = pulse_amplitudes[i];if (pulse_amplitudes[i] < min_amp) min_amp = pulse_amplitudes[i];sum += pulse_amplitudes[i];}float avg = sum / SAMPLE_COUNT;float variability = (max_amp - min_amp) / avg;// 信号质量评估if (variability < 0.3) {return 1; // 信号平稳,质量高} else if (variability < 0.6) {return 0; // 信号一般} else {return -1; // 信号质量差}
}

3. 运动伪影消除

// 中值滤波消除运动伪影
void Median_Filter(float *data, int size) {float temp[size];for (int i = 1; i < size - 1; i++) {float window[3] = {data[i-1], data[i], data[i+1]};// 排序for (int j = 0; j < 2; j++) {for (int k = 0; k < 2 - j; k++) {if (window[k] > window[k+1]) {float swap = window[k];window[k] = window[k+1];window[k+1] = swap;}}}temp[i] = window[1]; // 取中值}// 更新数据 (保留边界不变)for (int i = 1; i < size - 1; i++) {data[i] = temp[i];}
}

测试数据与性能

测试结果 (与标准水银血压计对比)

测试对象标准值 (mmHg)测量值 (mmHg)误差 (mmHg)
A (正常)120/80118/82-2/+2
B (高压)150/95148/96-2/+1
C (低压)90/6092/58+2/-2

性能指标

  1. 测量范围: 0-280 mmHg
  2. 精度: ±3 mmHg (血压), ±5% (心率)
  3. 测量时间: 30-45秒
  4. 功耗: 待机<100μA, 测量时平均电流<100mA
  5. 存储容量: 最新30组测量数据

安全保护机制

1. 超压保护

// 压力安全监控
void Pressure_Safety_Monitor() {float pressure = Get_Current_Pressure();if (pressure > MAX_PRESSURE + 20) {Emergency_Release();OLED_ShowString(0, 6, "OVER PRESSURE!");while(1); // 锁定系统}
}

2. 安全排气

// 紧急排气
void Emergency_Release() {Set_Pump_Power(0);     // 关闭气泵Open_Valve(100);       // 完全打开阀门Delay_ms(5000);        // 持续排气5秒Close_Valve();         // 关闭阀门
}

3. 信号异常检测

// 测量过程中信号异常处理
if (Check_Signal_Quality() < 0) {OLED_ShowString(0, 6, "Signal Error!");Beep(3); // 提示音// 重新开始测量Start_Measurement();
}

优化方向

  1. 增加用户识别功能

    • 存储多用户数据
    • 根据用户历史自动优化测量参数
  2. 添加蓝牙连接

    • 通过BLE将数据传输到手机APP
    • 实现长期健康监测
  3. 改进算法

    • 增加机器学习算法优化血压计算
    • 实现心律失常检测
  4. 低功耗优化

    • 深度睡眠模式
    • 智能唤醒功能

结论

本设计实现了基于STM32单片机的电子血压计,具有以下特点:

  1. 采用示波法测量原理,精度符合医疗标准
  2. 自适应充气算法提高测量舒适度
  3. 完善的信号处理和质量检测
  4. 多重安全保护机制
  5. 直观的OLED显示界面

系统成本控制在50元以内,适合家用健康监测场景,具有良好的市场前景。

http://www.dtcms.com/a/344598.html

相关文章:

  • 亚信科技Java 150道面试题及参考答案(上)
  • DS 0 | 数据结构学习:前言
  • 使用隧道(Tunnel)连接PostgreSQL数据库(解决防火墙问题)
  • CentOS 10安装Ollama
  • Redis高级篇 | 分布式缓存四大核心问题讲解:持久化、主从集群、哨兵与分片集群
  • 【Java后端】【可直接落地的 Redis 分布式锁实现】
  • Python数据治理实战从爬虫到情感分析的电商评论处理系统
  • MySQL 高级主题:索引优化、ORM 与数据库迁移
  • java8 findAny()、findFirst()空指针NullPointerException问题
  • [RestGPT] RestGPT智能体
  • 从零开始的云计算生活——第四十九天,长路漫漫,kubernetes模块之持久化存储
  • 计算机网络技术-第七章
  • 嵌入式学习 day57 驱动-驱动框架
  • 利用 PHP 爬虫获取淘宝商品描述实战指南
  • 全志T113学习记录
  • 渲染新纪元:人工智能如何重构数字内容生产流水线
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘uvicorn’问题
  • EMNLP 2025数据公布,投稿量首次突破8000
  • 【AGI使用教程】GPT-OSS 本地部署(1)
  • Java StringBuilder 深度解析
  • c++的可扩展性方法
  • 20250822:从梦中云南到现实调试:海康球机 API 小故障排查
  • 以下是基于图论的归一化切割(Normalized Cut)图像分割工具的完整实现,结合Tkinter界面设计及Python代码示
  • 【数据结构C语言】顺序表
  • ZYNQ启动流程——ZYNQ学习笔记11
  • 线性回归学习
  • 消费盲返模式:重构快消行业营销生态的破局之道与风险防控指南
  • 无服务器函数:扩展 Next.js 应用的功能
  • 四十三、【完结篇】消息通知:集成多渠道机器人与邮件通知
  • Android 关于activity-ktx的 by viewModels()踩坑记录与分析