news 2026/9/12 12:21:10

基于51单片机的脉搏血压体温测量仿真:信号调理与系统设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于51单片机的脉搏血压体温测量仿真:信号调理与系统设计

简介:这套基于51单片机的脉搏心率测量仿真设计,面向单片机初学者与电子设计竞赛备赛者,可用于课程设计或综合实训。资料包含完整C程序、Proteus仿真文件、原理图及HEX烧录文件,共23个文件,打包为7z格式,压缩包仅62KB,轻量易获取。硬件链路涵盖红外光电传感器脉冲采集、放大整形、单片机处理、按键上下限设置、蜂鸣器报警以及LCD1602显示,能直观呈现每分钟脉搏次数的测量与超限提示。目前已有超过1300人学习下载,说明该方案具备较高的参考价值。通过对照仿真与原理解读,读者可快速掌握模拟信号处理、定时/计数测频、显示驱动和报警逻辑,便于移植扩展到血压、体温等多参数检测设计中。

1. 基于51单片机的脉搏血压体温测量仿真:从需求拆解到文件交付

“基于51单片机的脉搏心率心跳血压体温测量检测仿真文件包含程序、仿真、原理图”这个标题在大学课程设计里出现频率极高,下载来的压缩包里通常有Keil工程、Proteus仿真和一张原理图,但三者的引脚分配经常对不上,LCD不显示,ADC乱跳。这类项目的本质不是算法多复杂,而是三条采集链路——红外对管脉搏检测、压力传感器血压检测、DS18B20体温检测——要把模拟信号调理、51单片机资源分配和仿真环境特性对齐。这篇文章按信号链顺序拆开讲硬件参数怎么整定、C51程序怎么组织、Proteus仿真里传感器模型怎么搭,最后落到原理图设计和实物排错,给出一套能完整跑通的最小实现。

2. 脉搏心率、血压、体温三条采集链路的硬件设计与参数整定

2.1 脉搏心率检测的PPG原理与比较器整形电路

光电容积脉搏波(PPG)的基本原理是:红外LED(通常选940nm或850nm)透射或反射手指组织,光电二极管接收透射光,指尖血管随心跳搏动改变血液容积,引起透射光强度变化,光电二极管输出的电流信号随之变化。这个信号有两个特征:一是直流分量很大,典型值在几伏级别,反映组织静态吸收;二是交流分量很小,只有直流分量的1%到5%,频率范围在0.5Hz到5Hz,对应30到300次/分钟的心率范围。所以信号调理的第一件事不是放大,而是隔直和滤波。

常见做法是一级隔直放大加一级比较器整形。前级运放接成同相交流放大,输入端串联1µF电解电容隔离直流分量,反相端接地电阻取10kΩ,反馈电阻取510kΩ,放大倍数约51倍。运放输出再接一个LM393比较器,比较门槛取放大后信号峰峰值的中间值,工程上直接把正输入端用两个10kΩ电阻分压到Vcc/2(2.5V),因为交流信号经过隔直后是围绕2.5V上下波动的。比较器输出接51单片机的INT0外部中断引脚,每一拍心跳产生一个下降沿中断,程序里计数即可。

这里有一个内置参数值得注意:正常成年人静息心率60到100bpm,对应信号周期600ms到1000ms,而PPG信号上升沿时间只有100ms左右。比较器如果设置成过零触发,抖动会非常大,一定要加滞回。LM393在正反馈环路里加一个1MΩ电阻,门槛从2.5V变成约2.4V和2.6V的滞回区间,抗噪效果明显好于无滞回。

链路传感器原始信号特征调理目标51单片机接口
脉搏心率红外对管+光电二极管mV级交流叠加几V直流隔直、放大51倍、滞回整形INT0外部中断
血压MPX5050GP或电位器模拟0.2~4.7V直流压力叠加mV级振荡分压入ADC、RC滤波去脉动ADC0809的IN0通道
体温DS18B20单总线数字信号4.7kΩ上拉、电平匹配P1.0普通IO口

2.2 血压测量的示波法与压力传感器信号链

