找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 16797|回复: 6
打印 上一主题 下一主题
收起左侧

单片机脉搏体温检测仪的Proteus仿真设计与调试 附源码+文档

  [复制链接]
跳转到指定楼层
楼主


由于仿真中没有红外,手指也模拟不了,其实就是单片机的IO口检测脉冲信号,那样用个方波信号模拟就行了
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


一、设计要求
本设计利用红外光电传感器产生脉冲信号,经过放大整形后,输入单片机内进行相应的控制,从而测量出一分钟内的脉搏跳动次数,快捷方便。测量范围限可以用按键调节,并进行声音报警,测量结果以数字方式显示,测量精确到2次/分。同时还可以设定上限次数和下限次数,当测量的范围超过设定的范围则驱动蜂鸣器报警提醒,结果最终可以把采集到的脉搏信号显示在LCD1602上。

二、方案论证

系统框图如下:

2.1主控模块的选型和论证

方案一:
采用MSP430系列单片机,该单片机是TI公司1996年开始推向市场的一种16位超低功耗的混合信号处理器。其内部集成了很多模拟电路、数字电路和微处理器,提供强大的功能。不过该芯片昂贵不适合一般的设计开发[3]。
方案二:
采用51系列的单片机,该单片机是一个高可靠性,超低价,无法解密,高性能的8位单片机,32个IO口,且STC系列的单片机可以在线编程、调试,方便地实现程序的下载与整机的调试。
因此选用方案二中的51系列单片机作为主控芯片。

2.2显示模块的选型和论证

方案一:

采用LED数码管动态扫描,LED数码管价格虽适中,对于显示数字也最合适,而且采用动态扫描法与单片机连接时,占用单片机口线少。但是由于数码管动态扫描需要借助74LS164移位寄存器进行移位,该芯片在电路调试时往往有很多障碍,所以不采用LED数码管作为显示。

方案二:

采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字,图形,显示多样,清晰可见,对于本设计而言一个LCD1602的液晶屏即可,价格也还能接受,需要的接口线较多,但会给调试带来诸多方便。
所以本设计中方案二中的LCD1602液显示屏作为显示模块。

2.3脉搏检测传感器的选型和论证

方案一:压电式
压电式传感器的检测方法是利用压力传感器或振动传感器将人体脉搏振动转换成电信号。常见的压力传感器可用现有的压电陶瓷代替。压电式元件的内阻极高,通常采用两片相同的元件,使其极性反向相叠,由夹在中间的铜片作为一个电极。这样,中央电极处于全空状态,可以用具有良好绝缘性的导线引出。此种方法的优点是传感器种类多,一般的传感器输出信号也比较大,对后面的放大电路要求不高。压电陶瓷具有成本低、取材方便、易于提高敏感度等特点。
方案二:声电式
声电式传感器的作用是将气体、液体或固体中传播的机械振动转换成电信号。因此,它也属于力学量传感器。它的制作材料一般由不定性无烟煤颗粒或压电陶瓷构成。颗粒式声电传感器的优点是耐用、成本低和容易制作,缺点是颗粒的机械磨损和接触表面上的瞬间电弧会使颗粒逐渐老化,从而导致杂音大、性能不稳定和非线性;而压电陶瓷式的声电传感器在检测声音信号时却存在着一定的缺陷。
声电式检测方法是利用微音传感器将人体的振动的声音转换成电信号。此种方法的优点是作为传感器的微音传感器可利用现有的驻极体或电容式话筒,但其后面的电路要采取一定的措施将环境的声音干扰信号滤去。
方案三:光电式
光电系统通常是指能敏感由紫外光到红外光的光能量,并将光能量转换成电信号的器件。通常用的光电器件有光电二极管和光电三极管。光电式传感器测量微小的位移变化有明显的效果,但是光电传感器对材料、电路控制和光电管属性要求较高:1)吸收红外光的能力极强2)介电常数小,以便得到大的输出电压。3)介电损耗小。
光电式检测方法是利用光电传感器检测人体内血液流动时对光的透过率或反射率不同而将其转换成电信号的方法。此种方法有两种方式:一种是对射式,另一种是反射式。对射式是在一个大小合适的环的两侧各放一个发射管和一个接收管,测量时将人的手指伸到环中,由于手指中的血流量的变化而使光电接收管的光电流也随之变化,反射式是光电发射与光电接收都指向一个方向,当人体内的血流发生变化时其对光的反射率也随之变化,从而检测出心率。这种方法的优点是外界干扰信号小,但其最大的难点是传感器输出信号小,对后面的放大电路要求较高。此外,对于干扰变化强烈的信号,回路不宜调制,可视光电管的定向角不同,光轴也不宜把握。
综上所述,从传感器的制作工艺、材料的选取、受外界的干扰信号的干扰程度和制作过程中前级电路的处理难易程度上考虑,就选用一对红外对射二极管实现。

