基于STM32的智能血压计设计:从硬件电路到软件算法的嵌入式系统实战
简介:本资源是一套完整的基于STM32单片机的智能血压计软硬件设计实现方案,面向嵌入式初学者、电子设计竞赛学生及医疗电子方向开发者,解决血压信号采集、算法处理、OLED显示与串口通信等核心功能集成问题。压缩包共143个文件,涵盖77个头文件(.h)与36个源文件(.c),构成完整的HAL库驱动框架(含ADC、I2C、TIM、UART、RTC等关键外设配置);另含原理图(.SchDoc)、PCB工程(.PcbDoc)、器件库(.SchLib/.PcbLib)、编译输出(.hex)、调试配置(.dbgconf)及说明文档(.pdf/.txt),总大小4.74MB。已有59人学习下载,资源结构规范,支持Keil MDK与STM32CubeMX双开发环境,提供可直接烧录运行的固件与完整电路设计文件,便于快速复现、模块化调试及二次开发拓展。
1. 项目概述与核心价值
最近几年,身边关注健康数据的朋友越来越多,尤其是血压这个指标。市面上的智能血压计琳琅满目,但作为一个电子爱好者,我总想亲手打造一个,既能满足精准测量的需求,又能深入理解其背后的软硬件协同逻辑。这次,我决定以STM32单片机为核心,从零开始设计一款智能血压计。这个项目不仅仅是把传感器数据读出来那么简单,它涉及模拟信号调理、精密算法实现、人机交互以及可靠的硬件设计,是一个综合性极强的嵌入式系统实战案例。
对于电子工程师或嵌入式学习者来说,通过这个项目,你能系统掌握如何将生物医学信号转换为可靠的数字信息,如何设计低噪声的模拟前端电路,以及如何编写稳健的嵌入式程序来处理复杂的振荡波算法。无论你是想参加电子设计竞赛,还是为智能穿戴设备开发积累经验,这个从原理图、PCB到嵌入式软件的全流程设计,都能提供一份扎实的参考。接下来,我将详细拆解整个设计过程,分享其中的技术要点和踩过的坑。
2. 整体系统架构与方案选型
设计一个血压计,首先得明确它的工作原理。我们采用的是示波法,这也是市面上主流电子血压计采用的方法。它的基本原理是:袖带充气阻断动脉血流,然后缓慢放气,在这个过程中,动脉血管壁的搏动会传递到袖带,引起袖带内压力的微小波动。我们的硬件需要精确捕捉这个包含直流分量(静态压力)和交流分量(脉搏波)的复合信号,再由软件算法从中提取出收缩压和舒张压。
2.1 核心控制器选型:为什么是STM32?
选择STM32系列单片机作为核心,是基于多方面的考量。首先,血压信号处理需要较高的模拟采样精度和实时性。STM32F103C8T6(俗称“蓝桥杯”或“江科大”同款)这类Cortex-M3内核的芯片,主频可达72MHz,完全能满足实时采样和算法运算的需求。其内置的12位ADC,在合理设计前端电路的情况下,足以分辨出mmHg级别的压力变化。
其次,我们需要丰富的片上外设。除了ADC,还需要定时器(TIM)来精确控制气泵和排气阀的PWM驱动,需要USART或I2C与OLED显示屏通信,需要足够的GPIO来控制按键和指示灯。STM32的生态成熟,HAL库或标准库降低了开发门槛,丰富的在线资源和社区支持(如“江科大STM32”教程)能让开发过程事半功倍。相比于传统的51单片机(如STC89C52RC),STM32在性能、外设和开发效率上具有代差优势。
2.2 传感器与信号链设计
压力传感器是整个系统的“眼睛”。我们选用医用级的MPS系列或类似的高精度、低功耗气压传感器。它输出的是与压力成比例的模拟电压信号。这个原始信号非常微弱,且混杂着高频噪声和50Hz工频干扰,必须经过精心设计的模拟前端电路进行调理。
信号链的核心是一个仪表放大器(如AD620或INA128),用于放大微弱的脉搏波交流信号。同时,我们需要一个减法电路或电平抬升电路,将放大后的交流信号叠加到一个合适的直流偏置上,以确保其电压范围完全落在STM32 ADC的输入量程(通常0-3.3V)之内。此外,必须设计抗混叠低通滤波器,截止频率设置在10Hz左右,因为有效的脉搏波频率通常低于5Hz,这样可以最大限度地抑制高频噪声。
注意 :模拟地(AGND)和数字地(DGND)的分离与单点连接是硬件设计成败的关键。必须使用磁珠或0欧电阻在电源入口处进行单点连接,否则数字电路的开关噪声会串入敏感的模拟信号中,导致测量结果跳动剧烈。
2.3 执行机构与控制逻辑
执行机构包括气泵和高速排气阀。气泵通常采用微型隔膜泵,由MOS管驱动,通过STM32的PWM控制其转速,实现快速充气和慢速线性泄压。高速排气阀则是一个通径较大的电磁阀,用于测量结束后快速将袖带压力泄为零。控制逻辑是一个状态机:空闲 -> 快速充气至目标压力(如180mmHg)-> 慢速线性泄压(如3-5mmHg/s)并同步高速采样 -> 测量结束,快速排气 -> 计算并显示结果。
3. 硬件设计深度解析:从原理图到PCB
硬件是测量的基石,任何一个细节的疏忽都可能导致软件算法“巧妇难为无米之炊”。这里我使用Altium Designer进行设计,也会提及与Allegro等工具的一些差异思考。
3.1 原理图设计要点与常见陷阱
原理图不仅是连接的描述,更是设计思想的体现。在绘制血压计原理图时,以下几个部分需要格外关注:
- 传感器接口电路 :压力传感器的供电必须极其稳定,建议使用LDO(如AMS1117-3.3)单独供电,并搭配π型滤波电路。其输出信号线在原理图上就要标明为“模拟走线”,提醒PCB布局时需特别处理。
- 运放电路参数计算 :以仪表放大器为例,其放大倍数
G = 1 + (50kΩ / Rg)。我们需要根据传感器输出脉搏波的幅值(可能只有几毫伏)和STM32 ADC的输入范围来反推需要的放大倍数。例如,若脉搏波幅值最大为5mV,我们希望放大到1Vpp,则增益需要200倍,据此可计算出Rg约为251Ω。电阻必须选用1%精度的高稳定性薄膜电阻。 - 电源树与去耦 :为STM32、运放、数字逻辑、气泵驱动分别规划电源路径。每个IC的电源引脚附近,必须放置一个0.1uF的陶瓷去耦电容,并且尽可能靠近引脚。对于MCU,还需要在电源入口处增加一个10uF的钽电容或电解电容,以应对瞬时电流需求。
- 保护电路 :袖带接口处可能因误操作引入静电或高压,需要加入TVS管和限流电阻。ADC输入引脚前可以串联一个数百欧姆的电阻并并联钳位二极管到电源和地,防止过压冲击损坏单片机。
实操心得 :画原理图时,养成给关键网络命名的习惯,比如
PPG_SIGNAL(光电容积脉搏波,如果扩展功能)、CUFF_PRESSURE(袖带压力)。这会让后续的PCB布局和程序阅读清晰很多。另外,务必建立自己的原理图库和PCB封装库,确保封装与实际购买的元件(如贴片电阻电容的0603、0805规格)完全一致,这是避免第一次打板就翻车的最有效方法。
3.2 PCB布局布线核心规则
PCB设计是将原理图转化为实体的关键一步,对于模拟混合信号系统,布局布线的重要性甚至超过原理图本身。
- 分区布局 :明确划分模拟区(传感器、运放、滤波器)和数字区(STM32、晶振、数字逻辑)。两个区域之间最好用一条“壕沟”(无铜区域)进行隔离,让信号只能通过预设的路径(如电源连接点)跨区。
- 模拟信号走线黄金法则 :
- 最短路径 :从传感器输出到运放输入,再到ADC输入引脚的走线必须尽可能短。
- 远离干扰源 :绝对远离晶振、时钟线、数字开关信号线(如PWM驱动气泵的走线)。如果必须交叉,应使用垂直交叉,切忌平行走线。
- 包地保护 :对于关键的模拟信号线,可以用地线将其包围起来,并在两端通过过孔连接到内部地平面,形成屏蔽。
- 禁止在模拟器件下方走数字线 :PCB的底层或内层,在运放、滤波器芯片的正下方区域,禁止任何数字信号线穿过。
- 地平面设计 :对于双层板,建议顶层和底层都尽可能铺铜作为地平面,并通过大量过孔缝合。模拟部分的地平面应保持完整,避免被电源线或信号线割裂。数字地平面可以适当分割,但模拟地和数字地的连接点必须唯一,通常选择在电源输入滤波电容的接地端。
- 电源线宽计算 :气泵电机启动瞬间电流较大,可能达到1A以上。根据电流大小计算所需线宽。一个简易公式:对于1oz铜厚,温升10°C时,约20mil线宽可通过1A电流。因此,驱动气泵的电源走线需要加粗,必要时在阻焊层开窗,后期可以手工焊锡增加载流能力。
- 晶振布局 :STM32的晶振及其负载电容必须紧贴芯片相关引脚放置,走线短而直,下方禁止其他信号线穿过,并用地线包围。
踩坑记录 :我第一次打样时,将气泵的PWM驱动线(数字高频信号)布在了压力传感器模拟信号线的相邻层且平行走了很长一段距离。结果ADC采样值上叠加了规律的毛刺,导致脉搏波形态严重失真,算法完全无法工作。后来重新布局,将这两类信号彻底分开,问题立刻解决。
3.3 设计检查与生产文件输出
完成布线后,一定要使用DRC(设计规则检查)功能,检查线宽、线距、孔径等是否符合PCB厂家的工艺能力(如嘉立创的常规工艺)。然后进行3D预览,检查元件之间是否有机械干涉。
生成生产文件(Gerber)时,需要包含顶层丝印层、顶层阻焊层、顶层布线层、底层布线层、底层阻焊层、钻孔图等。给PCB板厂的文件通常是Gerber格式,而 Gerber文件转PCB文件 通常是反向工程或借鉴他人设计时的需求,正常正向设计不需要此步骤。在嘉立创等平台下单时,如果需要对PCB上的位号(元件标识)尺寸进行批量修改,可以在其提供的在线Gerber查看器或编辑器中,找到位号编辑功能进行调整,但这通常在原设计文件中修改更直接。
4. 嵌入式软件设计与算法实现
硬件提供了干净的“食材”,软件则是烹饪出结果的“厨艺”。STM32的程序主要围绕精准采样、信号处理和状态机控制展开。
4.1 开发环境搭建与基础驱动
我选择使用STM32CubeIDE作为开发环境,它集成了CubeMX配置工具和编译调试功能,非常方便。首先用CubeMX进行引脚和外设初始化:
- ADC :配置为连续扫描模式,使用DMA(直接存储器访问)将采样数据直接搬运到内存数组。这样不占用CPU资源,且能保证采样的连续性。采样率设置为100-200Hz即可,过高会引入更多噪声,增加不必要的计算量。
- 定时器(TIM) :用一个定时器产生PWM驱动气泵(频率几十Hz即可),另一个定时器产生精确的中断(如1ms),用于控制泄压速度和整个测量过程的状态机计时。
- USART/I2C :用于驱动OLED显示屏,实时显示压力值和最终结果。
- GPIO :配置按键输入和LED指示输出。
初始化完成后,生成工程代码,在此基础上进行应用层开发。
4.2 核心算法:脉搏波提取与血压计算
这是整个项目的软件核心。ADC通过DMA持续采样得到的是袖带的总压力信号 P_total(t) ,它包含缓慢下降的直流压力 P_dc(t) (袖带静态压)和微弱的交流脉搏波 P_ac(t) 。
- 数字滤波 :首先对
P_total(t)进行数字低通滤波(如一阶IIR滤波器),得到近似P_dc(t)。然后用原信号减去这个直流分量,初步得到P_ac(t)。接着,对P_ac(t)再进行一次带通滤波(例如0.5Hz - 8Hz),以进一步滤除基线漂移和高频噪声,得到纯净的脉搏波振荡信号Osc(t)。 - 特征点提取 :在慢速泄压过程中,随着袖带压力从高于收缩压到低于舒张压,脉搏波振幅
Amp(t)会经历从无到有,增大到峰值,再减小到无的过程。我们需要实时计算每个脉搏周期的振幅(波峰-波谷值)。 - 血压判定 :示波法的主流判定准则之一是“幅度系数法”。找到整个测量过程中脉搏波振幅的最大值
Amp_max。收缩压(SYS)对应的袖带压力点,是振幅达到Amp_max * K1时对应的压力,K1通常是一个经验系数,约在0.45-0.55之间。舒张压(DIA)对应的点,是振幅达到Amp_max * K2时对应的压力,K2约在0.65-0.85之间。这些系数需要通过临床实验数据进行标定和优化。 - 心率计算 :通过计算脉搏波峰值的间隔时间,即可得到心率值。
// 简化的算法流程示意(伪代码)
while(测量状态 == 线性泄压中) {
raw_adc = DMA_buffer[latest_index]; // 获取最新ADC值
pressure_dc = lowpass_filter(raw_adc); // 低通得直流压力
pressure_ac = raw_adc - pressure_dc; // 减去直流得交流
osc_wave = bandpass_filter(pressure_ac); // 带通得纯净振荡波
if(检测到osc_wave的一个完整周期) {
current_amp = 当前周期波峰 - 当前周期波谷;
update_amplitude_array(current_amp, current_dc_pressure); // 记录振幅-压力对
}
// 状态机控制泄压阀,使dc压力以恒定速度下降
control_exhaust_valve();
}
// 测量结束后
find_max_amplitude();
sys_pressure = find_pressure_corresponding_to_amplitude(max_amp * 0.5);
dia_pressure = find_pressure_corresponding_to_amplitude(max_amp * 0.7);
4.3 程序架构与状态机
一个清晰的程序架构能让代码易于维护和调试。我采用基于时间片轮询和中断触发的混合架构。
- 主循环 :负责非实时性任务,如按键扫描、显示刷新、最终结果计算与显示。
- 定时器中断 :1ms定时中断,作为系统“心跳”。在这里实现精确的泄压控制(例如,每50个中断周期,即50ms,控制排气阀打开一个固定短时间,以实现平均每秒下降3mmHg的线性泄压)。同时,这里也是高级测量状态机(充气、稳压、泄压、排气)的推进器。
- DMA传输完成中断/半传输中断 :当DMA搬运完一半或全部ADC数据时触发。在此中断服务程序中,设置一个数据就绪标志位。主循环或后台任务检测到这个标志位后,对这批新数据进行批量滤波和算法处理,这样能提高效率。
状态机设计如下:
S_IDLE (空闲) -> [按键按下] -> S_INFLATE_FAST (快速充气) -> [压力>=目标值] -> S_DEFLATE_LINEAR (线性泄压采样) -> [压力<=阈值 或 超时] -> S_EXHAUST_FAST (快速排气) -> [排气完成] -> S_CALCULATE (计算) -> S_DISPLAY (显示结果) -> S_IDLE
5. 系统调试、标定与优化
硬件焊接完成、程序烧录后,真正的挑战才刚刚开始。没有经过调试和标定的血压计只是一个玩具。
5.1 硬件调试与信号验证
- 电源与基础功能 :首先不上电测量各电源与地之间是否短路。上电后,测量LDO输出是否稳定为3.3V,STM32能否正常启动,晶振是否起振。
- 模拟通路验证 :这是重中之重。使用标准压力源(或用一个精密可调稳压源模拟传感器输出)和示波器。给传感器施加一个固定压力,用示波器依次测量传感器输出端、运放输出端、滤波器输出端的波形和电压,是否与理论计算值相符。然后,用手有节奏地按压气囊模拟脉搏,观察最终输入到STM32 ADC引脚的信号,是否能看到清晰、干净的振荡波形。
- 执行机构测试 :单独测试气泵和排气阀的驱动电路,确保PWM能正常控制气泵转速,GPIO能可靠地开关电磁阀。
5.2 软件调试与算法验证
- 数据可视化 :将STM32 ADC采样到的原始数据、滤波后的数据、计算出的脉搏波振幅等,通过串口实时发送到电脑。利用Python的Matplotlib或串口绘图工具(如SerialPlot)绘制成曲线。这是调试算法的“眼睛”。你可以清晰地看到泄压曲线是否线性、脉搏波提取是否干净、振幅包络线是否光滑。
- 参数微调 :数字滤波器的截止频率、泄压速度、血压判定系数(K1, K2)都需要反复调整。最初可以使用一个模拟脉搏波发生器(用另一个单片机产生)作为输入信号进行闭环测试。
- 抗干扰测试 :在设备运行时,故意触碰线路、开关其他用电器,观察输出信号和最终结果是否稳定。这可以检验硬件布局布线和软件滤波算法的鲁棒性。
5.3 临床标定与误差分析
个人制作的设备必须经过严格的标定才能具有参考价值。标定需要一台经过认证的、准确的传统水银血压计或高精度电子血压计作为参考。
- 静态压力标定 :将袖带连接到一个密闭三通,一头接自己的压力传感器,另一头接一个高精度的数字压力表。给气囊打气,记录在不同压力点(如0, 50, 100, 150, 200 mmHg)下,自己设备的ADC读数。通过线性回归,得到ADC值与实际压力值的换算公式。这一步消除了传感器和放大电路的系统增益误差和零点误差。
- 动态比对测试 :邀请多位志愿者(最好涵盖不同血压区间),用参考血压计和自己的设备同时测量(分先后,间隔时间尽量短)。记录多组数据,计算自己设备测量值与参考值之间的平均误差和标准差。根据误差情况,回头调整算法中的判定系数。
- 误差来源分析 :
- 硬件误差 :传感器本身的非线性、温漂;运放电路的失调电压、噪声;电源纹波;PCB布局引入的干扰。
- 算法误差 :滤波参数不当导致特征点失真;泄压速度不均匀;幅度系数选择不适合所有人群。
- 操作误差 :袖带佩戴位置、松紧度不同。
重要提示 :自制血压计的测量结果 绝不能 作为临床诊断依据。其目的是学习嵌入式系统设计和信号处理技术。测量结果可能存在较大误差,尤其是对于血压异常(过高或过低)的情况,自制设备可能无法准确反映。
6. 项目进阶与扩展思考
完成基础功能后,这个项目还有很多可以深化和扩展的方向,让它从一个实验原型变得更像一款产品。
- 增加体温与血氧监测(可选) :可以集成MAX30102这类传感器模块,通过I2C接口与STM32连接,同时获取心率、血氧饱和度(SpO2)和用于计算血压的脉搏波信号(光电容积脉搏波PPG)。这需要融合两种信号进行算法上的创新。
- 数据存储与蓝牙传输 :增加SPI Flash或SD卡模块,用于存储历史测量数据。集成蓝牙模块(如HC-05或更专业的BLE芯片),将测量数据发送到手机APP,实现数据图表化、长期趋势分析等功能。这涉及到
STM32 HTTP库或MQTT等物联网协议的应用(如果通过Wi-Fi上传)。 - 低功耗设计 :如果考虑电池供电,需要选用低功耗的STM32L系列,并在软件上采用深度睡眠模式,仅在被按键或定时唤醒时工作。气泵和阀门的驱动电路也要考虑功耗。
- 用户界面优化 :使用彩色OLED或小型TFT屏,设计更友好的图形界面。增加语音播报功能,方便视力不佳的用户。
- 算法升级 :研究更先进的血压计算算法,如基于脉搏波传导时间(PTT)的模型,或引入机器学习模型对脉搏波特征进行学习,但这需要大量的临床数据作为训练集。
从一块空白的PCB到一台能显示数字的设备,整个过程充满了挑战,也收获了巨大的成就感。它强迫你去思考系统级的问题,从微小的模拟信号到宏观的软件状态机,从理想的原理图到充满妥协的PCB布局,每一个环节都紧密相连。最大的体会是,调试的时间往往远超开发时间,而一个清晰的调试手段(如串口数据可视化)能事半功倍。最后,请始终记住,电子制作关乎乐趣与学习,而健康测量关乎责任与安全。
更多推荐



所有评论(0)