血压测量在51单片机上做全自动示波法并不现实,因为气泵放气速率控制、脉动包络搜索和收缩压/舒张压判定都需要一定运算量。课程设计里最常用的替代方案是:压力传感器用MPX5050GP(0~50kPa,对应0.2V到4.7V输出),气泵用继电器控制,放气过程简化为定时器均匀放气,ADC以每秒50次的速率采集压力值。仿真阶段则用两个电位器分别模拟袖带直流压力和交流振荡幅度,一个按键切换显示收缩压还是舒张压,程序按简化示波法做包络峰值搜索。

示波法的处理逻辑可以简化成这样的链路:袖带放气过程中每个心动周期产生一个动脉振荡波,这些波的幅度先增后减,形成类似钟形的包络。峰值位置对应平均压,峰值前包络上升到最大幅度的70%处对应收缩压,峰值后包络衰减到最大幅度的55%处对应舒张压。51单片机内存有限,常见做法是采样128个点存入数组,放气结束后离线搜索包络峰值,这样比实时判断可靠得多。

压力信号进ADC之前要加一级RC低通滤波,截止频率设在10Hz,既能保留脉搏振荡波和压力变化趋势,又能滤掉继电器切换时的毛刺。R取10kΩ,C取1.5µF,算下来约10.6Hz,仿真里直接用MULTIMETER观察滤波后的电压是否平稳。

2.3 DS18B20单总线体温测量与上拉电阻配置

DS18B20测温范围-55°C到+125°C,12位分辨率下精度0.0625°C,完全覆盖人体测温需求。单总线通信最重要的一条规则:数据线必须接上拉电阻,典型值4.7kΩ,允许范围2.2kΩ到10kΩ。上拉太小,总线高电平驱动能力变弱;上拉太大,时序边沿变缓,高速模式容易出错。52单片机端口本身有内部上拉,但驱动DS18B20这种开漏总线器件,外部4.7kΩ更稳。

供电方式上,寄生供电和外部供电选后者。寄生供电需要数据线在高电平期间给内部电容充电,测量转换期间MCU必须把总线拉高以提供能量,如果代码时序处理不当,转换结果会读到85°C这个错误值。外部供电则把VDD接3.3V或5V,数据线只负责通信,转换期间无需额外维持电流。Proteus仿真里DS18B20元件默认支持外部供电模型,直接接VCC即可。

51单片机访问DS18B20没有硬件单总线控制器,时序全靠延时函数。12MHz晶振下执行一条普通指令约1µs,复位脉冲要求480µs以上,用两层嵌套循环实现;读时序要求总线拉低6µs后采样,写0时序要求总线拉低后继续保持60µs。这个时序窗口比较宽松,用_nop_()和简单的空循环就能满足。

/* 引脚分配与系统参数(STC89C52RC,12MHz晶振) */ sbit Pulse_In = P3^2; /* 脉搏整形输出接INT0外部中断 */ sbit DQ = P1^0; /* DS18B20数据线 */ #define VREF 5.0f /* ADC参考电压 */ #define ADC_CH_PRESS 0 /* 血压压力模拟通道接ADC0809 IN0 */ #define SAMPLE_N 128 /* 血压包络采样点数 */

这段代码把三条链路的引脚资源一次性锁死:P3.2是INT0外部中断,专门等脉搏跳变沿;P1.0给DS18B20;ADC0809数据总线占用P0口;P3.6和P3.7分别控制气泵继电器和显示切换按键。引脚分配到这一步就不要再改,否则后面Proteus仿真图和原理图全部要跟着动。血压通道之所以接ADC0809的IN0,是因为ADC0809的地址译码A、B、C全接地时默认选中IN0,少两根地址线少两处出错的可能。

3. C51程序实现:定时器中断、ADC采样与心率算法落地

3.1 定时器0做10ms时基,定时器1数脉搏脉冲

心率测量有两种思路:一种是把脉搏整形信号送定时器1外部计数引脚,定时器0做秒时基,1秒后读计数值再乘以60;另一种是测量两次脉搏跳变的时间间隔再换算。第一种适合信号质量一般、偶发漏检的情况,时间窗口内计数天然有平均效果。第二种读数快但受单次抖动影响大,剧烈运动时误差会到±10bpm。课程设计里建议用第一种,代码简单且抗抖动。

