简介:这份毕业设计文档面向电子信息、自动化等专业的本科毕业生,提供一套基于AT89S52单片机的数字心率计完整设计方案,可用于课程设计、毕设参考或嵌入式入门实践。资源包内仅含1个doc文件,约2.38MB,即整篇毕业论文正文,涵盖摘要、总体方案设计、元器件选型、硬件电路图、程序流程图及系统测试等章节。文中详细阐述了以AT89S52为核心,配合红外光电传感器OPT101采集人体信号,经OP07与LM324N双重放大电路提升信噪比,再由A/D转换器将模拟信号转为数字量,最终由四位数码管实时显示心率的完整链路,并采用主程序、信号采集、放大处理、显示等模块化软件结构。目前已有50人学习下载,适合需要低成本、高精度心率测量方案或想了解单片机信号采集与处理流程的读者参考借鉴。
1. 从光电脉搏波到四位数字:这套 AT89S52 心率计方案到底解决了什么
很多做过 51 单片机课程设计的人都有个共同体会:数码管动态扫描、按键消抖、串口收发这些模块单独调都能跑,一旦把模拟前端和单片机拼在一起,读数就开始乱跳。这套基于 AT89S52 的数字心率计设计,核心难点其实不在单片机本身,而在“怎么把手指尖那点微弱的半透明度变化,变成单片机外部中断能稳定识别的方波”。方案用 OPT101 红外光电传感器采集脉搏波,经 OP07 与 LM324N 两级放大、比较整形后送入单片机计数,最后用四位数码管显示心率值。它适合正在做单片机毕业设计、想搞懂模拟前端与数字处理如何衔接的读者,也适合已经会写 51 程序、但对传感器信号调理没底的人。整套设计成本低、器件常见,Proteus 能仿真大半,是典型的“麻雀虽小、五脏俱全”的嵌入式入门项目。
2. 脉搏波采集与双重放大电路的参数设计
2.1 为什么选红外光电法而不是压电法
设计里对比过两种采集方案:压电陶瓷片测手腕搏动,和红外光电测指尖半透明度。压电方案结构简单,但输出阻抗高、易受运动伪迹干扰,手指稍微一动基线就漂。红外光电法的物理基础是:心脏搏动时血液周期性充盈指尖组织,导致组织对红外光的吸收率变化,透射光强随之波动。这个波动频率与心率严格成正比,且信号在指尖、耳垂这类组织较薄处最明显。OPT101 把光敏二极管和跨阻放大器集成在一个封装里,片内反馈电阻 Rf=1MΩ,单电源 +2.7V 到 +36V 都能工作,省掉了分立光电二极管加运放的第一级设计,对课程设计来说能少调一个环节。
2.2 OPT101 输出到底有多弱
OPT101 在 650nm 处响应度约 0.45A/W,响应带宽 14kHz(Rf=1MΩ 时)。实际戴在手指上,透射光强的交流分量只有直流分量的百分之几,输出交流幅度通常在毫伏级。更麻烦的是,脉搏基频很低:50 次/分对应 0.78Hz,200 次/分对应 3.33Hz,属于典型的超低频弱信号。这意味着放大电路必须同时满足两个条件:足够高的增益,以及足够低的截止频率来抑制工频和日光灯闪烁干扰。
2.3 两级放大的增益分配与耦合电容取值
设计采用 OP07 做第一级、LM324N 做第二级的双重放大结构。OP07 的特点是输入失调电压低(最大 75μV 级别)、输入偏置电流小、噪声低,适合做前级;LM324N 是四运放,单电源 3V 到 32V 工作,共模范围包含负电源,适合做后级和比较整形。
第一级放大倍数由反馈网络决定,理论设计值约 200 倍。原文提到实际因 -5V 供电不足和器件限制,实测只有 20 倍左右——这是这类设计里非常真实的坑。耦合电容 C2、C3 取 10μF,目的是让 0.78Hz 的低频信号也能顺利通过,高通截止频率约为:
fc = 1 / (2 * π * R * C)若 R 取 10kΩ、C 取 10μF,fc ≈ 1.59Hz,刚好低于最低脉搏频率,不会把有用信号削掉。后级与 R7、C6 组成截止频率约 10Hz 的低通滤波器,进一步滤除残留高频干扰。这个“高通 1.6Hz + 低通 10Hz”的带通窗口,是脉搏信号调理的常见做法。
2.4 比较整形与单片机接口
放大后的正弦波经 C10、R14 微分形成尖脉冲,再由单稳态电路转成同频率的长脉冲,送到单片机外部中断引脚。AT89S52 用 12MHz 晶振,外部中断 0 检测脉冲下降沿,定时器 T0 做 1 秒闸门计数,T1 负责数码管动态扫描。这里有个设计细节值得注意:原文提到对心跳脉冲做了 100 倍频处理,配合 0.6 秒闸门,使计数值直接等于心率。比如心率 76 次/分,倍频后 127Hz,127×0.6=76.2,显示 76。这种“倍频+闸门”的换算方式,本质是用数字手段换取更短的测量时间,满足“5 秒内显示”的指标。
| 参数 | 取值 | 作用 |
|---|---|---|
| 晶振频率 | 12MHz | 定时器基准,机器周期 1μs |
| 第一级增益 | 理论 200 倍,实测约 20 倍 | OP07 前级放大 |
| 高通截止 | 约 1.6Hz | C2/C3=10μF 配合输入电阻 |
| 低通截止 | 约 10Hz | R7、C6 滤高频 |
| 闸门时间 | 0.6s | 配合 100 倍频直接读心率 |
提示:第一级增益远低于理论值时,先查运放供电是否对称。OP07 需要正负双电源,-5V 若由 7905 提供,注意 7905 的接地引脚不能悬空,否则负压建立不起来,增益会大幅缩水。
3. ADC0809 采样与 AT89S52 定时器中断的软件实现
3.1 ADC0809 在这套设计里的角色
ADC0809 是 8 通道、8 位逐次逼近型 A/D 转换器,DIP28 封装,转换时间约 100μs(时钟 640kHz 时)。设计里用它把放大整形后的模拟信号转成数字量送入单片机。需要说明的是,如果比较电路已经把信号整形成方波,理论上可以直接进外部中断计数,ADC0809 更多用于需要读取信号幅度的场合,比如判断信号是否有效、做阈值检测。接线要点:START 和 ALE 连在一起由 P2.0 控制,OE 接 P2.1,EOC 接 P2.2 查询或接中断,通道选择 A、B、C 接地选 IN0。
3.2 定时器 T0 做闸门、T1 做数码管扫描
AT89S52 有三个 16 位定时器,这里 T0 和 T1 分工明确。T0 工作在方式 1(16 位定时),初值计算:
// 12MHz 晶振,机器周期 1us // 定时 50ms,初值 = 65536 - 50000 = 15536 = 0x3CB0 TMOD = 0x11; // T0 方式1定时,T1 方式1定时 TH0 = 0x3C; TL0 = 0xB0; TH1 = 0xFC; // T1 用于数码管扫描,约 1ms 中断一次 TL1 = 0x18; ET0 = 1; ET1 = 1; EA = 1; TR0 = 1; TR1 = 1;T0 中断 20 次为 1 秒(或 12 次为 0.6 秒),在中断里累加计数脉冲;T1 中断里切换数码管位选并送段码。这种“一个定时器管时间基准、一个管显示刷新”的分工,是 51 单片机课程设计里最稳的写法,避免在主循环里用延时函数导致计数丢脉冲。
3.3 外部中断计数与防抖
脉搏脉冲从 INT0(P3.2)输入,配置为下降沿触发:
IT0 = 1; // 下降沿触发 EX0 = 1; // 开外部中断0中断服务程序里对 pulse_count 加一。实际调试时,比较器输出边沿可能因信号毛刺多次触发,常见做法是在中断里加一个短延时再确认电平,或者硬件上在比较器输出加 100nF 电容到地做简单滤波。软件防抖会占用中断时间,脉搏频率低(最高 3.33Hz),影响可以接受。
3.4 心率换算与显示刷新
计数值到心率值的换算取决于是否倍频。若未倍频,1 秒闸门计数值 N 对应心率 = N×60;若按原文 100 倍频、0.6 秒闸门,则显示值直接等于计数值。显示部分用四位共阳数码管,P0 口送段码(需上拉电阻,AT89S52 的 P0 是开漏),P2 口低四位做位选。动态扫描频率约 1kHz,人眼无闪烁。
void display(unsigned int hr) { unsigned char buf[4]; buf[0] = hr / 1000; // 千位 buf[1] = hr / 100 % 10; // 百位 buf[2] = hr / 10 % 10; // 十位 buf[3] = hr % 10; // 个位 // 位选和段码输出在 T1 中断中轮流进行 }注意:P0 口驱动数码管段码时必须接 10kΩ 上拉排阻,否则段码亮度极低甚至不亮。这是 51 单片机新手最常踩的坑之一。
4. 从 Proteus 仿真到整机联调的排错路径
4.1 分模块仿真验证顺序
不要一上来就整图仿真。合理顺序是:先单独仿真放大电路,用信号发生器给 1Hz、5mV 正弦波,看输出是否放大且无明显失真;再仿真比较电路,确认方波边沿干净;最后把单片机最小系统、ADC、数码管拼起来联调。Proteus 里 OPT101 没有现成模型,常用做法是用一个受控电流源加运放搭等效电路,或者直接用信号源替代传感器输出,先把数字部分跑通。
4.2 焊接与整机调试的典型问题
原文提到试验与焊接阶段分开进行,这是对的。焊接时先焊电源部分,上电测各路电压正常后再焊模拟前端,最后焊数字部分。整机调试常见问题有三类:一是数码管显示乱码,多半是段码表写错或位选接反;二是心率读数偏高且不稳定,通常是比较器阈值没调好,把噪声也计进去了;三是读数始终为零,检查 OPT101 输出是否被手指完全遮光导致饱和,或者外部中断引脚虚焊。
4.3 干扰来源与抑制手段
设计里明确提到几种主要干扰:工频 50Hz 干扰、日光灯闪烁、手指抖动。抑制手段包括:模拟部分用屏蔽线、电源加 100μF 和 0.1μF 去耦电容、比较器加迟滞(正反馈电阻)避免边沿抖动、软件上对连续两次测量值差异过大的数据做丢弃。迟滞比较器的正反馈电阻一般取反馈电阻的 1/100 到 1/10,太小不起作用,太大灵敏度下降。
| 故障现象 | 可能原因 | 排查动作 |
|---|---|---|
| 数码管全暗 | P0 无上拉、位选未使能 | 测 P0 电压、查位选三极管 |
| 读数偏高 | 比较器阈值过低、噪声计数 | 调阈值、加迟滞 |
| 读数跳动大 | 手指移动、电源纹波 | 固定手指、加去耦电容 |
| 无计数 | INT0 无脉冲、中断未开 | 示波器看 P3.2、查 EA/EX0 |
4.4 测量精度与响应时间的权衡
“5 秒内显示”和“读数稳定”本身有矛盾。闸门时间越长,计数越准,但响应越慢。原文用 100 倍频加 0.6 秒闸门,是在两者间取的折中。如果自己做,可以改成 1 秒闸门不倍频,读数更直观,代价是响应慢一点。对课程设计而言,能稳定显示且误差在 ±3 次/分以内,就算达标。
5. 用定时器 T1 中断做数码管动态扫描的进阶写法
很多 51 教程把数码管扫描放在主循环里用 delay 函数,一旦主循环里加了其他耗时操作,显示就闪。这套设计把扫描放进 T1 中断,是更工程化的做法。具体实现是:T1 每 1ms 中断一次,中断里关闭当前位、送下一位段码、开新位,四个位轮流,4ms 刷新一轮,刷新率 250Hz,远高于人眼闪烁阈值。
unsigned char code seg[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; unsigned char digit = 0; unsigned int hr_val = 0; void T1_ISR() interrupt 3 { TH1 = 0xFC; TL1 = 0x18; // 重装 1ms 初值 P2 = 0xFF; // 消隐,关闭所有位 switch(digit) { case 0: P0 = seg[hr_val/1000]; P2 = 0xFE; break; case 1: P0 = seg[hr_val/100%10]; P2 = 0xFD; break; case 2: P0 = seg[hr_val/10%10]; P2 = 0xFB; break; case 3: P0 = seg[hr_val%10]; P2 = 0xF7; break; } digit = (digit + 1) & 0x03; }这段代码的关键点有三个:一是每次切换前先P2 = 0xFF消隐,避免上一位的段码串到下一位造成“鬼影”;二是段码表按共阳接法编写,若用共阴数码管需取反;三是digit用位与运算循环,比 if-else 链更省周期。把显示和计数彻底解耦后,主循环只负责心率换算和报警判断,逻辑清晰很多。
验证方法也简单:把hr_val固定赋一个值如 1234,烧录后看四位是否稳定显示且无鬼影;再用信号发生器给 INT0 输入已知频率方波,比如 2Hz,1 秒闸门应显示 120,误差超过 ±2 就检查晶振和定时器初值。这套扫描写法稍作修改就能移植到 STC 或 STM32 的课程设计里,是 51 单片机显示模块里比较耐用的一个模板。
本文还有配套的精品资源,点击获取