基于STM32的脉搏电子血压计系统

基于STM32的脉搏电子血压计系统设计

一、系统总体架构

1.1 系统框图

血压袖带压力 → 压力传感器 → 信号调理电路 → ADC采集
脉搏波信号 → 光电传感器 → 滤波放大电路 → ADC采集
                              ↓
                        STM32F103C8T6
                              ↓
                     LCD显示/按键控制/USB通信

二、硬件设计

2.1 主要硬件组件

模块型号功能
MCUSTM32F103C8T6主控制器
压力传感器MPXV5050GP血压压力测量
光电传感器SEN-11574脉搏波检测
气泵DC 3V微型气泵袖带充气
电磁阀3V常闭型袖带放气
LCD显示OLED 0.96" SSD1306数据显示
ADCSTM32内置12位ADC信号采集

2.2 硬件连接图

STM32引脚配置:
PA0  - 压力传感器ADC输入
PA1  - 脉搏传感器ADC输入
PA2  - 气泵控制(推挽输出)
PA3  - 电磁阀控制(推挽输出)
PB6  - OLED_SCL(I2C)
PB7  - OLED_SDA(I2C)
PB8  - 开始按键(输入下拉)
PB9  - 停止按键(输入下拉)
PA9  - USB_DM(可选)
PA10 - USB_DP(可选)

三、软件设计

3.1 主程序架构

// main.c
#include "stm32f10x.h"
#include "adc.h"
#include "pump_valve.h"
#include "oled.h"
#include "algorithm.h"

#define SAMPLE_RATE 100  // 100Hz采样率

volatile uint32_t pressure_value = 0;
volatile uint32_t pulse_value = 0;
volatile uint8_t measurement_flag = 0;

int main(void)
{
    System_Init();
    ADC_Init();
    OLED_Init();
    Pump_Valve_Init();
    Key_Init();
    
    OLED_ShowString(0, 0, "BP Monitor Ready");
    
    while(1)
    {
        if(Key_Scan() == KEY_START)
        {
            measurement_flag = 1;
            BloodPressure_Measurement();
        }
    }
}

void BloodPressure_Measurement(void)
{
    uint16_t pressure_buffer[1000];
    uint16_t pulse_buffer[1000];
    uint16_t index = 0;
    uint32_t systolic = 0, diastolic = 0, heart_rate = 0;
    
    // 1. 充气阶段
    Pump_On();
    while(pressure_value < 18000)  // 180mmHg
    {
        pressure_buffer[index] = ADC_GetPressure();
        pulse_buffer[index] = ADC_GetPulse();
        index++;
        Delay_ms(10);
        if(index >= 1000) break;
    }
    Pump_Off();
    
    // 2. 线性放气测量阶段
    Valve_Open_Slow();  // 慢速放气
    index = 0;
    
    while(pressure_value > 6000)  // 60mmHg
    {
        pressure_buffer[index] = ADC_GetPressure();
        pulse_buffer[index] = ADC_GetPulse();
        index++;
        Delay_ms(10);
    }
    Valve_Close();
    
    // 3. 算法处理
    Process_BloodPressure(pressure_buffer, pulse_buffer, index, 
                         &systolic, &diastolic, &heart_rate);
    
    // 4. 显示结果
    Display_Result(systolic, diastolic, heart_rate);
}

3.2 ADC采集模块

// adc.c
#include "stm32f10x.h"

void ADC_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    
    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
    
    // 配置PA0, PA1为模拟输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // ADC配置
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_Init(ADC1, &ADC_InitStructure);
    
    // 使能ADC
    ADC_Cmd(ADC1, ENABLE);
    
    // ADC校准
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
}

uint16_t ADC_GetPressure(void)
{
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}

uint16_t ADC_GetPulse(void)
{
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    return ADC_GetConversionValue(ADC1);
}

3.3 气泵与电磁阀控制

// pump_valve.c
#include "stm32f10x.h"
#include "pwm.h"

void Pump_Valve_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    // 气泵控制引脚PA2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 电磁阀控制引脚PA3 (PWM控制放气速度)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 初始化PWM用于精确控制放气速度
    PWM_Init(TIM2, 7200, 100);  // 10kHz PWM
}

void Pump_On(void)
{
    GPIO_SetBits(GPIOA, GPIO_Pin_2);
}

void Pump_Off(void)
{
    GPIO_ResetBits(GPIOA, GPIO_Pin_2);
}

void Valve_Open_Fast(void)
{
    PWM_SetDuty(TIM2, 100);  // 全速放气
}

void Valve_Open_Slow(void)
{
    PWM_SetDuty(TIM2, 20);  // 20%占空比,慢速放气
}

void Valve_Close(void)
{
    PWM_SetDuty(TIM2, 0);
}

3.4 血压算法处理

// algorithm.c
#include <math.h>
#include "filter.h"

#define MAX_PRESSURE 20000  // 200mmHg
#define MIN_PRESSURE 6000   // 60mmHg

