基于单片机心率计程序
基于51单片机的心率计设计

基于51单片机的心率计设计一、引言心率是人体健康状况的一个重要指标,测量心率对于预防心血管疾病和监控身体健康非常重要。
本文将介绍基于51单片机的心率计的设计。
二、硬件设计1. 传感器心率计的核心是心率传感器,用于检测心脏的跳动并转化为电信号。
常见的心率传感器有光电传感器和压电传感器。
本设计选用光电传感器,通过红外光发射二极管和光敏二极管组成,以非侵入性的方式测量心率。
2. 信号放大与滤波电路由于心率信号较小,需要经过放大与滤波电路进行信号处理。
设计中使用运放对信号进行放大,并通过带通滤波器滤除杂散信号。
3. 数模转换放大滤波后的心率信号是模拟信号,需要通过模数转换器(ADC)将其转换为数字信号,以便后续处理和显示。
4. 显示屏心率计的设计中需要一个合适的显示屏来显示测量出的心率数值。
常见的显示屏有LCD液晶屏和LED数码管。
5. 51单片机本设计使用51单片机作为控制核心,负责对信号的采集、处理和显示。
51单片机具有成熟的开发环境和丰富的外设资源,非常适合嵌入式系统的设计。
三、软件设计1. 信号采集通过51单片机的IO口连接传感器,定时采集传感器输出的心率信号,并将其转换为数字信号。
2. 信号处理通过软件算法对采集到的心率信号进行滤波和处理,去除噪声和干扰,提取出准确的心率数值。
3. 心率计算根据心率信号的特征,设计一个合适的算法对心率进行计算。
常用的算法有峰值检测法和自相关法等。
4. 数据显示将计算得到的心率数值通过LCD屏或数码管显示出来,以便用户直观地了解自己的心率状况。
四、实验结果与讨论经过实验验证,基于51单片机的心率计设计能够准确地测量心率,并将心率数值显示在屏幕上。
通过与商用心率计的比对,结果显示该设计具有较高的准确性和稳定性。
五、应用前景基于51单片机的心率计设计可以应用于医疗领域、体育训练和健康监控等方面。
例如,可以将心率计嵌入健康手环中,实时监测用户的心率状况,并提醒用户进行适当的运动。
基于单片机的心率计设计

基于单片机的心率计设计
一、硬件设计
1.核心处理器:选用STM32单片机,具有丰富的外设资源,大
内存容量,高性能,在实现心率计功能方面非常适合。
2.心率传感器模块:选用现有的心率传感器模块,如MAX30102。
3.显示模块:可以采用OLED显示模块或者LCD模块来显示心率值。
4.按键模块:添加一个按键模块,用于操作心率计。
5.电源模块:设计适合的电源模块,以保障心率计稳定工作。
二、软件设计
1.初始化:在程序初始化时,配置好单片机的外设,包括时钟,GPIO口,定时器等。
2.心率检测:读取心率传感器的数据,通过波形处理等算法,
实时计算出心率值,然后将其显示在屏幕上。
3.数据存储:可以在单片机内部或外部添加存储芯片,将检测
到的数据保存下来,以方便后期分析。
同时,可以添加一个实时时
钟模块,记录下每次检测的时间。
4.操作界面:添加按键模块,实现心率计的开关、数据存储等
功能。
5.通信功能:可以添加一个蓝牙模块,将心率数据传输到手机
或其他设备上,以便进行分析和管理。
三、应用场景
基于单片机的心率计可以被广泛应用于医疗、运动等领域。
在
医疗领域,可以用于监测老年人、患病人士等人群的心率变化情况。
在运动领域,可以作为一款运动手环,记录运动者运动时的心率变
化情况。
同时,基于单片机的心率计也可以成为一种新颖的DIY硬
件项目,符合日益增长的Maker文化需求。
基于单片机心率计程序