2.4温度传感器的选型
方案一:
由于本设计是测温电路,可以使用热敏电阻之类的器件,将随被测温度变化的电压或电流采样,进行A/D转换后就可以用单片机进行数据处理,实现温度显示。这种设计需要用到A/D转换电路,增大了电路的复杂性,而且要做到高精度也比较困难。

方案二
              考虑到在单片机属于数字系统,容易想到数字温度传感器,可选用DS18B20数字温度传感器,此传感器为单总线数字温度传感器,起体积小、构成的系统结构简单,它可直接将温度转化成串行数字信号给单片机处理,即可实现温度显示。另外DS18B20具有3引脚的小体积封装,测温范围为-55~+125摄氏度,测温分辨率可达0.0625摄氏度,其测量范围与精度都能符合设计要求。
              以上两种方案相比较,第二种方案的电路、软件设计更简单,此方案设计的系统在功耗、测量精度、范围等方面都能很好地达到要求,故本设计采用方案二。

2.5系统整体设计概述

系统总体设计由STC89C52、按键、LCD1602、光电传感器、时钟模块、运放等构成,系统设有四个按键,可以设置上下限脉搏数,当超过范围的时候单片机会驱动蜂鸣器发响,脉搏测量的时候需要人把手轻轻的按在光电传感器上面,由于人脉搏跳动的时候,血液的透光性不一样会导致接收器那边接收的信号强弱不一样,间接的把人脉搏信号传回,通过运放对其进行放大、整形后连接到单片机的IO口,单片机利用外部中断对其进行计数,最终换算成人一分钟脉搏的跳动次数,最终显示在液晶屏上。

三、理论设计

硬件设计

1、硬件原理图

2、工作原理

本设计利用红外光电传感器产生脉冲信号,经过放大整形后,输入单片机内进行相应的控制,从而测量出一分钟内的脉搏跳动次数,当测量的范围超过设定的范围则驱动蜂鸣器报警提醒,当检测的体温超过设置的温度上下限也会蜂鸣器报警提醒,结果最终可以把采集到的脉搏信号显示在LCD1602上。

3.1.1单片机最小系统设计

图3.1 单片机最小系统电路图
              图3.1为单片机最小系统电路图,单片机最小系统有单片机、时钟电路、复位电路组成,时钟电路选用了12MHZ的晶振提供时钟,作用为给单片机提供一个时间基准,其中执行一条基本指令需要的时间为一个机器周期,单片机的复位电路,按下复位按键之后可以使单片机进入刚上电的起始状态。图中10K排阻为P0口的上拉电阻,由于P0口跟其他IO结构不一样为漏极开路的结构,因此要加上拉电阻才能正常使用。

3.1.2 液晶原理介绍

液晶显示器(LCD)英文全称为Liquid Crystal Display,它一种是采用了液晶控制透光度技术来实现色彩的显示器。和CRT显示器相比,LCD的优点是很明显的。由于通过控制是否透光来控制亮和暗,当色彩不变时,液晶也保持不变,这样就无须考虑刷新率的问题。
显示接口用来显示系统的状态,命令或采集的电压数据。本系统显示部分用的是LCD液晶模块,采用一个16×2的字符型液晶显示模块。
LCD1602引脚图