void Process_BloodPressure(uint16_t *pressure_data, uint16_t *pulse_data, 
                          uint16_t length, uint32_t *systolic, 
                          uint32_t *diastolic, uint32_t *heart_rate)
{
    uint16_t i, max_amp = 0, max_index = 0;
    float pressure_mmHg, pulse_amplitude;
    float pulse_envelope[1000];
    
    // 1. 滤波处理
    Moving_Average_Filter(pulse_data, length, 5);
    
    // 2. 提取脉搏波包络
    for(i = 10; i < length - 10; i++)
    {
        pulse_envelope[i] = Calculate_Envelope(pulse_data, i, 10);
        
        if(pulse_envelope[i] > max_amp)
        {
            max_amp = pulse_envelope[i];
            max_index = i;
        }
    }
    
    // 3. 寻找特征点(振荡法)
    uint16_t systolic_idx = Find_Systolic_Point(pulse_envelope, max_index);
    uint16_t diastolic_idx = Find_Diastolic_Point(pulse_envelope, max_index);
    
    // 4. 转换为mmHg
    *systolic = (uint32_t)(pressure_data[systolic_idx] * 200.0 / 4096.0);
    *diastolic = (uint32_t)(pressure_data[diastolic_idx] * 200.0 / 4096.0);
    
    // 5. 计算心率
    *heart_rate = Calculate_HeartRate(pulse_data, length);
}

uint32_t Calculate_HeartRate(uint16_t *pulse_data, uint16_t length)
{
    uint16_t peak_count = 0;
    uint16_t last_peak = 0;
    uint32_t total_interval = 0;
    
    for(uint16_t i = 1; i < length - 1; i++)
    {
        if(pulse_data[i] > pulse_data[i-1] && 
           pulse_data[i] > pulse_data[i+1] &&
           pulse_data[i] > 2000)  // 阈值检测
        {
            if(last_peak != 0)
            {
                total_interval += (i - last_peak);
            }
            last_peak = i;
            peak_count++;
        }
    }
    
    if(peak_count > 1)
    {
        float avg_interval = total_interval / (float)(peak_count - 1);
        return (uint32_t)(6000.0 / avg_interval);  // 100Hz采样率
    }
    return 0;
}

3.5 OLED显示模块

// oled.c
#include "ssd1306.h"

void Display_Result(uint32_t systolic, uint32_t diastolic, uint32_t heart_rate)
{
    char buffer[20];
    
    OLED_Clear();
    
    // 显示标题
    OLED_ShowString(24, 0, "BP Monitor");
    OLED_DrawLine(0, 12, 127, 12);
    
    // 显示收缩压
    OLED_ShowString(0, 16, "SYS:");
    sprintf(buffer, "%3d mmHg", systolic);
    OLED_ShowString(40, 16, buffer);
    
    // 显示舒张压
    OLED_ShowString(0, 28, "DIA:");
    sprintf(buffer, "%3d mmHg", diastolic);
    OLED_ShowString(40, 28, buffer);
    
    // 显示心率
    OLED_ShowString(0, 40, "HR :");
    sprintf(buffer, "%3d BPM", heart_rate);
    OLED_ShowString(40, 40, buffer);
    
    // 显示状态
    OLED_ShowString(0, 52, "Status: OK");
}

3.6 滤波算法

// filter.c

// 移动平均滤波
void Moving_Average_Filter(uint16_t *data, uint16_t length, uint8_t window_size)
{
    uint16_t temp[1000];
    uint16_t i, j;
    uint32_t sum;
    
    for(i = window_size/2; i < length - window_size/2; i++)
    {
        sum = 0;
        for(j = 0; j < window_size; j++)
        {
            sum += data[i - window_size/2 + j];
        }
        temp[i] = sum / window_size;
    }
    
    // 复制回原数组
    for(i = window_size/2; i < length - window_size/2; i++)
    {
        data[i] = temp[i];
    }
}

// 脉搏波包络提取
float Calculate_Envelope(uint16_t *data, uint16_t index, uint8_t window)
{
    float max_val = 0;
    uint16_t i;
    
    for(i = index - window; i <= index + window; i++)
    {
        if(i < 1000 && data[i] > max_val)
        {
            max_val = data[i];
        }
    }
    return max_val;
}

四、系统调试与校准

4.1 校准程序

void Calibration_Procedure(void)
{
    OLED_ShowString(0, 0, "Calibration Mode");
    OLED_ShowString(0, 16, "1. Release pressure");
    OLED_ShowString(0, 28, "2. Press key when");
    OLED_ShowString(0, 40, "   ready");
    
    while(!Key_Pressed());
    uint32_t zero_offset = ADC_GetPressure();
    
    OLED_Clear();
    OLED_ShowString(0, 0, "Apply 100mmHg");
    OLED_ShowString(0, 16, "standard pressure");
    
    while(!Key_Pressed());
    uint32_t ref_value = ADC_GetPressure();
    
    // 保存校准参数到EEPROM/Flash
    Save_Calibration(zero_offset, ref_value);
}

五、注意事项

  1. 安全要求

    • 袖带压力不应超过300mmHg
    • 充气时间不宜过长,应有超时保护
    • 加入硬件过压保护电路
  2. 精度优化

    • 使用多次测量取平均值
    • 加入温度补偿算法
    • 定期进行零点校准
  3. 电源管理

    • 使用3.3V LDO稳压
    • 气泵使用单独电源供电
    • 加入低功耗模式
  4. EMC设计

    • 模拟信号使用屏蔽线
    • 数字与模拟电源分离
    • 加入滤波电容

六、扩展功能建议

  1. 数据存储:添加SD卡或EEPROM存储历史数据
  2. 蓝牙传输:添加HC-05模块实现手机APP连接
  3. 语音播报:添加语音芯片实现测量结果播报
  4. USB通信:实现与PC的数据通信和数据分析
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值