定时器1工作在计数模式,外部脉冲从P3.5引脚进入;定时器0工作在16位定时模式,每10ms溢出一次。定时器0中断里累加100次就是1秒,每秒读取定时器1的计数值差值,心率等于差值乘以60。TMOD设置成0x51:高四位是定时器1的计数模式,低四位是定时器0的定时模式,都是方式1的16位计数。

/* 定时器0中断函数:每10ms进一次,累计1秒读取脉搏计数 */ void Timer0_Isr() interrupt 1 { static unsigned int ms10 = 0; static unsigned int last_cnt = 0; unsigned int cur_cnt; TH0 = 0xD8; /* 65536-10000=55536 (0xD8F0) */ TL0 = 0xF0; if (++ms10 >= 100) /* 满100次=1秒 */ { ms10 = 0; TR1 = 0; /* 停T1,避免读取时计数跳变 */ cur_cnt = (TH1 << 8) | TL1; // 心率 = (本次计数值-上次计数值) * 60 heart_rate = (unsigned int)(cur_cnt - last_cnt) * 60; last_cnt = cur_cnt; TH1 = 0; /* T1清0,重新开始下一秒计数 */ TL1 = 0; TR1 = 1; } }

这段逻辑的关键在于读取计数前先停掉定时器1,否则TH1和TL1可能处于进位过程中,高低字节组合出错。心率的计算结果是次/分钟,正常范围60到100,小于30或大于220基本可以判定为信号异常,显示“----”而不是一个错误数字。需要说明的是,脉搏信号每次心跳只有一个下降沿,所以计数差值本身等于心跳次数,乘以60就是bpm。如果后续想提高刷新率,可以把时间窗口缩到5秒再乘12,代价是显示跳动更频繁,两种做法对应不同场景取舍。

3.2 DS18B20温度读取的时序实现

DS18B20的读写完全依赖主机控制总线时序,三个核心动作分别是复位脉冲、写一个字节、读一个字节。复位时主机拉低总线480µs到960µs,然后释放并读取从机应答脉冲;写1时序是拉低总线1µs到15µs后释放,写0时序是拉低总线60µs到120µs;读时序是拉低总线1µs后释放,在第15µs内完成采样。

/* 读取DS18B20温度,单位0.0625°C */ unsigned int ds18b20_read_temp_raw(void) { unsigned char low_byte, high_byte; unsigned int temp_raw; ds18b20_reset(); /* 复位总线 */ DQ = 1; _nop_(); DQ = 0; /* 写跳过ROM命令 0xCC */ write_byte(0xCC); write_byte(0x44); /* 启动温度转换 */ while (!DQ); /* 等待转换完成,DQ拉高表示完成 */ ds18b20_reset(); write_byte(0xCC); write_byte(0xBE); /* 读暂存器 */ low_byte = read_byte(); high_byte = read_byte(); temp_raw = (unsigned int)((high_byte << 8) | low_byte); return temp_raw; }

转换等待这段最好加超时保护:DS18B20在12位分辨率下转换时间最长750ms,如果单总线没接好,while(!DQ)会死循环。常见的做法是加一个计数器,超过20000次循环就返回0xFFFF表示读取失败。返回值是高8位和低8位的组合,低4位是小数部分,符号位在高字节的第5位,体温场景基本都是正数,直接乘以0.0625得到实际温度值即可。

3.3 血压包络提取的简化算法

仿真里血压信号的来源是两个电位器:一个调节直流偏置模拟袖带压力,一个调节交流幅值模拟脉动振荡。ADC0809以每秒50次的采样率连续采集128个点存入数组,放气过程结束后统一处理。实际算法分三步走:第一步计算基线,取数组前10个点的平均值作为基准;第二步计算每个点相对基线的偏差绝对值,得到振荡幅值序列;第三步搜索幅值序列的峰值和峰位,按收缩压70%、舒张压55%的比例映射到压力值。

/* 简化示波法包络搜索:env[]为振荡幅值数组,press[]为同步压力值 */ unsigned char i, peak_index = 0; unsigned int max_env = 0; for (i = 0; i < SAMPLE_N; i++) { if (env[i] > max_env) { max_env = env[i]; peak_index = i; } } /* 收缩压:峰前第一个幅值超过70% max_env的点对应压力 */ /* 舒张压:峰后第一个幅值衰减到55% max_env的点对应压力 */

这段代码的工程性改良点是加平滑:直接对env数组求差分会把单点毛刺放大,算峰值前先做三邻域平均,再搜索时用滞回比较,小于阈值连续5个点才确认越过阈值。仿真阶段就算不做平滑也能出数,但移植到真实传感器上会频繁误判,所以保留平均这一步更稳妥。另外,128个采样点对应放气持续时间约2.56秒,这个时长在仿真里没问题,真实袖带放气通常要8到15秒,采样周期要改成每点50ms才能覆盖完整放气过程。

4. Proteus仿真文件搭建:元件清单、传感器模型与联合调试

4.1 仿真整体结构与元件清单

Proteus仿真要把51单片机、模拟前端和显示外设放在同一张图里,元件清单按功能划分成四块:MCU及最小系统、模拟信号链、显示交互、电源和调试辅助。

元件型号数量作用
单片机AT89C511主控,程序中替换为STC89C52RC同管脚
运放LM3581脉搏信号一级交流放大
比较器LM3931脉搏信号整形,输出方波
数据采集ADC08091血压压力模拟量转数字量
温度传感器DS18B201单总线测温
液晶屏LM016L12行16列显示心率、体温
电位器POT-HG2模拟血压直流压力和振荡幅度
脉冲源PULSE1模拟PPG脉搏信号
去耦电容10µF+0.1µF若干每芯片电源引脚各配

单片机晶振放12MHz,电容22pF;复位电路用10µF电解电容加10kΩ电阻,上电自动复位。LCD的V0引脚串一个5kΩ电位器到GND调对比度,仿真里不调会白屏,这是最多人遇到的问题。ADC0809的CLK引脚务必接一个时钟源,可以直接用单片机的ALE引脚,也可以加一个PULSE信号源设成500kHz,不接时钟ADC永远输出0xFF或不变。

4.2 用PULSE信号源模拟PPG脉搏波形

真实PPG信号是带直流偏置的不规则脉动波,Proteus里最接近的模拟方式是PULSE信号源叠加直流偏置。设置方法:初始低电平0V,高电平1V,脉冲宽度0.1秒,周期0.8秒(对应75bpm),相位延迟0。输出端接一个1µF电容隔直,再送入LM358放大,效果和无信号源时的直流偏置完全区分开。

仿真时务必在脉搏信号源和放大器之间留一个测试点,用虚拟示波器分别观察传感器源点、运放输出和比较器输出三个位置。源点应该是0V到1V的脉冲方波;运放输出是被放大后的双向波形(隔直后负半周朝下),比较器输出是规则的0V/5V方波,方波频率就是心率。如果比较器输出一直高电平或者一直低电平,说明门槛电压没落在信号幅度范围内,调一下分压电阻比例就行。这个三步观察法对模拟信号链路的排错价值最大,它能直接定位问题出在前级放大、比较器门槛还是后级计数逻辑。

4.3 Keil5生成HEX文件与工程参数对齐

Keil5里新建工程时选芯片型号要严格对应Proteus里的型号,AT89C51和STC89C52RC管教兼容,但RAM和Flash大小不同,编译出来的HEX可能包含Proteus仿真的AT89C51不支持的地址段。稳妥的做法是Keil里选Atmel AT89C51,仿真用AT89C51,原理图用STC89C52RC,实机烧录时重新选择STC型号编译一次,因为这两者的头文件寄存器定义是一样的,代码层面完全兼容。

编译设置里打开Output选项卡勾选Create HEX File,然后在Proteus里双击单片机,Program File路径指向生成的HEX文件。调试顺序是:先调LCD,能显示字符后再调DS18B20温度,固定温度正确后再加脉搏仿真信号源,最后再接ADC0809和电位器做血压模拟。把每一步分开验证的好处是出问题能缩小范围,一体化调试一旦不显示就先乱成一锅粥。

5. 原理图模块化设计与仿真到实物的排错技巧

5.1 原理图模块化布局与去耦参数

原理图在AD或立创EDA里绘制时,按供电入口、51单片机最小系统、脉搏信号调理、血压采集、DS18B20、显示和外设六个模块分块摆放。每一块用一个矩形边框圈起来并标注功能,评审老师和后期调试都容易进入状态。电源去耦按“每芯片一组”的规则:每个芯片的VCC引脚放一个0.1µF陶瓷电容,就近接地;板级电源入口放一个10µF到100µF电解电容。

三个设计习惯直接影响实物稳定性。第一,ADC0809和运放的模拟地与数字地分开走线,在电源入口处单点连接;第二,脉搏放大器输入端走线远离继电器驱动线和气泵电机线,避免50Hz工频干扰从寄生电容耦合进来;第三,DS18B20的数据线不要铺地铜皮,单总线器件的寄生电容过大会拉慢上升沿,导致时序不稳。

5.2 仿真正常但实物不工作的四步排查法

实物和仿真最大的差异是电源质量、传感器偏置和参考电压,按顺序排查能把问题压缩到最小范围。

排查步骤检查点操作方法
1电源纹波示波器AC档测5V,观察有无高频毛刺
2运放偏置点万用表测LM358输出,静态应在1.5V到3.5V
3单总线波形示波器测DQ引脚,复位和应答脉冲是否完整
4ADC时钟确认ADC0809的CLK引脚有脉冲输入

第四步最容易被忽略但影响最严重:ADC0809的CLK引脚内部没有时钟源,必须外部提供10kHz到1MHz的方波,否则ADC转换结果直接不可用。仿真里如果忘了接CLK,结果还能勉强看到几个数在跳,实物的表现是ADC值固定不变或者全部为0。合规的接法是从ALE引脚引信号经过分频后接CLK,或者直接用一个定时器中断翻转IO引脚产生方波。

如果实物测量时心率值比正常高出一倍,多半是LM393比较器输出沿抖动导致外部中断重复触发,给P3.2引脚加一个10kΩ下拉电阻并开启INT0的中断标志位清空逻辑能缓解大半。这些都确认无误后,再把放气过程加长到10秒以上,用串口把压力数组打出来,画成折线图核对包络形态是否符合预期。仿真文件、程序和原理图三者的引脚关系保持一致,整套流程才算闭环。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 12:20:49

阳台自动浇水装置设计与实现全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 12:19:48

Kronos 股票预测:教AI读懂K线,400根历史进,120根未来出

Kronos 股票预测&#xff1a;教AI读懂K线&#xff0c;400根历史进&#xff0c;120根未来出 【免费下载链接】Kronos Kronos: A Foundation Model for the Language of Financial Markets 项目地址: https://gitcode.com/GitHub_Trending/kronos14/Kronos Kronos 是第一个…

作者头像 李华
网站建设 2026/9/12 12:19:16

网页视频下载:猫抓 3 步把视频存到本地

网页视频下载&#xff1a;猫抓 3 步把视频存到本地 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 课程视频一到期就打不开&#xff0c;直播回放点…

作者头像 李华
网站建设 2026/9/12 12:17:04

STM32F10x三轴云台PWM同步驱动:RCC时钟树与TIM高级定时器实战

简介&#xff1a;本资源是一个面向嵌入式开发初学者与STM32进阶实践者的三轴云台控制系统Keil工程源码包&#xff0c;聚焦于俯仰&#xff08;Pitch&#xff09;、翻滚&#xff08;Roll&#xff09;、偏航&#xff08;Yaw&#xff09;三自由度姿态稳定与电机协同控制&#xff0c…

作者头像 李华
网站建设 2026/9/12 12:16:58

SpringBoot古文学习系统开发实战与优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华