2.1主控模块的选型和论证 方案一: 采用MSP430系列单片机,该单片机是TI公司1996年开始推向市场的一种16位超低功耗的混合信号处理器。其内部集成了很多模拟电路、数字电路和微处理器,提供强大的功能。不过该芯片昂贵不适合一般的设计开发[3]。 方案二 采用51系列的单片机,该单片机是一个高可靠性,超低价,无法解密,高性能的8位单片机,32个IO口,且STC系列的单片机可以在线编程、调试,方便地实现程序的下载与整机的调试。 因此选用方案二中的51系列单片机作为主控芯片。 2.2显示模块的选型和论证 方案一: 采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较合适,如采用在显示数字显得太浪费,且价格也相对较高,所以不用此种作为显示。 方案二: 采用LED数码管动态扫描,LED数码管价格虽适中,对于显示数字也最合适,而且采用动态扫描法与单片机连接时,占用单片机口线少。但是由于数码管动态扫描需要借助74LS164移位寄存器进行移位,该芯片在电路调试时往往有很多障碍,所以不采用LED数码管作为显示。 方案三: 采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字,图形,显示多样,清晰可见,对于本设计而言一个LCD1602的液晶屏即可,价格也还能接受,需要的接口线较多,但会给调试带来诸多方便。 所以本设计中方案三中的LCD1602液显示屏作为显示模块。 2.3脉搏检测传感器的选型和论证 方案一: 采用压电传感器用来提取人的脉搏信号,压电传感器是利用某些电介质受力后产生的压电效应制成的传感器。所谓压电效应是指某些电介质在受到某一方向的外力作用而发生形变(包括弯曲和伸缩形变)时,由于内部电荷的极化现象,会在其表面产生电荷的现象。通过此现象可以提取出人的脉搏信号。 方案二: 采用光电传感器提取人体脉搏信号,授予手指组织可以分成皮肤、肌肉、骨骼等非血液组织和血液组织,其中非血液组织的光吸收量是恒定的,而在血液中,静脉血的搏动相对动脉血是十分微弱的,可以忽略,因此可以认为光透过手指后的变化仅由动脉血的充盈而引起,那么在恒定波长的光源的照射下,通过检测透过手指的光强将可以间接测量到人体的脉搏信号[4]。 由于光电传感器较压电传感器容易在一般的地方可以买得到,因此这里选用光电传感器来提取人体脉搏信号。 2.4温度传感器的选型方案一 由于本设计是测温电路,可以使用热敏电阻之类的器件,将随被测温度变化的电压或电流采样,进行A/D转换后就可以用单片机进行数据处理,实现温度显示。这种设计需要用到A/D转换电路,增大了电路的复杂性,而且要做到高精度也比较困难。
方案二 考虑到在单片机属于数字系统,容易想到数字温度传感器,可选用DS18B20数字温度传感器,此传感器为单总线数字温度传感器,起体积小、构成的系统结构简单,它可直接将温度转化成串行数字信号给单片机处理,即可实现温度显示。另外DS18B20具有3引脚的小体积封装,测温范围为-55~+125摄氏度,测温分辨率可达0.0625摄氏度,其测量范围与精度都能符合设计要求。 以上两种方案相比较,第二种方案的电路、软件设计更简单,此方案设计的系统在功耗、测量精度、范围等方面都能很好地达到要求,故本设计采用方案二。
2.5系统整体设计概述
系统总体设计由STC89C52、按键、LCD1602、光电传感器、时钟模块、运放等构成,如图2.1所示,系统设有四个按键,可以设置上下限脉搏数,当超过范围的时候单片机会驱动蜂鸣器发响,脉搏测量的时候需要人把手轻轻的按在光电传感器上面,由于人脉搏跳动的时候,血液的透光性不一样会导致接收器那边接收的信号强弱不一样,间接的把人脉搏信号传回,通过运放对其进行放大、整形后连接到单片机的IO口,单片机利用外部中断对其进行计数,最终换算成人一分钟脉搏的跳动次数,最终显示在液晶屏上。
3.1.3单片机最小系统设计 图3.3 单片机最小系统电路图 图3.3为单片机最小系统电路图,单片机最小系统有单片机、时钟电路、复位电路组成,时钟电路选用了12MHZ的晶振提供时钟,作用为给单片机提供一个时间基准,其中执行一条基本指令需要的时间为一个机器周期,单片机的复位电路,按下复位按键之后可以使单片机进入刚上电的起始状态。图中10K排阻为P0口的上拉电阻,由于P0口跟其他IO结构不一样为漏极开路的结构,因此要加上拉电阻才能正常使用。
3.2.3液晶显示部分与STC89C52的接口 如图3.5所示。用STC89C52的P0口作为数据线,用P1.2、P1.1、P1.0分别作为LCD的EN、R/W、RS。其中EN是下降沿触发的片选信号,R/W是读写信号,RS是寄存器选择信号本模块设计要点如下:显示模块初始化:首先清屏,再设置接口数据位为8位,显示行数为1行,字型为5×7点阵,然后设置为整体显示,取消光标和字体闪烁,最后设置为正向增量方式且不移位[10]。向LCD的显示缓冲区中送字符,程序中采用2个字符数组,一个显示字符,另一个显示电压数据,要显示的字符或数据被送到相应的数组中,完成后再统一显示.首先取一个要显示的字符或数据送到LCD的显示缓冲区,程序延时2.5ms,判断是否够显示的个数,不够则地址加一取下一个要显示的字符或数据。 图3.5 LCD1602与STC89C52的引脚连接图
3.3信号采集电路设计 此部分电路的功能是由传感器将脉搏信号转换为电信号,一般为几十毫伏,必须加以放大,以达到整形电路所需的电压,一般为几伏。放大后的信号波形是不规则的脉冲信号,因此必须加以滤波整形,整形电路的输出电压应满足计数器的要求。选择电路:所选放大整形电路框图如图3.8所示。 图3.8 放大整形电路框图 3.3.1传感器简介 传感器采用了红外光电转换器,作用是通过红外光照射人的手指的血脉流动情况,把脉搏跳动转换为电信号,其原理电路如图3.9所示。 图3.9 传感器信号调节原理电路 如图3.9中,红外管VD采用ST188。用+5V电源供电,R1取150Ω,R2取33kΩ,当人把手指放在发光二极管和光电二极管之间的时候,光电二极管接收到的信号会随人脉搏强度的变化而变化[11]。 3.3.2滤波电路 图3.10 放大滤波电路 图3.10为脉搏计的放大滤波信号,由于脉搏信号输出的信号十分微弱,一般在uV级别,除此外输出的信号一般会伴随很大的噪声干扰,因此在这里用LM358搭建起一个放大和滤波电路。 3.3.3放大整形电路 经过放大滤波后的脉搏信号仍是不规则的脉冲信号,且有低频干扰,仍不满足计数器的要求,必须采用整形电路,这里选用了滞回电压比较器,如图3.11所示,其目的是为了提高抗干扰能力。集成运放采用了LM358,除此外LM358还接上了一个LED用作指示脉搏跳动的状态。 图3.11波形整形电路 3.4 数字温度传感器模块3.4.1 DS18B20性能- 独特的单线接口仅需一个端口引脚进行通信
- 简单的多点分布应用
- 无需外部器件
- 可通过数据线供电
- 零待机功耗
- 测温范围-55~+125℃,以0.5℃递增
- 可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃
- 温度数字量转换时间200ms,12位分辨率时最多在750ms内把温度转换为数字
- 应用包括温度控制、工业系统、消费品、温度计和任何热感测系统
- 负压特性:电源极性接反时,传感器不会因发热而烧毁,但不能正常工作
3.4.2 DS18B20外形及引脚说明
图3 DS18B20外形及引脚
- GND:地
- DQ:单线运用的数据输入/输出引脚
- VD:可选的电源引脚
3.4.3 DS18B20接线原理图单总线通常要求接一个约10K左右的上拉电阻,这样,当总线空闲时,其状态为高电平。
图4 DS18B20接线原理图
3.4.4 DS18B20时序图 主机使用时间隙来读写DS18B20的数据位和写命令字的位。
图5 DS18B20初始化时序
图6 DS18B20读写时序 3.4.5 数据处理 高速暂存存储器由9个字节组成,其分配如表5所示。当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在 高速暂存存储器的第0和第1个字节。单片机可通过单线接口读到该数据,读取时低位在前,高位在后。 图7 字节分配
下表为12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0, 这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际 温度。 例如+125℃的数字输出为07D0H, 实际温度=07D0H*0.0625=2000*0.0625=125℃。 例如-55℃的数字输出为FC90H,则应先将11位数据位取反加1得370H(符号位不变,也不作运算), 实际温度=370H*0.0625=880*0.0625=55℃。 可见其中低四位为小数位。
图8 DS18B20温度数据表 第四章 系统软件设计 4.1系统软件总体设计 图4.1系统流程图 主程序流程图如图4.1所示,单片机上电后先进行初始化,清楚一些参数的初值,然后等待用户按下对应的按键并进入对应的功能,当用户按下测量按键的时候流程如图4.1(c)所示,单片机通过定时15s测量人体的脉搏次数流程如图4.1(b)所示,然后再换算出对应的真实的脉搏次数再在液晶屏幕上显示流程如图4.1(a)所示,当用户按下设置脉搏范围设定按键后,单片机根据用户按下的按键进行增加或减少范围。 首先先调用液晶自定义的字库,设置好DDRAM地址后在第一行显示,根据程序中的数据设置显示数据的首地址并设置循环量,在循环过程中不断的取字符代码直到终止,第二行的显示过程同一行的显示过程一样,两行显示完毕后便结束子程序,如图4.2所示[15]。 图4.2 LCD1602初始化子函数流程图 4.2程序设计原理 软件任务分析和硬件电路设计结合进行,哪些功能由硬件完成,哪些任务由软件完成,在硬件电路设计基本定型后,也就基本上决定下来了。 软件任务分析环节是为软件设计做一个总体规划。从软件的功能来看可分为两大类:一类是执行软件,它能完成各种实质性的功能,如测量,计算,显示,打印,输出控制和通信等,另一类是监控软件,它是专门用来协调各执行模块和操作者的关系,在系统软件中充当组织调度角色的软件。这两类软件的设计方法各有特色,执行软件的设计偏重算法效率,与硬件关系密切,千变万化。 软件任务分析时,应将各执行模块一一列出,并为每一个执行模块进行功能定义和接口定义(输入输出定义)。在各执行模块进行定义时,将要牵扯到的数据结构和数据类型问题也一并规划好。 各执行模块规划好后,就可以监控程序了。首先根据系统功能和键盘设置选择一种最适合的监控程序结构。相对来讲,执行模块任务明确单纯,比较容易编程,而监控程序较易出问题。这如同当一名操作工人比较容易,而当一个厂长就比较难了。 软件任务分析的另一个内容是如何安排监控软件和各执行模块。整个系统软件可分为后台程序(背景程序)和前台程序。后台程序指主程序及其调用的子程序,这类程序对实时性要求不是太高,延误几十ms甚至几百ms也没关系,故通常将监控程序(键盘解释程序),显示程序和打印程序等与操作者打交道的程序放在后台程序中执行;而前台程序安排一些实时性要求较高的内容,如定时系统和外部中断(如掉电中断)。也可以将全部程序均安排在前台,后台程序为“使系统进入睡眠状态”,以利于系统节电和抗干扰。
第五章 系统调试
5.1软件调试 基于单片机的脉搏计系统是多功能的数字型设计,,所以对于它的程序也较为复杂,所以在编写程序和调试时出现了相对较多的问题。最后经过多次的模块子程序的修改,一步一步的完成,最终解决了软件。在软件的调试过程中主要遇到的问题如下: 问题1:烧入程序后,LCD液晶显示闪动,而且亮度不均匀。 解决:首先对调用的延时进行逐渐修改,可以解决显示闪动问题。其次,由于本作品使作动态扫描方式显示的数字,动态扫描很快,人的肉眼是无法看出,但是调用的显示程序时,如果不在反回时屏蔽掉最后的附值,则会出现很亮的现象,所以在显示的后面加了屏蔽子令,最后解决了此问题。 问题2:当用户按下按键的时候,单片机读取的数值跟设定的数值不对。 解决:重新检查矩阵键盘电路的连接,重新建立一个新的对应关系。 5.2硬件调试 基于单片机的脉搏计系统的电路较大,对于焊接方面更是不可轻视,庞大的电路系统中只要出于一处的错误,则会对检测造成很大的不便,而且电路的交线较多,对于各种锋利的引脚要注意处理,否则会刺破带有包皮的导线,则会对电路造成短路现象[14]。 在本脉搏计的设计调试中遇到了很多的问题。回想这些问题只要认真多思考都是可以避免的,以下为主要的问题: 问题1:最开始的时候以为单片机IO口直接可以驱动蜂鸣器发声,后来调试的时候久久不能出声音(见附录C)。 解决:经过查找相关资料,知道扬声器需要三极管来驱动,后来把三极管放大器加上系统便可以正常工作。 问题2:开始的时候由于没想到脉搏信号十分微弱大概在uV级别,因此没有放大足够的倍数,单片机最后没有检测到脉搏的信号(见附录C)。 解决:经过查找相关资料,确定脉搏信号的幅值范围后,增加放大器的放大倍数就解决问题。 5.3调试结果 1.放大倍数的增加 传感器的输出端经示波器观察有幅度很小的正弦波,但经整形输出后检测到的脉冲还是很弱,在确定电路没有问题的情况下,加强信号的放大倍数,调整电阻R23和R27的阻值。 2.时钟的调试 根据晶体振荡频率计算出内部定时器的基本参数,通过运行一段时间可通过秒表来校正后,看时间误差的量,以这个量为依据改变程序中的内部定时器基本参数,就可使时钟调准确。 3.开机后无显示 首先检查交流电源部分,有无交流,若无则可能保险管或变压器烧坏,如有继续查直流有无,如无则电源已烧坏,可更换解决。 4.显示正常但经适当运动后测量,脉搏次数没有增加 可能是前置放大级有问题,可采用更换的办法判断并排除。 5.进人测量状态, 但测量值不稳定 主要是光电传感器受到电磁波等干扰,其次是损坏或有虚焊。 6.开机后显示不正常或按键失灵 可查手指摆放的位置或按键电路,若无故障则是硬件损坏。 经过一系列的问题查找后系统最终能正常工作,并完成所有的功能。 5.4误差分析
注:实际的脉搏次数以听诊器测出的脉搏次数为参考值。 表3.1列出了测量值,但存在误差,由于传感器和其他器件本身并非理想线性,实测数据进行了线性补偿。 由均方差公式得: =0.59 误差分析:经校准,非线性补偿后,误差以基本达到要求。 附录A:系统整体原理图:
附录B:系统源程序 - #include <reg52.h> //调用单片机头文件
- #define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
- #define uint unsigned int //无符号整型 宏定义 变量范围0~65535
- #include<DS18N02.h>
- #include <intrins.h>
- #include "eeprom52.h"
-
-
- #define DBPort P0
-
- unsigned char i=0,timecount=0,displayOK=0,rate=0,rate1=0,aa=0,time1=0,flat300ms=0;
- unsigned int time[6]={0};
- unsigned int oneminte=0;
- unsigned int ReadTempDate;
- unsigned char S_temp_H,S_temp_L,S_heart_H,S_heart_L;
- unsigned char yemian=0,biaozhi=0;
-
-
- sbit K1 = P1^0; //菜单
- sbit K2 = P1^1; //加
- sbit K3 = P1^2; //减
- sbit Buzzer= P1^7; //控制端
-
-
- sbit rs = P2^5 ;
- sbit rw = P2^6 ;
- sbit ep = P2^7 ;
-
-
- bit flag=1;
-
-
- /******************把数据保存到单片机内部eeprom中******************/
- void write_eeprom()
- {
- SectorErase(0x2000);
- byte_write(0x2000, S_heart_H);
- byte_write(0x2001, S_heart_L);
- byte_write(0x2002, S_temp_H);
- byte_write(0x2003, S_temp_L);
-
-
- byte_write(0x2060, a_a);
- }
-
- /******************把数据从单片机内部eeprom中读出来*****************/
- void read_eeprom()
- {
- S_heart_H = byte_read(0x2000);
- S_heart_L = byte_read(0x2001);
- S_temp_H = byte_read(0x2002);
- S_temp_L = byte_read(0x2003);
- a_a = byte_read(0x2060);
- }
-
- /**************开机自检eeprom初始化*****************/
- void init_eeprom()
- {
- read_eeprom(); //先读
- if(a_a != 2) //新的单片机初始单片机内问eeprom
- {
- S_heart_H = 120;
- S_heart_L = 60;
- S_temp_H = 38;
- S_temp_L = 5;
- a_a = 2;
- write_eeprom();
- }
- }
-
- /***********************1ms延时函数*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<110;j++);
- }
-
-
- /********************************************************************
- * 名称 : delay_uint()
- * 功能 : 小延时。
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void delay_uint(uint q)
- {
- while(q--);
- }
-
-
- typedef bit BOOL ;
-
-
- uchar data_byte;
-
- void delay(uchar ms)
- { // 延时子程序
- uchar i ;
- while(ms--)
- {
- for(i = 0 ; i<250;i++) ;
- }
- }
-
-
- /************************LCD模块******************************************/
-
- BOOL lcd_bz()//测试LCD忙碌状态
- {
- BOOL result ;
- rs = 0 ;
- rw = 1 ;
- ep = 1 ;
- result = (BOOL)(P0 & 0x80) ;
- ep = 0 ;
- return result ;
- }
-
- void lcd_init()// 初始化
- {
- write_cmd(0x38) ;
- delay(1);
- write_cmd(0x08) ;
- delay(1);
- write_cmd(0x01) ;
- delay(1);
- write_cmd(0x06) ;
- delay(1);
- write_cmd(0x0c) ;
- delay(1);
- }
-
- display(uchar addr, uchar q)//在某一地址上显示一字节
- {
- delay(1) ;
- write_addr(addr) ;
- write_byte(q) ;
- // longdelay(1) ;
-
- }
-
-
- void show1()
- {
- lcd_init();// 初始化
- // Welcome
-
-
- display(0x05,'W');
- display(0x06,'e');
- display(0x07,'l');
- display(0x08,'c');
- display(0x09,'o');
- display(0x0a,'m');
- display(0x0b,'e');
- longdelay(50);//短暂延时
-
-
- display(0x42,' ');
- display(0x43,' ');
- display(0x44,' ');
- display(0x45,' ');
- display(0x46,' ');
- display(0x48,' ');
- display(0x49,' ');
- display(0x4a,' ');
- display(0x4b,' ');
- longdelay(50);//短暂延时
-
- /*
- //2012283443
- display(0x02,'2');
- display(0x03,'0');
- display(0x04,'1');
- display(0x05,'2');
- display(0x06,'2');
- display(0x07,'8');
- display(0x08,'3');
- display(0x09,'4');
- display(0x0a,'4');
- display(0x0b,'3');
- longdelay(50);//短暂延时
-
- //TEL:18268256180
- display(0x40,'T');
- display(0x41,'e');
- display(0x42,'l');
- display(0x43,':');
- display(0x44,'1');
- display(0x45,'8');
- display(0x46,'2');
- display(0x47,'6');
- display(0x48,'8');
- display(0x49,'2');
- display(0x4a,'5');
- display(0x4b,'6');
- display(0x4c,'1');
- display(0x4d,'8');
- display(0x4e,'0');
- longdelay(50);//短暂延时
- */
- }
-
-
-
-
-
- void shezhi() //对里面的数值进行修改
- {
- if(!K2) //按下按键
- {
- delay_1ms(20);
- if(!K2)
- {
- if(yemian==1)
- {
- S_heart_H+=1; //没按下一次,数值加1
- if(S_heart_H>=200) {S_heart_H=200;}
- write_eeprom(); //保存数据
-
- display(0x46,S_heart_H/100+'0');
- display(0x47,S_heart_H%100/10+'0');
- display(0x48,S_heart_H%100%10+'0');
- }
-
- if(yemian==2)
- {
- S_heart_L+=1; //没按下一次,数值加1
- if(S_heart_L>=200) {S_heart_L=200;}
- write_eeprom(); //保存数据
-
- display(0x46,S_heart_L/100+'0');
- display(0x47,S_heart_L%100/10+'0');
- display(0x48,S_heart_L%100%10+'0');
- }
-
- if(yemian==3)
- {
- S_temp_H+=1; //没按下一次,数值加1
- if(S_temp_H>=125) {S_temp_H=125;}
- write_eeprom(); //保存数据
-
- display(0x46,S_temp_H/100+'0');
- display(0x47,S_temp_H%100/10+'0');
- display(0x48,S_temp_H%100%10+'0');
- }
-
- if(yemian==4)
- {
- S_temp_L+=1; //没按下一次,数值加1
- if(S_temp_L>=125) {S_temp_L=125;}
- write_eeprom(); //保存数据
-
- display(0x46,S_temp_L/100+'0');
- display(0x47,S_temp_L%100/10+'0');
- display(0x48,S_temp_L%100%10+'0');
- }
-
- }
- // while(!K2); //等待按键 弹起 屏蔽此句,可以实现按键按下不放开时,连加技术功能,
- // 不过需要将上面延时去抖时间延长效果才好。建议改为: delay_LCD(50);
- }
-
-
- if(!K3) //按下按键
- {
- delay_1ms(20);
- if(!K3)
- {
- if(yemian==1)
- {
-
- if(S_heart_H<=1) {S_heart_H=1;}
- S_heart_H-=1; //没按下一次,数值加1
- write_eeprom(); //保存数据
-
- display(0x46,S_heart_H/100+'0');
- display(0x47,S_heart_H%100/10+'0');
- display(0x48,S_heart_H%100%10+'0');
-
- }
-
-
- if(yemian==4)
- {
- if(S_temp_L<=1) {S_temp_L=1;}
- S_temp_L-=1; //没按下一次,数值加1
- write_eeprom(); //保存数据
-
- display(0x46,S_temp_L/100+'0');
- display(0x47,S_temp_L%100/10+'0');
- display(0x48,S_temp_L%100%10+'0');
-
-
- }
- }
- // while(!K3); //等待按键 弹起 //等待按键 弹起 屏蔽此句,可以实现按键按下不放开时,连加技术功能,
- // 不过需要将上面延时去抖时间延长效果才好。建议改为: delay_LCD(50);
- }
-
-
- }
-
- void wendumaibo()
- {
-
- if(displayOK==0)//如果显示关
- {
- display(0x06,'W');
- display(0x07,'a');
- display(0x08,'i');
- display(0x09,'t');
- display(0x0a,'i');
- display(0x0b,'n');
- display(0x0c,'g');
- flag=1;
- oneminte=0;//加上这个,当displayOK标志位没有置1时,都清零计数,等待重新检测中计数。
- }
-
- if(displayOK==1 && oneminte<=200)//如果显示开
- {
- flag=0;
- display(0x06,'T');
- display(0x07,'e');
- display(0x08,'s');
- display(0x09,'t');
- display(0x0a,'i');
- display(0x0b,'n');
- display(0x0c,'g');
- }
-
- ReadTempDate=ReadTemperature();
- display(0x46,ReadTempDate/100+'0');
- display(0x47,ReadTempDate%100/10+'0');
- display(0x48,'.');
- display(0x49,ReadTempDate%100%10+'0');
- display(0x4a,0xdf);
- display(0x4b,'C');
- }
-
-
- void baojin()
- {
- if( ( (rate*6<S_heart_L || rate*6>S_heart_H) && oneminte>200 ) || ReadTempDate>=S_temp_H*10 || ReadTempDate<=S_temp_L*10 ) { Buzzer=0; }
-
- if( oneminte>=0 && oneminte<200 && ReadTempDate<S_temp_H*10 && ReadTempDate>S_temp_L*10 ) { Buzzer=1; }
- }
-
- /*************定时器0初始化程序***************/
- void time_init()
- {
- EA = 1; //开总中断
- TMOD = 0X01; //定时器0、定时器1工作方式1
- ET0 = 1; //开定时器0中断
- TR0 = 1; //允许定时器0定时
- }
-
-
- /***********外部中断0初始化程序****************/
- void init_int0() //外部中断0初始化程序
- {
- EX0=1; //允许外部中断0中断
- EA=1; //开总中断
- IT0 = 1; //外部中断0负跳变中断
- }
-
- /****************主函数***************/
- void main()
- {
- ReadTemperature();
- show1();//显示问候语和其他信息
- time_init(); //初始化定时器
- init_int0(); //外部中断0初始化程序
- init_eeprom(); //读eeprom数据
- while(1)
- {
- key(); //按键扫描
- if(flat300ms>=4) //200ms
- {
- flat300ms=0;
- //==================主界面===================
- if(yemian==0)
- {
- if(biaozhi==0)
- {
- biaozhi=1;
-
- lcd_init();// 初始化
- display(0x00,'H');
- display(0x01,'e');
- display(0x02,'a');
- display(0x03,'r');
- display(0x04,'t');
- display(0x05,':');
-
- display(0x40,'T');
- display(0x41,'e');
- display(0x42,'m');
- display(0x43,'p');
- display(0x44,':');
- }
- wendumaibo();
- baojin();
- }
-
- //==================脉搏报警上限 设置===================
- if(yemian==1)
- {
- if(biaozhi==1)
- {
- biaozhi=2;
- Buzzer=1;
- lcd_init();// 初始化
- display(0x04,'H');
- display(0x05,'e');
- display(0x06,'a');
- display(0x07,'r');
- display(0x08,'t');
- display(0x09,'-');
- display(0x0a,'H');
-
- display(0x46,S_heart_H/100+'0');
- display(0x47,S_heart_H%100/10+'0');
- display(0x48,S_heart_H%100%10+'0');
- }
- shezhi();
- }
-
- //==================脉搏报警下限 设置===================
- if(yemian==2)
- {
- if(biaozhi==2)
- {
- biaozhi=3;
- Buzzer=1;
- lcd_init();// 初始化
- display(0x04,'H');
- display(0x05,'e');
- display(0x06,'a');
- display(0x07,'r');
- display(0x08,'t');
- display(0x09,'-');
- display(0x0a,'L');
-
- display(0x46,S_heart_L/100+'0');
- display(0x47,S_heart_L%100/10+'0');
- display(0x48,S_heart_L%100%10+'0');
- }
- shezhi();
- }
-
- //==================温度报警 上限设置===================
- if(yemian==3)
- {
- if(biaozhi==3)
- {
- biaozhi=4;
- Buzzer=1;
- lcd_init();// 初始化
-
- display(0x05,'T');
- display(0x06,'e');
- display(0x07,'m');
- display(0x08,'p');
- display(0x09,'-');
- display(0x0a,'H');
-
- display(0x46,S_temp_H/100+'0');
- display(0x47,S_temp_H%100/10+'0');
- display(0x48,S_temp_H%100%10+'0');
- }
- shezhi();
- }
-
- //==================温度报警 下限设置===================
- if(yemian==4)
- {
- if(biaozhi==4)
- {
- biaozhi=0;
- Buzzer=1;
- lcd_init();// 初始化
-
- display(0x05,'T');
- display(0x06,'e');
- display(0x07,'m');
- display(0x08,'p');
- display(0x09,'-');
- display(0x0a,'L');
-
- display(0x46,S_temp_L/100+'0');
- display(0x47,S_temp_L%100/10+'0');
- display(0x48,S_temp_L%100%10+'0');
- }
- shezhi();
- }
-
-
- }
- }
- }
-
-
- void int0() interrupt 0
- {
- if(time1>=8)
- {
- time1=0;
- timecount=0;//50ms计数清零
- i++;
- if(i==3)//记录到超过等于3次时间
- {
- i=1;//计数从1开始
- displayOK=1; //测得3次开始显示
- }
-
- if(displayOK==1 && oneminte<=200 &&yemian==0) { rate1=0; rate ++; } //10s
- if( oneminte>200 && flag==0 && yemian==0)
- {
- flag=1;
- rate1=rate*6;
-
- display(0x09,'/');
- display(0x0a,'m');
- display(0x0b,'i');
- display(0x0c,'n');
-
- display(0x06,rate1/100+'0');
- display(0x07,rate1%100/10+'0');
- display(0x08,rate1%100%10+'0');
- }
-
- }
-
- }
-
-
- /*************定时器0中断服务程序***************/
- void time0_int() interrupt 1
- {
- TH0 = 0x3c;
- TL0 = 0xb0; // 50ms 12M
- timecount++;//每50ms一次计数
- time1++;
-
- oneminte++;
- flat300ms++;
- if(timecount>50 &&yemian==0 ) //当超过50*50ms=2.5s左右没有检测到信号停止显示
- {
- i=0;//数据个数清零
- timecount=0;//50ms计数清零
- displayOK=0;//显示关
- oneminte=0;
- rate=0;
- display(0x06,'W');
- display(0x07,'a');
- display(0x08,'i');
- display(0x09,'t');
- display(0x0a,'i');
- display(0x0b,'n');
- display(0x0c,'g');
-
-
- }
- }
复制代码
以上的Word格式文档51黑下载地址:
参考文档.doc
(895.27 KB, 下载次数: 18)
|