心率测试仪.docx
《心率测试仪.docx》由会员分享,可在线阅读,更多相关《心率测试仪.docx(22页珍藏版)》请在冰豆网上搜索。
心率测试仪
心率测试仪设计与制作
摘要:
脉搏波所呈现出来的形态、强度、速率和节律等方面的综合信息,能反映出人体心血管系统中许多生理疾病的血流特征。
本系统采用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系统主程序的设计
系统主程序控制单片机系统按预定的操作方式运行,是单片机系统程序的框架。
系统主程序流程图如图:
图系统主程序流程图
上电后,首先进行整机初始化处理。
主程序的初始化模块主要完成仪器硬件、软件的初态设置,单片机内专用寄存器的设定,单片机工作方式及各端口的工作状态的规定。
整机初始化结束后,检测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。
每分钟脉搏跳动次数
,为方便计算,取
。
脉搏波动频率测量子程序流程图如下图所示。
脉搏频率测量中断服务程序流程图
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;ifor(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);
}
//初始化LCD************************************************************
voidLCD_Initial(void)//初始化LCD
{
LCD_Write(0,0x38);
LCD_W