#include <reg52.h>#include <intrins.h> // 包含头文件#define uint#define uchar#define ulong#define LCD_DATA unsigned intunsigned charunsigned longP0//宏定义//定义P0 口为LCD_DATAsbit LCD_RS =P2^5; sbit LCD_RW =P2^6;sbit LCD_E =P2^7;sbit Xintiao =P3^2 ; sbit speaker =P2^4;//定义LCD 控制引脚//脉搏检测输入端定义//蜂鸣器引脚定义void delay5ms(void); //误差0usvoid LCD_WriteData(uchar LCD_1602_DATA); void LCD_WriteCom(uchar LCD_1602_COM); ***********/ /********LCD1602 数据写入***********/ /********LCD1602 命令写入void lcd_1602_word(uchar Adress_Com,uchar Num_Adat,uchar *Adress_Data); /*1602字符显示函数,变量挨次为字符显示首地址,显示字符长度,所显示的字符*/void InitLcd();//液晶初始化函数void Tim_Init();uchar Xintiao_Change=0; //uint Xintiao_Jishu;uchar stop;uchar View_Data[3];uchar View_L[3];uchar View_H[3];uchar Xintiao_H=100; //脉搏上限uchar Xintiao_L=40; //脉搏下限uchar Key_Change;uchar Key_Value; uchar View_Con; uchar View_Change; //按键键值//设置的位(0 正常工作,1 设置上限,2 设置下限)void main(){//主函数InitLcd();Tim_Init();lcd_1602_word(0x80,16,"Heart Rate: "); //初始化显示TR0=1;TR1=1; //打开定时器while(1) //进入循环{if(Key_Change) //有按键按下并已经得出键值{Key_Change=0; //将按键使能变量清零,等待下次按键按下View_Change=1;switch(Key_Value) //判断键值{case 1:{View_Con++;if(View_Con==3)View_Con=0;break;}case 2:{if(View_Con==2)//设置键按下//设置的位加//都设置好后将此变量清零//跳出,下同//加键按下//判断是设置上限{if(Xintiao_H<150)Xintiao_H++;}if(View_Con==1){ //上限数值小于150 //上限+//如果是设置下限if(Xintiao_L<Xintiao_H-1)//下限值小于上限-1 (下限值不能超过上限)Xintiao_L++;}break;}case 3:{if(View_Con==2){ //下限值加//减键按下//设置上限if(Xintiao_H>Xintiao_L+1)//上限数据大于下限+1 (同样上限值不能小于下限)Xintiao_H--; //上限数据减}if(View_Con==1) //设置下限{if(Xintiao_L>30) //下限数据大于30 时Xintiao_L--;}break;}}//下限数据减}if(View_Change)// 显示变量{View_Change=0;//变量清零if(stop==0) //心率正常时{if(View_Data[0]==0x30) //最高位为0 时不显示View_Data[0]=' ';}else超过5s)不显示数据//心率不正常(计数超过5000,也就是两次信号时间{View_Data[0]=' ';View_Data[1]=' ';View_Data[2]=' ';}switch(View_Con){case 0: //正常显示{lcd_1602_word(0x80,16,"Heart Rate:lcd_1602_word(0xc0,16,"lcd_1602_word(0xcd,3,View_Data);break;}case 1: //设置下限时显示{lcd_1602_word(0x80,16,"Heart Rate:lcd_1602_word(0x8d,3,View_Data);View_L[0]=Xintiao_L/100+0x30;View_L[1]=Xintiao_L%100/10+0x30;View_L[2]=Xintiao_L%10+0x30;if(View_L[0]==0x30)View_L[0]=' ';lcd_1602_word(0xC0,16,"Warning L :lcd_1602_word(0xCd,3,View_L);");//显示一行数据");//显示第二行数据//第二行显示心率");//第一行显示心率//将下限数据拆字//最高位为0 时,不显示");//第二行显示下限数据break;}case 2: //设置上限时显示(同上){lcd_1602_word(0x80,16,"Heart Rate: ");lcd_1602_word(0x8d,3,View_Data);View_H[0]=Xintiao_H/100+0x30;View_H[1]=Xintiao_H%100/10+0x30;View_H[2]=Xintiao_H%10+0x30;if(View_H[0]==0x30)View_H[0]=' ';lcd_1602_word(0xC0,16,"Warning H : ");lcd_1602_word(0xCd,3,View_H);break;}}}}}void Time1() interrupt 3 //定时器1 服务函数{static uchar Key_Con,Xintiao_Con;TH1=0xd8; TL1=0xf0; switch(Key_Con) {case 0:{//10ms//重新赋初值//无按键按下时此值为0 //每10ms 扫描此处if((P1&0x07)!=0x07)//扫描按键是否有按下{Key_Con++;}break;}case 1:{ //有按下此值加1,值为1//10ms 后二次进入中断后扫描此处(Key_Con 为1)if((P1&0x07)!=0x07)//第二次进入中断时,按键仍然是按下 (起到按键延时去抖的作用){Key_Con++; //变量加1,值为2switch(P1&0x07) //判断是哪个按键按下{case 0x06:Key_Value=1;break; //判断好按键后将键值赋值给变量Key_Valuecase 0x05:Key_Value=2;break;case 0x03:Key_Value=3;break;}}else //如果10ms 时没有检测到按键按下(按下时间过短){Key_Con=0;}break;}case 2:{if((P1&0x07)==0x07){Key_Change=1;//变量清零,重新检测按键//20ms 后检测按键//检测按键是否还是按下状态//有按键按下使能变量, (此变量为1 时才会处理键值数据)Key_Con=0;}//变量清零,等待下次有按键按下break;}}switch (Xintiao_Con)//此处与上面按键的检测类似{case 0: //默认Xintiao_Con 是为0 的{if(!Xintiao)//每10ms (上面的定时器)检测一次脉搏是否有信号{Xintiao_Con++;//如果有信号,变量加一,程序就会往下走了}break;}case 1:{if(!Xintiao) //每过10ms 检测一下信号是否还存在{Xintiao_Con++;//存在就加一}else{Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测}break;}case 2:{if(!Xintiao){Xintiao_Con++;//存在就加一}else{Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测}break;}case 3:{if(!Xintiao){Xintiao_Con++;//存在就加一}else{Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测}break;}case 4:{if(Xintiao)//超过30ms 向来有信号,判定此次是脉搏信号,执行以下程序{if(Xintiao_Change==1)//心率计原理为检测两次脉冲间隔时间计算心率,变量Xintiao_Change 第一次脉冲时为0 的,所有走下面的else,第二次走这里{if(60000/Xintiao_Jishu>200){View_Data[0]='-';View_Data[1]='-';View_Data[2]='-';speaker=1; //不响}else{View_Data[0]=(60000/Xintiao_Jishu)/100+0x30; // 计算心跳并拆字显示:心跳计时是以10ms 为单位,两次心跳中间计数如果是100 次,也就是100*10ms=1000ms=1sView_Data[1]=(60000/Xintiao_Jishu)%100/10+0x30; // 那么计算出的一分钟(60s)心跳数就是:60*1000/ (100*10ms) =60 次其中60 是一分钟60s ,1000 是一秒有1000ms ,100 是计数值,10 是一次计数对应的时间是10msView_Data[2]=(60000/Xintiao_Jishu)%10+0x30; // 计算出的心跳数/100 得到心跳的百位,%100 是取余的,就是除以100 的余数,再除以10 就得到十位了,以此类推//0x30 的目的是得到对应数字的液晶显示码,数字0 对应的液晶显示码是0x30 ,1 是0x30+1,以此类推if(((60000/Xintiao_Jishu)>=Xintiao_H)||((60000/Xintiao_Jishu)<=Xintiao_L))//心率不在范围内报警speaker=0;elsespeaker=1; } //蜂鸣器响//不响View_Change=1;Xintiao_Jishu=0;Xintiao_Change=0;stop=0;}//计算出心率后启动显示//心跳计数清零//计算出心率后该变量清零,准备下次检测心率//计算出心率后stop 邈else//第一次脉冲时Xintiao_Change 为0{Xintiao_Jishu=0; //脉冲计时变量清零,开始计时Xintiao_Change=1;//Xintiao_Change 置1,准备第二次检测到脉冲时计算心率}Xintiao_Con=0;break;}}}}//清零,准备检测下一次脉冲/**定时器T0 工作函数**/void Time0() interrupt 1{TH0=0xfc; TL0=0x18; //1ms//重新赋初值Xintiao_Jishu++; //心跳计数加if(Xintiao_Jishu==5000)//心跳计数大于5000 {Xintiao_Jishu=0; View_Change=1; //数据清零//显示位置1Xintiao_Change=0; //置零,准备再次检测stop=1; //心跳计数超过5000 后说明心率不正常或者没有测出,stop 置1speaker=1; //关闭蜂鸣器}}/**定时器初始化函数**/void Tim_Init(){EA=1;ET0=1;ET1=1; TMOD=0x11; TH0=0xfc; TL0=0x18; //打开中断总开关//打开T0 中断允许开关//打开T1 中断允许开关//设定定时器状态//1ms//赋初值TH1=0xd8;TL1=0xf0; }//10ms //赋初值/**在指定地址显示指定数量的指定字符**//**Adress_Com 显示地址,Num_Adat 显示字符数量,Adress_Data 显示字符串内容**/ void lcd_1602_word(uchar Adress_Com,uchar Num_Adat,uchar *Adress_Data){uchar a=0;uchar Data_Word;LCD_WriteCom(Adress_Com); //选中地址for(a=0;a<Num_Adat;a++) //for 循环决定显示字符个数{Data_Word=*Adress_Data; //读取字符串数据LCD_WriteData(Data_Word); //显示字符串Adress_Data++; //显示地址加一}}/***************1602 函数*******************/void LCD_WriteData(uchar LCD_1602_DATA) /********LCD1602 数据写入***********/ {delay5ms(); //操作前短暂延时,保证信号稳定LCD_E=0;LCD_RS=1;LCD_RW=0;_nop_();LCD_E=1;LCD_DATA=LCD_1602_DATA;LCD_E=0;LCD_RS=0;}/********LCD1602 命令写入***********/void LCD_WriteCom(uchar LCD_1602_COM){delay5ms();//操作前短暂延时,保证信号稳定LCD_E=0;LCD_RS=0;LCD_RW=0;_nop_();LCD_E=1;LCD_DATA=LCD_1602_COM;LCD_E=0;LCD_RS=0;}void InitLcd() //初始化液晶函数{delay5ms();delay5ms();LCD_WriteCom(0x38); //display modeLCD_WriteCom(0x38); //display modeLCD_WriteCom(0x38); //display modeLCD_WriteCom(0x06); //显示光标挪移位置LCD_WriteCom(0x0c); //显示开及光标设置LCD_WriteCom(0x01); //显示清屏delay5ms();delay5ms();}void delay5ms(void) //5ms 延时函数{unsigned char a,b;for(b=185;b>0;b--)for(a=12;a>0;a--);}。
心率计51单片机代码.doc