液晶寄存器选择控制如表3.1。

表3.1寄存器选择控制
RS
R/W
操作说明
0
0
写入指令寄存器(清除屏等)
0
1
读busy flag(DB7),以及读取位址计数器(DB0~DB6)值
1
0
写入数据寄存器(显示各字型等)
1
1
从数据寄存器读取数据

LCD1602与单片机接口电路如下:


3.1.3信号采集电路

信号采集电路如图3-2所示。5MM红外对管D1与D3组成红外传感器。因红外传感器输出的脉冲信号是非常微弱的信号,而且频率很低(如脉搏50次/分钟为0.78Hz,200次/分钟为3.33Hz),并且还伴有各种噪声干扰,故该信号要经过R7、C5低通滤波,去除高频干扰。当传感器检测到较强的干扰噪音时,其输出端的直流电压信号会有很大变化
图3.2 信号采集电路

3.1.4信号放大电路

如图3-3所示,R3与R8的电阻之比为放大器的放大倍数,经过计算所得该放大器的理论值为200倍,但由于8号接口上5V供压不足再加上材料限制和人为的因素,该放大倍数只有20倍左右。
  图中C7为耦合电容,作用为隔直流通交流,之所以使用1uF的电容,是为了让所有的信号通过。
图3.3 信号放大电路

3.1.5信号比较电路

电压比较器是一种常用的集成电路。它可用于报警器电路、自动控制电路、测量技术,也可用于V/F 变换电路、A/D 变换电路、高速采样电路、电源电压监测电路、振荡器及压控振荡器电路、过零检测电路等。我们主要介绍其基本概念、工作原理及典型工作电路,电压比较器是对两个模拟电压比较其大小并判断出其中哪一个电压高,接到的信号电压小于该值时显示0V,当大于该值时显示5V,这就形成了0和5V的方波。如图3.4 所示。
图3.4 放大滤波电路
软件设计
3.2系统软件总体设计
图3.2系统流程图
主程序流程图如图3.2所示,单片机上电后先进行初始化,清楚一些参数的初值,然后等待用户按下对应的按键并进入对应的功能,当用户按下测量按键的时候流程如图3.2(c)所示,单片机通过定时15s测量人体的脉搏次数流程如图3.2(b)所示,然后再换算出对应的真实的脉搏次数再在液晶屏幕上显示流程如图3.2(a)所示,当用户按下设置脉搏范围设定按键后,单片机根据用户按下的按键进行增加或减少范围。

延时子程序:


四、测试方案、测试结果及分析

4.1软件调试
当模块设计完成并在ISIS 7 protues中仿真成功后,电路基本确定,但那只是理论值,需要对这些仿真电路进行试验,以确保这些电路是否适用与该设计。
4.2硬件调试
准备施焊;加热焊件;送入焊丝;焊接元件。在焊接过程中要注意假焊,虚焊,焊接不规则等等问题,尽量避免不必要的错误。器件安装焊接完后,就要焊接电线,一定要保证连接端口的正确连接,管脚的位置及所代表的含义不能搞错,这样才能避免电路板出现问题,将装置供电后,将已写好的程序下载到单片机里面,观察板子的现象。
测试结果:程序下载好并供电后,LCD显示屏上显示14.4°,手指放在红外灯管上,显示屏显示脉搏次数93,如果脉搏超过预先设定的范围,装置中的蜂鸣器报警,测量的脉搏在正常范围内,警报停止报警。按下功能键,可以修改设置的警告上下限。在测量时,红外传感器检测到的人体信号很微弱,手指的一点抖动都会引起测量心率值的大幅变化,手指尽量别乱动,以免测量数据不准确,导致蜂鸣器一直报警。
分析:设计要求全部实现。

