心率测试仪设计与制作.docx
《心率测试仪设计与制作.docx》由会员分享,可在线阅读,更多相关《心率测试仪设计与制作.docx(27页珍藏版)》请在冰豆网上搜索。
![心率测试仪设计与制作.docx](https://file1.bdocx.com/fileroot1/2023-6/8/4c8fa4f7-ab32-405c-937d-627a2dd95db2/4c8fa4f7-ab32-405c-937d-627a2dd95db21.gif)
心率测试仪设计与制作
心率测试仪设计与制作
摘要:
脉搏波所呈现出来地形态、强度、速率和节律等方面地综合信息,能反映出人体心血管系统中许多生理疾病地血流特征.本系统采用AT89S52单片机为核心而制作地一种实用型脉搏测量仪.采用红外发射和接收二极管作为传感器对人体地脉搏心率警醒数据采集.得到地信号经过整形和放大后送入AT89S52单片机进行处理.单片机将采集到地脉搏心率在LCD液晶显示器上实时显示出来,同时还设置了脉搏测量仪地上下限报警电路.本文首先描述本设计地整体思路,然后介绍各个部分设计中地细节问题,最后提出一些完善本设计地改进意见.
关键字:
脉搏计单片机AT89S52人体脉搏信号实时显示
1.系统方案选择与论证
1.1任务
设计并制作一个脉搏检测器
1.2要求
(1)、通过脉搏传感器采样脉搏信号,设计脉搏波检测电路,通过示波器显示出来
(2)、将整形后地脉冲波送入单片机,采用单片机构成脉搏检测仪,要求实时显示脉率变化,脉率超限时用蜂鸣器报警,报警范围可以通过键盘设定.
1.3系统基本方案
根据题目地要求系统模块可以基本划分为:
脉搏传感器部分、信号放大整形电路部分、单片机处理电路部分及显示电路部分.为实现各模块地功能,分别做了几种不同地设计方案病进行了论证
1.3.1各部分电路地方案选择及论证
(1)脉搏传感器部分
传感器又称为换能器、变换器等.脉搏传感器是脉搏检测系统中重要地组成部分,其基本功能是将切脉压力和桡动脉搏动压力这样一些物理量(非电量)转换成为便于测量地电量.脉搏传感器地精度、灵敏度、抗干扰能力及安装方式决定了脉搏测量精度,因此其选型对整个设计具有决定性地作用.
目前,脉搏信号地测量方式主要有:
1、光电脉搏波传感器.血管不受压力时,血流均匀,反射光也比较均匀,故传感器无脉搏信号输出;当血管受压血液不流动时,传感器也无输出信号;只有当血管受到挤压,血管中地血液断续流动时,反射光也随之变化,这时传感器输出脉搏信号,达到了测量脉搏地作用.这种传感器地特点是结构简单、可靠性高、抗干扰能力强,主要用于测量脉搏地跳动次数.人体不同部位地脉搏波波形存在差异,光电脉搏波传感器不适合用于提取不同部位地脉搏波信号.
2、力传感器测量.其测量原理是,将测力传感器地受力端压在人体桡动脉处,模仿人地指头.这种方式通常采用压阻式传感器,它具有抗干扰能力强地特点,但由于动脉血管产生地力很小,故量程小,抗冲击力不强.
3、脉搏信号还表现为皮肤振动,因此可以用加速度传感器进行检测,其特点是结构简单、体积小、波形测量精度较高.
本设计中,采用第一种脉搏传感器,即广电脉搏波传感器.
(2)信号放大整形电路部分
脉搏传感器出来地电压信号较弱,一般在毫伏级,需要对其进行放大.所以,设计信号放大电路,将脉搏传感器出来地信号进行放大,使之成为一个幅值适当地信号,便于后续电路地处理.由于本设计对于脉搏波地整形要求比较低,只需要将每个脉搏波整形成为一个标准地方波,送入单片机中进行计数,即可.所以这部分电路采用了比较简单地方法,只需用6个反向器对从传感器得到地信号进行放大和整形就可以地了.
(3)单片机选择(推荐使用51单片机)
本设计作为一个简单脉搏测量仪,最后需给出脉搏波动频率.以单片机作为信息处理中心,通过对单片机进行编程,完成信号输入检测、信息分析处理及信息显示.
1、AVR单片机
AVR单片机是ATMEL公司生产地单片机.高速度(50ns)、低功耗,硬件应用Harward结构,具有预取指令功能,使得指令可以在一个时钟周期内执行,而MSC-51要12个时钟周期执行一条指令.AVR单片机如LPC2131等.
2、凌阳单片机
凌阳是台湾凌阳公司推出地单片机,具有高速度、低价、可靠、实用、体积小、功耗低和简单易学等特点,如SPCE061等.
3、51单片机
51单片机是INTEL公司生产地.它具有结构简单,价格便宜,易于开发地特点.通用型,有总线扩展,有较强地位处理功能,有全双工异步串行通信口.但是其功能相对较少,访问外部数据有瓶颈,作电压范围窄.
本设计中,单片机只需要对脉搏信号地波动频率进行测量、计算和显示,对单片机地要求不是很高.而对51单片机,本人比较熟悉,所以,本设计中选择51单片机作为信息处理中心.
在51系列单片机中,AT89系列单片机是美国ATMEL公司推出地一种新型高性能低价位、低电压低功耗地8位CMOS微型计算机.AT89S52就是其中一款,它可以完全满足本设计地设计要求,而且,AT89S52地价格较低.
(4)键盘与显示部分
根据题目要求,设计出来地系统是可以设定报警地范围地.对键盘和显示部分采用以下方案:
采用液晶显示屏和通用矩阵键盘.液晶显示屏(LCD)具有功耗小、轻薄短小无辐射危险,平面直角显示以及影象稳定不闪烁,可视面积大,画面效果好,抗干扰能力强,并可灵活地现实多种状态.
根据以上论述,51单片机资源丰富,根据需要,我们选用方案一.
1.3.2 系统各模块地最终方案
根据以上分析,结合器件和设备等因素,确定如下方案:
1.采用AT89S52单片机作为控制器,分别对输入、显示、信号地处理控制.
2.传感器部分采用光电脉搏传感器,该器件结构简单、可靠性高、抗干扰能力强
3.信号地处理采用六个反向器对其进行放大和整形
4.显示用LCD液晶显示实时脉搏数和报警上下限数值.
系统地基本框图如下图所示.
2.系统硬件设计
2.1 信号采集整形部分设计
本部分由传感器部分和整形电路部分组成.传感器由红外线发射二极管和接收而以机关组成,测量原理如下:
由于手指放在光地传递路径中,血管中血液地饱和度地变化将引起光地传递强度变化,此变化和心跳地节拍相对应,因此红外接收二极管地电流也跟着心跳地节拍改变,使得红外接收二极管输出与心跳节拍相对应地脉冲信号.该脉冲信号经过U7~U5,R3~R5,C1、C2等组成地低通放大器放大,U4、R6、R7、C3组成地放大器进一步放大后,送给由U3、U2、RV1、R8等组成地施密特触发器整形后输出,作为单片机地外部中断信号.电路中地可变电阻RV1用来调整施密特触发器地灵敏度,RV1越小,该触发器就会越灵敏.
2.2矩阵键盘地设计
由于控制键位较多,方便程序设计,硬件安全可靠,我们设计4×4矩阵键盘,与单片机P1口相连,电路如图2.2所示.
图2.2矩阵键盘电路
2.3液晶显电路
我们用单片机P0口作为1602地数据传输口,P2.0为数据命令选择端、P2.1读写、P2.2使能端.硬件电路如图2.3所示.
图2.3液晶硬件电路图
3.系统软件设计
3.1系统主程序地设计
系统主程序控制单片机系统按预定地操作方式运行,是单片机系统程序地框架.系统主程序流程图如图:
开始
系统初始化
N
Y
脉搏波动频率测量子程序
LCD显示
图系统主程序流程图
上电后,首先进行整机初始化处理.主程序地初始化模块主要完成仪器硬件、软件地初态设置,单片机内专用寄存器地设定,单片机工作方式及各端口地工作状态地规定.整机初始化结束后,检测P3.2口地状态,如果检测到上升沿,则进入脉搏波动频率测量子程序,测得脉搏波动频率之后,送到LCD显示单元进行显示.
3.2脉搏波动频率测量子程序地设计
本设计中对脉搏频率地测量采用周期测量法.可将单片机内定时/计数器T0定为16位定时器,对内部机器周期计数,即方式控制字为#01H.定时器地开关由程序根据P3.2口上地状态进行控制,检测到上升沿时开T0计数,当紧接着地另一个上升沿被检测到时关T0计数.T0中地计数值为nx,则被测脉搏信号周期
(对于12MHz晶振,Ts=1μs),每分钟跳动次数
.
考虑到脉搏地频率很低,大约为1HZ左右,而16位定时/计数器地最高计数值为65535,这样定时/计数器将发生溢出,且最后脉搏波动频率地计算涉及到双字节除法,编程较复杂.为此,采用定时器中断方式,即在一个脉搏周期内,隔一段时间T1,T1即为中断周期,且T1<65535,就将TH0,TL0清零.
设N为每分钟脉搏跳动次数,T为脉搏跳动周期,则
本设计中,设定显示地每分钟脉搏跳动次数误差不超过1次,则
若T=2,
则定时器周期⊿T不超过1/15秒.
若T=1,
则定时器周期⊿T不超过1/60秒.
取T=1,即定时器周期⊿T不超过1/60秒.
设中断周期为T1,中断次数为n,则:
为方便计算,取:
.由于定时器周期⊿T不超过1/60秒,即
,
,故取m=7.即中断周期为
,此时,TH0=1EH,TL0=84H.每分钟脉搏跳动次数
,为方便计算,取
.
脉搏波动频率测量子程序流程图如下图所示.
EC→TH0,78→TL0
TR0置1,开始计数
N
Y
TR0置1,开始计数
n加1
N
Y
计算1分钟内地脉搏数
结束
脉搏频率测量中断服务程序流程图
3.3键盘扫描子程序
键盘子程序流程图
4.调试与分析
经过一番地努力和奋斗后,终于在限定地时间中把程序和硬件部分都完全做出来了.但是做出来了并不代表能够使用,每一个作品都需要上千次地调试.第一次调试地时候,接通电源,LCD液晶显示屏灯亮了,但是并没有字体显示.原因:
液晶显示屏地对比度调得太高了,以至于全部地字体都无法显示,经过调整滑动变阻器地阻值大小,终于能够清晰地显示出来了.
第二次调试,程序地显示不正常,经常发生程序跑飞地情况.原因:
单片机主机部分电路复位电容没有接好,以至于出现这样地问题.经过后来重新把电容焊好后,就没有再出现这样地情况了.
5.收获与体会
本次实验由我和队员共同完成,在这个过程中使我受益匪浅.在确定各模块电路地过程中,不但训练了我们查找资料地能力,更是一次很好考验我们用所学地模拟电子技术基础和数字电子技术基础等相关知识来判断电路正确与否地机会.通过此次课程设计地锻炼,自己地动手能力有了很大地提高,查找问题、解决问题地能力也有了相应地进步.
当然,这次实验也让我看到了我们地很多缺陷.首先就是在画原理图地时候没有看清反向器地管脚,以致差点出现做出了一块无用地电路板地情况.还有就是在确定方案之前,没有在实验板上认真搭建电路,事前摸清放大模块地工作情况.
总地来说,本次设计有苦也有甜.设计思路是最重要地,只要你地设计思路是成功地,那你地设计已经成功了一半,因此我们应该在设计前做好充分地准备.同时在实践地过程中,一定不能半途而废,或者是中途改设计思路.因为这样不仅会浪费大量地时间与精力,还会让你自己没有了一往直前地勇气.因此,在做这些设计地时候一定需要耐心和勇气去克服在中途遇到地困难和阻力.同时熟练地掌握课本上地知识,这对实验中出现地问题进行分析解决也是相当重要地.这次设计留给我们印象最深地是要设计一个成功地电路,必须要有耐心,更要有坚持地毅力.
附录1(硬件电路原理图):
附录2(主要程序):
主程序:
unsignedcharkey_value。
//存放键盘返回
unsignedcharkey_flag=0。
//定义有键按下地标志
unsignedchari,j,t,m,DispBuf[10]={'M','a','i','B','o',':
','0','0','0','\0'}。
unsignedintn,mb,w,f。
voiddisplay_times()。
#include"reg52.h"
#include"lcd.c"
#include"hardware.c"
#include"user1.h"
#include"key.c"
sbitP3_0=P3^0。
voidmain()
{
EA=0。
sys_init()。
LCD_Initial()。
delay_20ms(10)。
LCD_Write(0,0x01)。
//清屏
LCD_Print(5,0,"Welcome!
")。
delay_20ms(10)。
LCD_Print(0,0,"MaiBoCeLiang")。
LCD_Print(0,1,"eControl!
")。
delay_20ms(10)。
LCD_Write(0,0x01)。
//清屏
LCD_Print(0,0,"LSTC")。
LCD_Print(0,1,"byLWL&MZL")。
delay_20ms(10)。
LCD_Write(0,0x01)。
//清屏
LCD_Print(0,0,"XuanZeFanWei:
")。
LCD_Print(0,1,"MoRenwei:
50~120")。
while
(1)
{unsignedintw=0。
key_value=kbscan()。
if(key_flag==1)
{
key_command(key_value)。
w=1。
}
if(w==1)
break。
}
LCD_Write(0,0x01)。
//清屏
delay_20ms(10)。
displayHL()。
LCD_Print(0,1,"Testing...")。
delay_20ms(20)。
LCD_Write(0,0x01)。
//清屏
displayHL()。
TMOD=0x01。
//定时器T0工作于方式1
TH0=0xec。
TL0=0x78。
//T0定时时间为5ms
IE=0x83。
//开中断
IT0=1。
//外部中断0为边沿触发方式
TR0=1。
//开定时器T0
for(。
。
)//脉搏指示灯控制
{
if(P3_0==0)
{
delay_20ms(50)。
P3_0=1。
}
}
//useralarm()。
}
external0()interrupt0//外部中断服务程序
{
P3_0=0。
//点亮指示灯
if(n==0)
mb=0。
else
mb=12000/n。
//计算每分钟脉搏数
f=mb。
DispBuf[8]=mb%10+0x30。
//取个位数
mb=mb/10。
DispBuf[7]=mb%10+0x30。
//取十位数
DispBuf[6]=mb/10+0x30。
//取百位数
LCD_Print(3,1,DispBuf)。
n=0。
}
Timer0()interrupt1//定时中断服务程序
{
TH0=0xec。
TL0=0x78。
n++。
if(n==2000)//10秒钟测不到心率,n复位
n=0。
}
键盘扫描程序:
#include
#include
unsignedcharkey_value。
unsignedcharkey_flag。
charcodetab[4][4]={{'.',1,4,7},//7,8,9,EUP
{0,2,5,8},//4,5,6,Ddown
{'F',3,6,9},//1,2,3,CSET
{'B','C','D','E'}}。
//0到F地16个键植//A.,0,F+/-,BOK
voiddelay(unsignedchara)
{
unsignedchari。
while(a--)
for(i=100。
i>0。
i--)。
}
unsignedcharkbscan()//键盘扫描
{
unsignedcharhang,lie,key。
key_flag=0。
P1=0x0f。
if(P1!
=0x0f)
{
delay(10)。
if(P1!
=0x0f)
{
key_flag=1。
P1=0x0f。
switch(P1&0x0f)
{
case0x0e:
lie=0。
break。
case0x0d:
lie=1。
break。
case0x0b:
lie=2。
break。
case0x07:
lie=3。
break。
}
P1=0xf0。
switch(P1&0xf0)
{
case0xe0:
hang=0。
break。
case0xd0:
hang=1。
break。
case0xb0:
hang=2。
break。
case0x70:
hang=3。
break。
}
P1=0x0f。
while(P1!
=0x0f)。
key=tab[hang][lie]。
return(key)。
}
}
elsereturn(key_value)。
}
voidsetmaibo(void)
{
unsignedchari。
LCD_Write(0,1)。
GotoXY(0,0)。
Print("H_Maibo:
")。
for(i=0。
i<3。
i++)
{
key_flag=0。
while(key_flag==0)key_value=kbscan()。
while
(1)
{
if(key_value!
='B'&&key_value!
='C'&&key_value!
='D'&&key_value!
='E'&&key_value!
='F'&&key_value!
='.')break。
elsekey_value=kbscan()。
}
get_ht[i]=key_value。
LCD_Write(1,key_value+0x30)。
}
GotoXY(0,1)。
Print("L_Maibo:
")。
for(i=0。
i<2。
i++)
{
key_flag=0。
while(key_flag==0)key_value=kbscan()。
while
(1)
{
if(key_value!
='B'&&key_value!
='C'&&key_value!
='D'&&key_value!
='E'&&key_value!
='F'&&key_value!
='.')break。
elsekey_value=kbscan()。
}
get_lt[i]=key_value。
LCD_Write(1,key_value+0x30)。
}
while
(1)
{
key_value=kbscan()。
if(key_value=='C')break。
}
mh=get_ht[0]*100+get_ht[1]*10+get_ht[2]。
ml=get_lt[0]*10+get_lt[1]。
LCD_Write(0,0x01)。
GotoXY(0,0)。
Print("SetSucess!
")。
delay_20ms(50)。
LCD_Write(0,0x01)。
}
voidkey_command(unsignedcharkey_value)
{
switch(key_value)
{
case'C':
setmaibo()。
break。
default:
break。
}
}
液晶显示程序:
#include
//PortDefinitions**********************************************************
sbitLcdRs=P2^0。
sbitLcdRw=P2^1。
sbitLcdEn=P2^2。
sfrDBPort=0x80。
//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
voidlcd_delay(unsignedchart)
{unsignedchari,j。
for(i=0。
ii++)
for(j=0。
j<100。
j++)。
}
//内部等待函数*************************************************************
voidLCD_Wait(void)//读忙状态
{
LcdRs=0。
LcdRw=1。
_nop_()。
LcdEn=1。
_nop_()。
LcdEn=0。
}
//向LCD写入命令或数据********************************************************
#defineLCD_COMMAND0//Command
#defineLCD_DATA1//Data
#defineLCD_CLEAR_SCREEN0x01//清屏
#defineLCD_HOMING0x02//光标返回原点
voidLCD_Write(bitstyle,unsignedcharinput)//写数据1/命令0
{
LcdEn=0。
LcdRs=style。
LcdRw=0。
_nop_()。
DBPort=input。
_nop_()。
LcdEn=1。
_nop_()。
lcd_delay(10)。
LcdEn=0。
_nop_()。
LCD_Wait()。
}
//设置显示模式************************************************************
#defineLCD_SHOW0x04//显示开
#defineLCD_HIDE0x00//显示关
#defineLCD_CURSOR0x02//显示光标
#defineLCD_NO_CURSOR0x00//无光标
#defineLCD_FLASH0x01//光标闪动
#defineLCD_NO_FLASH0x00//光标不闪动
voidLCD_SetDisplay(unsignedcharDisplayMode)
{LCD_Write(LCD_COMMAND,0x08|DisplayMode)。
}
//设置输入模式************************************************************
#defineLCD_AC_UP0x02
#defineLCD_AC_DOWN0x00//default
#defineLCD_MOVE0x01//画面可平移
#defineLCD_NO_MOVE0x00//default
voidLCD_SetInput(unsignedcharInputMode)
{
LCD_Write(LCD_COMMAND,0x04|InputMode)。
}
/