while(t--);
}
}
void SMG_Display(unsigned int num)
{
SMG_ShowNum(num/1000);
P0 =0x08>>1;
delay_ms(2);
SMG_ShowNum((num%1000)/100);
P0 =0x08>>2;
delay_ms(2);
void Timer0_Init()
{
TMOD = 0x01;
TR0 = 1;//16位定时器工作方式
TH0 = T1MS>>8;
TL0 = T1MS;
ET0 = 1;//打开定时器0中断
EA = 1;//打开总中断
}
void Timer0_ISR() interrupt 1
{
unsigned int temp;
count++;
TH0 = T1MS>>8;
TL0 = T1MS;
if(count=5000)
temp=Xinlv;
for{}
SMG_Display(temp);
}
数码管部分代码
void HC595_send_byte(unsigned char byte)
{
unsigned char i,temp;
unsigned char seg[10] = {0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
sbit HC595_RST = P0^6;
sbit HC595_SCK = P0^4;
sbit HC595_RCK = P0^5;
基于单片机心率监测系统设计方案

一、实物描述:
二、功能描述:
本系统由STM32F103C8T6单片机主控模块、心率传感器模块、TFT屏显示模块、按键模块、蜂鸣器报警模块组成。
1、TFT液晶实时显示心率值。
2、TFT液晶实时显示采集到的的模拟信号的曲线图,直接显示心率变化曲线。
3、通过按键可以设置心率报警阈值,按键有设置按键、设置+、设置-,在设置情况下可以对设置值进行加减。
4、当前心率值超过设置阈值,蜂鸣器报警,同时显示心率值为红色;否则蜂鸣器不报警,心率值显示蓝色。
三、功能框图:
心率传感器模
块单片机
STM32F103C8T
6TFT屏显示模
块
报警模块
按键模块
四、代码描述:
打开程序主界面如下图所示,程序由各个子程序组成,通过在主函数mian中调用。
Main()函数中首先对各模块进行初始化显示
然后进行ADC读取,读取结果通过单片机处理在显示屏上显示
显示屏坐标绘制函数,用于绘制初始化界面
按键子程序,用于设置报警值,在主函数中调用。
基于单片机的心率设计

基于单片机的心率设计引言:心率是测量人体健康状况的重要指标之一,通过监测心率可以及时了解人体的健康状况,对心脑血管疾病的预防和治疗具有重要意义。
本文将基于单片机设计一款心率检测装置,实现心率的实时监测和数据的显示。
一、设计方案1.硬件部分:(2)单片机:选用性能稳定的单片机,如STM32系列单片机,通过单片机来控制心率传感器进行数据采集和处理。
(3)显示模块:选择一款合适的显示模块,如OLED模块或LCD模块,用于实时显示心率数据。
2.软件部分:(1)心率检测算法:设计心率检测算法,通过心率传感器采集到的数据进行心率计算,可以采用波峰检测算法或者傅里叶变换等方法进行心率的计算。
(2)数据处理与显示:通过单片机进行数据的处理和显示,将计算得到的心率数据实时显示在显示模块上,并可以设置报警阈值,当心率超过设定的阈值时进行报警。
二、系统设计及实现1.硬件设计:(1)搭建硬件电路:将心率传感器与单片机进行连接,连接时需要注意信号的保护和滤波,以提高数据的准确性和可靠性。
(2)连接显示模块:将显示模块与单片机进行连接,将计算得到的心率数据通过串口或者I2C总线传输到显示模块上进行显示。
2.软件设计:(1)初始化:进行单片机和心率传感器的初始化工作,配置相应的引脚和寄存器。
(2)数据采集:设置数据采集的频率和时长,通过心率传感器采集心率数据,并进行滤波和去噪处理。
(3)心率计算:采用波峰检测算法或者傅里叶变换等方法,对心率数据进行处理和计算,得到实时的心率数值。
(4)数据显示:将计算得到的心率数值通过串口或I2C传输到显示模块上进行显示。
(5)报警功能:设置心率的报警阈值,当心率超过设定的阈值时,通过蜂鸣器或者LED进行报警。
三、总结和展望本文基于单片机实现了心率检测装置的设计,通过心率传感器采集到的数据计算得到心率,并实时显示在显示模块上。
该装置具有实时性和准确性,并可以设置报警功能,以提醒用户注意心率异常。
基于51单片机的心率计设计

基于51单片机的心率计设计一、引言心率是反映心脏功能的重要指标之一,对于人体健康的监测具有重要意义。
本文将介绍一种基于51单片机的心率计设计方案,通过测量心电信号来实时监测心率变化,并将结果显示在液晶屏上。
二、硬件设计1. 传感器选择心电信号的采集是心率计设计的关键,常用的传感器有心电图传感器和心率带。
本设计选择心电图传感器作为采集装置,它能够直接测量心脏电活动,并将信号转化为模拟电压。
2. 信号放大与滤波由于心电信号较弱且容易受到干扰,需要对信号进行放大和滤波处理。
可以采用运算放大器进行信号放大,并通过滤波电路去除高频干扰和基线漂移。
3. 信号采样与转换经过放大和滤波处理的心电信号需要进行模数转换,将模拟信号转换为数字信号以便单片机处理。
可以选择12位的AD转换器进行采样,并通过SPI接口与单片机进行通信。
4. 单片机控制与显示选取51单片机作为控制核心,通过编程实现信号的采集、处理和显示功能。
使用GPIO口与AD转换器和液晶屏连接,通过串口通信实现与电脑的数据传输。
三、软件设计1. 信号采集与处理通过单片机的GPIO口实现对AD转换器的控制,进行心电信号的采集。
同时,通过软件滤波算法对信号进行滤波处理,去除噪声和干扰。
2. 心率计算心率的计算可以通过测量心跳的时间间隔来实现。
在信号处理过程中,可以设置一个阈值,当信号超过该阈值时,计数器加一。
根据连续心跳的次数和采样频率,可以计算出心率的值。
3. 数据显示与存储通过液晶屏显示心率的实时数值,并提供用户界面操作。
同时,可以通过串口将数据传输到电脑进行进一步的分析和存储。
四、实验结果与讨论本设计基于51单片机成功实现了心率计的功能。
通过实验验证,心率计能够准确地测量心率,并实时显示在液晶屏上。
通过与商用心率计进行对比,结果表明本设计具有较高的准确性和稳定性。
五、总结与展望本文介绍了一种基于51单片机的心率计设计方案。
通过对心电信号的采集、处理和显示,实现了心率的实时监测。
基于单片机的脉搏测量仪-程序代码

基于单片机的脉搏测量仪-程序代码#include "reg51.h"#define uint8 unsigned char#define uint16 unsigned int#define uchar unsigned char#define uint unsigned int#define TIMER0_HIGHT 0x3C //设置定时器0工作方式1自动装载初值,定时50ms,Fosc=12MHZ#define TIMER0_LOW 0xB0unsigned char keyin = 1; //按键输入bit starttest; //启动测脉搏标志unsigned int cnt10ms; //10ms计数器unsigned char cnt1s; //1秒计数器unsigned intPulsecnt; //脉搏次数,计数器unsigned char NowPulse; //现在测试脉搏的次数unsigned char OLDPulse; //上次测试脉搏的次数char DECPulse; //脉搏的次数差unsigned intPulsenum; //上次测试脉搏的次数unsigned char start=0; //unsigned intPulseTime; //10ms计数器unsigned int Pulse; //10ms计数器unsigned intZs=0; //指数unsigned int SUM=0; //3次脉搏之和unsigned char cnt1s=0; //1s计数器unsigned char cnt1s_flag=0; //1s标志unsigned char cnt10s=0;unsigned char cnt1s2=0; //1s计数器unsigned char cnt1s_flag2=0; //1s标志unsignedint cnt1s2_count=0;unsigned char START1=0;unsigned char Timeover=0;unsigned char PLSEover=0;voidInit_Extint(void);voidTimerInitProc();voidInit_System(void);void Display(uint8 chose_dat, uint8 dat);voidShowDisp(uint8 tPulsenum, uint8 tPulsecnt, uint8 tcnt1s);voidDelayMs(uint8 Ms);unsigned char Pulse_FLAG=0;unsigned char Pulse_5=0;unsigned char MODE_SET_OK=0;#define LCD_Data P0 //LCD的数据口sbit LCD_BF=LCD_Data^7; //LCD忙信号位sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_EN=P2^2;#define LCD_GO_HOME 0x02 //AC=0,光标、画面回HOME位//输入方式设置#define LCD_AC_AUTO_INCREMENT 0x06 //数据读、写操作后,AC自动增一#define LCD_AC_AUTO_DECREASE 0x04 //数据读、写操作后,AC自动减一#define LCD_MOVE_ENABLE 0x05 //数据读、写操作,画面平移#define LCD_MOVE_DISENABLE 0x04 //数据读、写操作,画面不动//设置显示、光标及闪烁开、关#define LCD_DISPLAY_ON 0x0C //显示开#define LCD_DISPLAY_OFF 0x08 //显示关#define LCD_CURSOR_ON 0x0A //光标显示#define LCD_CURSOR_OFF 0x08 //光标不显示#define LCD_CURSOR_BLINK_ON 0x09 //光标闪烁#define LCD_CURSOR_BLINK_OFF 0x08 //光标不闪烁//光标、画面移动,不影响DDRAM#define LCD_LEFT_MOVE 0x18 //LCD显示左移一位#define LCD_RIGHT_MOVE 0x1C //LCD显示右移一位#define LCD_CURSOR_LEFT_MOVE 0x10 //光标左移一位#define LCD_CURSOR_RIGHT_MOVE 0x14 //光标右移一位//工作方式设置#define LCD_DISPLAY_DOUBLE_LINE 0x38 //两行显示#define LCD_DISPLAY_SINGLE_LINE 0x30 //单行显示/*定义子程序*/void LCD_ClrAll(void); //清屏void Judge_LCD_busy(void); //检测是否忙碌void LCD_Write(ucharWriteData); //写控制字void LCD_write_data(ucharLCD_data); //写数据显示void LCD_cursor(uchar x); //光标起始地址void LCD_printc(unsigned char lcd_data) ; //输出一个字符void LCD_prints(unsigned char *lcd_string);//输出字符串/*LCD1602忙碌判断子程序*/void Judge_LCD_busy(void) //判断LCD1602是否忙状态{while(1){LCD_EN=0;LCD_RS=0;LCD_RW=1;LCD_Data=0xff;LCD_EN=1; //EN 是 1—0 使能if(!LCD_BF)break; //LCD_BF=1表示忙碌,需要等待。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <>#include <> // 包含头文件#define uint unsigned int#define uchar unsigned char#define ulong unsigned long //宏定义#define LCD_DATA P0 //定义P0口为LCD_DATAsbit LCD_RS =P2^5;sbit LCD_RW =P2^6;sbit LCD_E =P2^7; //定义LCD控制引脚sbit Xintiao =P3^2 ; //脉搏检测输入端定义sbit speaker =P2^4; //蜂鸣器引脚定义void delay5ms(void); //误差 0usvoid LCD_WriteData(uchar LCD_1602_DATA); /********LCD1602数据写入***********/void LCD_WriteCom(uchar LCD_1602_COM); /********LCD1602命令写入***********/void lcd_1602_word(uchar Adress_Com,uchar Num_Adat,uchar *Adress_Data); /*1602字符显示函数,变量依次为字符显示首地址,显示字符长度,所显示的字符*/void InitLcd();//液晶初始化函数void Tim_Init();uchar Xintiao_Change=0; //uint Xintiao_Jishu;uchar stop;uchar View_Data[3];uchar View_L[3];uchar View_H[3];uchar Xintiao_H=100; //脉搏上限uchar Xintiao_L=40; //脉搏下限uchar Key_Change;uchar Key_Value; //按键键值uchar View_Con; //设置的位(0正常工作,1设置上限,2设置下限)uchar View_Change;void main() //主函数{InitLcd();Tim_Init();lcd_1602_word(0x80,16,"Heart Rate: "); //初始化显示TR0=1;TR1=1; //打开定时器while(1) //进入循环{if(Key_Change) //有按键按下并已经得出键值{Key_Change=0; //将按键使能变量清零,等待下次按键按下View_Change=1;switch(Key_Value) //判断键值{case 1: //设置键按下{View_Con++; //设置的位加if(View_Con==3) //都设置好后将此变量清零View_Con=0;break; //跳出,下同}case 2: //加键按下{if(View_Con==2) //判断是设置上限{if(Xintiao_H<150) //上限数值小于150Xintiao_H++; //上限+}if(View_Con==1) //如果是设置下限{if(Xintiao_L<Xintiao_H-1)//下限值小于上限-1(下限值不能超过上限)Xintiao_L++; //下限值加}break;}case 3: //减键按下{if(View_Con==2) //设置上限{if(Xintiao_H>Xintiao_L+1)//上限数据大于下限+1(同样上限值不能小于下限)Xintiao_H--; //上限数据减}if(View_Con==1) //设置下限{if(Xintiao_L>30) //下限数据大于30时Xintiao_L--; //下限数据减}break;}}}if(View_Change)//显示变量{View_Change=0;//变量清零if(stop==0) //心率正常时{if(View_Data[0]==0x30) //最高位为0时不显示View_Data[0]=' ';}else //心率不正常(计数超过5000,也就是两次信号时间超过5s)不显示数据{View_Data[0]=' ';View_Data[1]=' ';View_Data[2]=' ';}switch(View_Con){case 0: //正常显示{lcd_1602_word(0x80,16,"Heart Rate: ");//显示一行数据lcd_1602_word(0xc0,16," ");//显示第二行数据lcd_1602_word(0xcd,3,View_Data); //第二行显示心率break;}case 1: //设置下限时显示{lcd_1602_word(0x80,16,"Heart Rate: ");//第一行显示心率lcd_1602_word(0x8d,3,View_Data);View_L[0]=Xintiao_L/100+0x30; //将下限数据拆字View_L[1]=Xintiao_L%100/10+0x30;View_L[2]=Xintiao_L%10+0x30;if(View_L[0]==0x30) //最高位为0时,不显示View_L[0]=' ';lcd_1602_word(0xC0,16,"Warning L : ");//第二行显示下限数据lcd_1602_word(0xCd,3,View_L);break;}case 2: //设置上限时显示(同上){lcd_1602_word(0x80,16,"Heart Rate: ");lcd_1602_word(0x8d,3,View_Data);View_H[0]=Xintiao_H/100+0x30;View_H[1]=Xintiao_H%100/10+0x30;View_H[2]=Xintiao_H%10+0x30;if(View_H[0]==0x30)View_H[0]=' ';lcd_1602_word(0xC0,16,"Warning H : ");lcd_1602_word(0xCd,3,View_H);break;}}}}}void Time1() interrupt 3 //定时器1服务函数{static uchar Key_Con,Xintiao_Con;TH1=0xd8; //10msTL1=0xf0; //重新赋初值switch(Key_Con) //无按键按下时此值为0{case 0: //每10ms扫描此处{if((P1&0x07)!=0x07)//扫描按键是否有按下{Key_Con++; //有按下此值加1,值为1}break;}case 1: //10ms后二次进入中断后扫描此处(Key_Con为1){if((P1&0x07)!=0x07)//第二次进入中断时,按键仍然是按下(起到按键延时去抖的作用){Key_Con++; //变量加1,值为2switch(P1&0x07) //判断是哪个按键按下{case 0x06:Key_Value=1;break; //判断好按键后将键值赋值给变量Key_Valuecase 0x05:Key_Value=2;break;case 0x03:Key_Value=3;break;}}else //如果10ms时没有检测到按键按下(按下时间过短){Key_Con=0; //变量清零,重新检测按键}break;}case 2: //20ms后检测按键{if((P1&0x07)==0x07) //检测按键是否还是按下状态{Key_Change=1; //有按键按下使能变量,(此变量为1时才会处理键值数据)Key_Con=0; //变量清零,等待下次有按键按下}break;}}switch (Xintiao_Con)//此处与上面按键的检测类似{case 0: //默认Xintiao_Con是为0的{if(!Xintiao)//每10ms(上面的定时器)检测一次脉搏是否有信号{Xintiao_Con++;//如果有信号,变量加一,程序就会往下走了}break;}case 1:{if(!Xintiao) //每过10ms检测一下信号是否还存在{Xintiao_Con++;//存在就加一}else{Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测}break;}case 2:{if(!Xintiao){Xintiao_Con++;//存在就加一}else{Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测}break;}case 3:{if(!Xintiao){Xintiao_Con++;//存在就加一}else{Xintiao_Con=0;//如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测}break;}case 4:{if(Xintiao)//超过30ms一直有信号,判定此次是脉搏信号,执行以下程序{if(Xintiao_Change==1)//心率计原理为检测两次脉冲间隔时间计算心率,变量Xintiao_Change第一次脉冲时为0的,所有走下面的else,第二次走这里{if(60000/Xintiao_Jishu>200){View_Data[0]='-';View_Data[1]='-';View_Data[2]='-';speaker=1; //不响}else{View_Data[0]=(60000/Xintiao_Jishu)/100+0x30;//计算心跳并拆字显示:心跳计时是以10ms为单位,两次心跳中间计数如果是100次,也就是100*10ms=1000ms=1sView_Data[1]=(60000/Xintiao_Jishu)%100/10+0x30; //那么计算出的一分钟(60s)心跳数就是:60*1000/(100*10ms)=60次其中60是一分钟60s,1000是一秒有1000ms,100是计数值,10是一次计数对应的时间是10msView_Data[2]=(60000/Xintiao_Jishu)%10+0x30; //计算出的心跳数/100得到心跳的百位,%100是取余的,就是除以100的余数,再除以10就得到十位了,以此类推//0x30的目的是得到对应数字的液晶显示码,数字0对应的液晶显示码是0x30,1是0x30+1,以此类推if(((60000/Xintiao_Jishu)>=Xintiao_H)||((60000/Xintiao_Jishu)<=Xintiao_L))/ /心率不在范围内报警speaker=0; //蜂鸣器响elsespeaker=1; //不响}View_Change=1; //计算出心率后启动显示Xintiao_Jishu=0; //心跳计数清零Xintiao_Change=0; //计算出心率后该变量清零,准备下次检测心率stop=0; //计算出心率后stop邈}else//第一次脉冲时Xintiao_Change为0{Xintiao_Jishu=0; //脉冲计时变量清零,开始计时Xintiao_Change=1;//Xintiao_Change置1,准备第二次检测到脉冲时计算心率}Xintiao_Con=0; //清零,准备检测下一次脉冲break;}}}}/**定时器T0工作函数**/void Time0() interrupt 1{TH0=0xfc; //1msTL0=0x18; //重新赋初值Xintiao_Jishu++; //心跳计数加if(Xintiao_Jishu==5000)//心跳计数大于5000{Xintiao_Jishu=0; //数据清零View_Change=1; //显示位置1Xintiao_Change=0; //置零,准备再次检测stop=1; //心跳计数超过5000后说明心率不正常或者没有测出,stop置1speaker=1; //关闭蜂鸣器}}/**定时器初始化函数**/void Tim_Init(){EA=1; //打开中断总开关ET0=1; //打开T0中断允许开关ET1=1; //打开T1中断允许开关TMOD=0x11; //设定定时器状态TH0=0xfc; //1msTL0=0x18; //赋初值TH1=0xd8; //10msTL1=0xf0; //赋初值}/**在指定地址显示指定数量的指定字符**//**Adress_Com显示地址,Num_Adat显示字符数量,Adress_Data显示字符串内容**/ void lcd_1602_word(uchar Adress_Com,uchar Num_Adat,uchar *Adress_Data){uchar a=0;uchar Data_Word;LCD_WriteCom(Adress_Com); //选中地址for(a=0;a<Num_Adat;a++) //for循环决定显示字符个数{Data_Word=*Adress_Data; //读取字符串数据LCD_WriteData(Data_Word); //显示字符串Adress_Data++; //显示地址加一}}/***************1602函数*******************/void LCD_WriteData(uchar LCD_1602_DATA) /********LCD1602数据写入***********/ {delay5ms(); //操作前短暂延时,保证信号稳定LCD_E=0;LCD_RS=1;LCD_RW=0;_nop_();LCD_E=1;LCD_DATA=LCD_1602_DATA;LCD_E=0;LCD_RS=0;}/********LCD1602命令写入***********/void LCD_WriteCom(uchar LCD_1602_COM){delay5ms();//操作前短暂延时,保证信号稳定LCD_E=0;LCD_RS=0;LCD_RW=0;_nop_();LCD_E=1;LCD_DATA=LCD_1602_COM;LCD_E=0;LCD_RS=0;}void InitLcd() //初始化液晶函数{delay5ms();delay5ms();LCD_WriteCom(0x38); //display modeLCD_WriteCom(0x38); //display modeLCD_WriteCom(0x38); //display modeLCD_WriteCom(0x06); //显示光标移动位置LCD_WriteCom(0x0c); //显示开及光标设置LCD_WriteCom(0x01); //显示清屏delay5ms();delay5ms();}void delay5ms(void) //5ms延时函数{unsigned char a,b;for(b=185;b>0;b--)for(a=12;a>0;a--);}。