五、作品功能和使用说明:

作品功能:实现温度的测量、脉搏测量。能测出即时的温度和脉搏,显示在LCD屏上。手指放到红外对管中,2秒内读出心率。同时还可以设定上限次数和下限次数,当测量的范围超过设定的范围则驱动蜂鸣器报警提醒,当检测的体温超过设置的温度上下限也会蜂鸣器报警提醒。
使用说明:显示每分钟脉搏次数和温度。
三个按键:一个设置,一个加,一个减。
按下设置的时候才可以加减。
手指放上去尽量别乱动。

六、心得体会

通过这次课程设计,学到了不少课本上没有的知识,也锻炼了自己的动手能力,将以前学过的零散的知识串到一起。经过长时间的设计及调试,软件仿真基本能实现基于单片机的脉搏计的所有功能。但是硬件的稳定性有待进一步提高,无法发现错误在何处。
综合设计主要涉及硬件和软件两方面的内容,硬件和软件开发能力都获得了提高。首先硬件方面,基本了解了电子产品的开发流程和所要做的工作,焊完实物后,首先是硬件调试。电路的调试过程是检验、修正设计方案的实践过程,但也是对理论知识的实际应用,解决各种问题的关键环节,是电路设计人员必须掌握的基本技能。基本掌握了Protel99SE原理图的方法,通过开发板的设计和硬件搭建的过程,对51系单片机的接口有了更深层次的理解,熟悉了一些单片机常用的外围电路引脚和连接方法,如LCD液晶,键盘等。并且学会了分析问题解决问题的能力,加深了对所学理论知识的理解和运用,动手能力得到了很大的提高,创新意识得到了锻炼。

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>       

  3. #define uint            unsigned int
  4. #define uchar           unsigned char
  5. #define ulong           unsigned long         //宏定义
  6. #define LCD_DATA        P0                                 //定义P0口为LCD_DATA

  7. sbit LCD_RS =P2^5;
  8. sbit LCD_RW =P2^6;
  9. sbit LCD_E  =P2^7;                                                 //定义LCD控制引脚

  10. sbit Xintiao =P1^0 ;                                         //脉搏检测输入端定义
  11. sbit speaker =P2^4;                                                 //蜂鸣器引脚定义
  12. sbit DQ=P3^7;

  13. void delay5ms(void);   //误差 0us
  14. void LCD_WriteData(uchar LCD_1602_DATA);         /********LCD1602数据写入***********/
  15. void LCD_WriteCom(uchar LCD_1602_COM);                 /********LCD1602命令写入***********/
  16. void lcd_1602_word(uchar Adress_Com,uchar Num_Adat,uchar *Adress_Data); /*1602字符显示函数,变量依次为字符显示首地址,显示字符长度,所显示的字符*/
  17. void InitLcd();//液晶初始化函数

  18. void Tim_Init();

  19. uchar Xintiao_Change=0;           //
  20. uint  Xintiao_Jishu;
  21. uchar stop;
  22. uchar View_Data[3];
  23. uchar View_L[3];
  24. uchar View_H[3];
  25. uchar Xintiao_H=100;        //脉搏上限
  26. uchar Xintiao_L=40;                //脉搏下限
  27. uint wendu=0;

  28. uchar Key_Change;
  29. uchar Key_Value;                //按键键值
  30. uchar View_Con;                        //设置的位(0正常工作,1设置上限,2设置下限)
  31. uchar View_Change;


  32. /*****延时子程序*****/
  33. void Delay_DS18B20(int num)
  34. {
  35.   while(num--) ;
  36. }
  37. /*****初始化DS18B20*****/
  38. void Init_DS18B20(void)
  39. {
  40.   unsigned char x=0;
  41.   DQ = 1;         //DQ复位
  42.   Delay_DS18B20(8);    //稍做延时
  43.   DQ = 0;         //单片机将DQ拉低
  44.   Delay_DS18B20(80);   //精确延时,大于480us
  45.   DQ = 1;         //拉高总线
  46.   Delay_DS18B20(34);
  47. }
  48. /*****读一个字节*****/
  49. unsigned char ReadOneChar(void)
  50. {
  51.   unsigned char i=0;
  52.   unsigned char dat = 0;
  53.   for (i=8;i>0;i--)
  54.   {
  55.     DQ = 0;     // 给脉冲信号
  56.     dat>>=1;
  57.     DQ = 1;     // 给脉冲信号
  58.     if(DQ)
  59.     dat|=0x80;
  60.     Delay_DS18B20(4);
  61.   }
  62.   return(dat);
  63. }

  64. void WriteOneChar(unsigned char dat)
  65. {
  66.   unsigned char i=0;
  67.   for (i=8; i>0; i--)
  68.   {
  69.     DQ = 0;
  70.     DQ = dat&0x01;
  71.     Delay_DS18B20(5);
  72.     DQ = 1;
  73.     dat>>=1;
  74.   }
  75. }
  76. /*****读取温度*****/
  77. unsigned int ReadTemperature(void)
  78. {
  79.   unsigned char a=0;
  80.   unsigned char b=0;
  81.   unsigned int t=0;
  82.   float tt=0;
  83.   Init_DS18B20();
  84.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  85.   WriteOneChar(0x44);  //启动温度转换
  86.   Init_DS18B20();
  87.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  88.   WriteOneChar(0xBE);  //读取温度寄存器
  89.   a=ReadOneChar();     //读低8位
  90.   b=ReadOneChar();    //读高8位
  91.   t=b;
  92.   t<<=8;
  93.   t=t|a;
  94.   tt=t*0.0625;
  95.   t= tt*10+0.5;     //放大10倍输出并四舍五入
  96.   return(t);
  97. }
  98. //=====================================================================================
  99. //=====================================================================================
  100. //=====================================================================================


  101. void main()          //主函数
  102. {
  103. InitLcd();
  104. Tim_Init();
  105. lcd_1602_word(0x80,16,"Heart Rate:     ");          //初始化显示

  106. TR0=1;
  107. TR1=1;                                  //打开定时器
  108. while(1)                          //进入循环
  109.   {
  110.           if(View_Con==0)
  111.         {
  112.                 wendu=ReadTemperature();
  113.                 lcd_1602_word(0xc0,10," Temp:    ");//显示第二行数据
  114.                 LCD_WriteCom(0x80+0x40+10);
  115.                 LCD_WriteData(wendu/100+0x30);
  116.                 LCD_WriteData(wendu%100/10+0x30);
  117.                 LCD_WriteData('.');
  118.                 LCD_WriteData(wendu%100%10+0x30);
  119.                 LCD_WriteData(0xdf);
  120.                 LCD_WriteData('C');
  121.         }
  122.          
  123.    if(Key_Change)          //有按键按下并已经得出键值
  124.     {
  125.          Key_Change=0;          //将按键使能变量清零,等待下次按键按下
  126.          View_Change=1;
  127.          switch(Key_Value)                                //判断键值
  128.           {
  129.            case 1:                                                //设置键按下
  130.                  {
  131.                           View_Con++;                        //设置的位加
  132.                           if(View_Con==3)                //都设置好后将此变量清零
  133.                            View_Con=0;
  134.                           break;                                //跳出,下同
  135.                          }
  136.            case 2:                                                //加键按下
  137.                  {
  138.                           if(View_Con==2)                //判断是设置上限
  139.                            {
  140.                                    if(Xintiao_H<150)        //上限数值小于150
  141.                                  Xintiao_H++;                //上限+
  142.                            }
  143.                           if(View_Con==1)                //如果是设置下限
  144.                            {
  145.                                    if(Xintiao_L<Xintiao_H-1)//下限值小于上限-1(下限值不能超过上限)
  146.                                  Xintiao_L++;                //下限值加
  147.                            }
  148.                           break;
  149.                          }
  150.            case 3:                                                //减键按下
  151.                  {
  152.                           if(View_Con==2)                //设置上限
  153.                            {
  154.                                    if(Xintiao_H>Xintiao_L+1)//上限数据大于下限+1(同样上限值不能小于下限)
  155.                                  Xintiao_H--;                //上限数据减
  156.                            }
  157.                           if(View_Con==1)                //设置下限
  158.                            {
  159.                                    if(Xintiao_L>30)        //下限数据大于30时
  160.                                  Xintiao_L--;                //下限数据减
  161.                            }
  162.                           break;
  163.                          }
  164.          }
  165.         }
  166.    if(View_Change)//开始显示变量
  167.     {
  168.          View_Change=0;//变量清零
  169.          if(stop==0)                          //心率正常时
  170.           {
  171.            if(View_Data[0]==0x30) //最高位为0时不显示
  172.             View_Data[0]=' ';
  173.           }
  174.          else                                          //心率不正常(计数超过5000,也就是两次信号时间超过5s)不显示数据
  175.           {
  176.            View_Data[0]=' ';
  177.            View_Data[1]=' ';
  178.            View_Data[2]=' ';
  179.           }

  180.          switch(View_Con)
  181.           {
  182.            case 0: //正常显示
  183.                   {
  184.                            lcd_1602_word(0x80,16,"Heart Rate:     ");//显示一行数据

  185.                            lcd_1602_word(0x8d,3,View_Data);                         //第1行显示心率

  186.                            break;
  187.                           }
  188.            case 1: //设置下限时显示
  189.                   {
  190.                            lcd_1602_word(0x80,16,"Heart Rate:     ");//第一行显示心率
  191.                            lcd_1602_word(0x8d,3,View_Data);
  192.                           
  193.                            View_L[0]=Xintiao_L/100+0x30;                //将下限数据拆字
  194.                            View_L[1]=Xintiao_L%100/10+0x30;
  195.                            View_L[2]=Xintiao_L%10+0x30;

  196.                            if(View_L[0]==0x30)                                        //最高位为0时,不显示
  197.                             View_L[0]=' ';
  198.                           
  199.                            lcd_1602_word(0xC0,16,"Warning L :     ");//第二行显示下限数据
  200.                            lcd_1602_word(0xCd,3,View_L);
  201.                            break;
  202.                           }
  203.            case 2: //设置上限时显示(同上)
  204.                   {
  205.                            lcd_1602_word(0x80,16,"Heart Rate:     ");
  206.                            lcd_1602_word(0x8d,3,View_Data);
  207.                           
  208.                            View_H[0]=Xintiao_H/100+0x30;
  209.                            View_H[1]=Xintiao_H%100/10+0x30;
  210.                            View_H[2]=Xintiao_H%10+0x30;

  211.                            if(View_H[0]==0x30)
  212.                             View_H[0]=' ';
  213.                           
  214.                            lcd_1602_word(0xC0,16,"Warning H :     ");
  215.                            lcd_1602_word(0xCd,3,View_H);
  216.                            break;
  217.                           }
  218.           }
  219.         }
  220.   }
  221. }

  222. void Time1() interrupt 3                //定时器1服务函数
  223. {
  224.         static uchar Key_Con,Xintiao_Con;
  225.         TH1=0xd8;                   //10ms
  226.         TL1=0xf0;                   //重新赋初值
  227.         switch(Key_Con)   //无按键按下时此值为0
  228.         {
  229.                 case 0:                   //每10ms扫描此处
  230.                 {
  231.                         if((P3&0x07)!=0x07)//扫描按键是否有按下
  232.                         {
  233.                                 Key_Con++;                  //有按下此值加1,值为1
  234.                         }
  235.                         break;
  236.                 }
  237.                 case 1:                                          //10ms后二次进入中断后扫描此处(Key_Con为1)
  238.                 {
  239.                         if((P3&0x07)!=0x07)//第二次进入中断时,按键仍然是按下(起到按键延时去抖的作用)
  240.                         {
  241.                                 Key_Con++;                  //变量加1,值为2
  242.                                 switch(P3&0x07)  //判断是哪个按键按下
  243.                                 {
  244.                                         case 0x06:Key_Value=1;break;         //判断好按键后将键值赋值给变量Key_Value
  245.                                         case 0x05:Key_Value=2;break;
  246.                                         case 0x03:Key_Value=3;break;
  247.                                 }
  248.                         }
  249.                         else                                                                 //如果10ms时没有检测到按键按下(按下时间过短)
  250.                         {
  251.                                 Key_Con=0;                                                 //变量清零,重新检测按键
  252.                         }
  253.                         break;
  254.                 }
  255.                 case 2:                                                                         //20ms后检测按键
  256.                 {
  257.                         if((P3&0x07)==0x07)                                 //检测按键是否还是按下状态
  258.                         {
  259.                                 Key_Change=1;                                         //有按键按下使能变量,(此变量为1时才会处理键值数据)
  260.                                 Key_Con=0;                                                //变量清零,等待下次有按键按下
  261.                         }
  262.                         break;
  263.                 }
  264.         }
  265.                
  266.         switch (Xintiao_Con)//此处与上面按键的检测类似
  267.         {
  268.                 case 0:                         //默认Xintiao_Con是为0的
  269.                 {
  270.                         if(!Xintiao)//每10ms(上面的定时器)检测一次脉搏是否有信号
  271.                         {
  272.                                 Xintiao_Con++;//如果有信号,变量加一,程序就会往下走了
  273.                         }
  274.                         break;
  275.                 }
  276.                 case 1:
  277.                 {
  278.                         if(!Xintiao)           //每过10ms检测一下信号是否还存在
  279.                         {
  280.                                 Xintiao_Con++;//存在就加一
  281.                         }
  282.                         else
  283.                         {
  284.                                 Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测
  285.                         }
  286.                         break;
  287.                 }
  288.                 case 2:
  289.                 {
  290.                         if(!Xintiao)
  291.                         {
  292.                                 Xintiao_Con++;//存在就加一
  293.                         }
  294.                         else
  295.                         {
  296.                                 Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测
  297.                         }
  298.                         break;
  299.                 }
  300.                 case 3:
  301.                 {
  302.                         if(!Xintiao)
  303.                         {
  304.                                 Xintiao_Con++;//存在就加一
  305.                         }
  306.                         else
  307.                         {
  308.                                 Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测
  309.                         }
  310.                         break;
  311.                 }
  312.                 case 4:
  313.                 {
  314.                         if(Xintiao)//超过30ms一直有信号,判定此次是脉搏信号,执行以下程序
  315.                         {
  316.                                 if(Xintiao_Change==1)//心率计原理为检测两次脉冲间隔时间计算心率,变量Xintiao_Change第一次脉冲时为0的,所有走下面的else,第二次走这里
  317.                                 {
  318.                                         View_Data[0]=(60000/Xintiao_Jishu)/100+0x30;
  319.                                         View_Data[1]=(60000/Xintiao_Jishu)%100/10+0x30;
  320.                                         View_Data[2]=(60000/Xintiao_Jishu)%10+0x30;
  321.                                        
  322.                                         if(((60000/Xintiao_Jishu)>=Xintiao_H)||((60000/Xintiao_Jishu)<=Xintiao_L))//心率不在范围内报警
  323.                                         speaker=0;                        //蜂鸣器响
  324.                                         else
  325.                                         speaker=1;                        //不响
  326.                        
  327.                                         View_Change=1;           //计算出心率后启动显示
  328.                                         Xintiao_Jishu=0;           //心跳计数清零
  329.                                         Xintiao_Change=0;   //计算出心率后该变量清零,准备下次检测心率
  330.                                         stop=0;                           //计算出心率后stop清零
  331.                                    TR0=0;
  332.                                 //   wendu=ReadTemperature();
  333.                                 //   TR1=0;
  334.                                 }
  335.                                 else//第一次脉冲时Xintiao_Change为0
  336.                                 {
  337.                                         Xintiao_Jishu=0;        //脉冲计时变量清零,开始计时
  338.                                         Xintiao_Change=1;//Xintiao_Change置1,准备第二次检测到脉冲时计算心率
  339.                                         TR0=1;
  340.                                 }
  341.                                 Xintiao_Con=0;        //清零,准备检测下一次脉冲
  342.                                 break;
  343.                         }
  344.                 }
  345.         }
  346. }
  347. /**定时器T0工作函数**/
  348. void Time0() interrupt 1
  349. {
  350. TH0=0xfc;                   //1ms
  351. TL0=0x18;                   //重新赋初值
  352. Xintiao_Jishu++;  //心跳计数加
  353. if(Xintiao_Jishu==5000)//心跳计数大于5000
  354.   {
  355.    Xintiao_Jishu=0;                //数据清零
  356.    View_Change=1;                //显示位置1
  357.    Xintiao_Change=0;        //置零,准备再次检测
  358.    stop=1;           //心跳计数超过5000后说明心率不正常或者没有测出,stop置1
  359.    speaker=1;  //关闭蜂鸣器
  360.   }
  361. }
  362. /**定时器初始化函数**/
  363. void Tim_Init()
  364. {
  365. EA=1;                          //打开中断总开关
  366. ET0=1;                          //打开T0中断允许开关
  367. ET1=1;                          //打开T1中断允许开关
  368. TMOD=0x11;                  //设定定时器状态
  369. TH0=0xfc;                   //1ms
  370. TL0=0x18;                   //赋初值

  371. TH1=0xd8;                   //10ms
  372. TL1=0xf0;                   //赋初值
  373. }

  374. /**Adress_Com显示地址,Num_Adat显示字符数量,Adress_Data显示字符串内容**/
  375. void lcd_1602_word(uchar Adress_Com,uchar Num_Adat,uchar *Adress_Data)
  376. {
  377. uchar a=0;
  378. uchar Data_Word;
  379. LCD_WriteCom(Adress_Com); //选中地址
  380. for(a=0;a<Num_Adat;a++)   //for循环决定显示字符个数
  381.   {
  382.    Data_Word=*Adress_Data;          //读取字符串数据
  383.    LCD_WriteData(Data_Word);  //显示字符串
  384.    Adress_Data++;                          //显示地址加一
  385.   }
  386. }

  387. ……………………

  388. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
16 脉搏体温检测仪的设计与制作2016111435朱波.zip (731.88 KB, 下载次数: 335)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:675863 发表于 2020-1-12 21:23 | 只看该作者
仿真运行不了,似乎有错误
回复

使用道具 举报

板凳
ID:705967 发表于 2020-4-7 22:19 | 只看该作者
霸气范 发表于 2020-1-12 21:23
仿真运行不了,似乎有错误

真的吗??运行不了吗?
回复

使用道具 举报

地板
ID:57810 发表于 2020-4-7 23:45 | 只看该作者
好资料,学习下,楼上的 仿真运行出来是这样的,大家看看有错误吗?我是用Proteus 7.5版本,,,刚开始用8.8也是仿真不出来

回复

使用道具 举报

5#
ID:382079 发表于 2020-4-20 08:19 | 只看该作者
楼主, 是不是还得在这个仿真里面导入程序才能运行呢
回复

使用道具 举报

6#
ID:314894 发表于 2020-4-29 21:05 | 只看该作者
楼主你仿真运行不了,在线调试都没用
回复

使用道具 举报

7#
ID:755333 发表于 2020-5-21 09:45 | 只看该作者
ywc3000 发表于 2020-4-7 23:45
好资料,学习下,楼上的 仿真运行出来是这样的,大家看看有错误吗?我是用Proteus 7.5版本,,,刚开始用8.8也是 ...

仿真里的脉搏数据不能显示呀
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表