基于51单片机的模拟心率电子脉搏器proteus仿真原理图PCB

功能介绍:
0.本系统采用STC89C52作为单片机
1.系统可检测心率脉搏值,通过LCD1602液晶实时显示测量值
2.心率脉搏超过设定阈值,蜂鸣器将报警
3.四个功能按键可修改心率脉搏上下限阈值
4.采用DC002作为电源接口可直接输入5V给整个系统供电
5.实物中采用两个红外对管模拟心率,可以方便演示心率脉搏的高低变化

原理图:

基于51单片机的模拟心率电子脉搏器proteus仿真原理图PCB_第1张图片

PCB :
基于51单片机的模拟心率电子脉搏器proteus仿真原理图PCB_第2张图片

主程序:

#include 
#include  //			 包含头文件

#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long //宏定义
#define LCD_DATA P0			//定义P0口为LCD_DATA

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

sbit HEART = P1^0; //脉搏检测输入端定义
sbit BUZZER = P2^4; //蜂鸣器引脚定义

void Delay5ms(void);													  
void LCD_WriteData(uchar LCD_1602_DATA);								  /********LCD1602数据写入***********/
void LCD_WriteCom(uchar LCD_1602_COM);									  /********LCD1602命令写入***********/
void LCD_DispWord(uchar Adress_Com, uchar Num_Adat, uchar *Adress_Data); /*1602字符显示函数,变量依次为字符显示首地址,显示字符长度,所显示的字符*/
void LCD_Init(); //初始化LCD
void TIM_Init(); //初始化定时器

uchar heartChange = 0; 
uint heartCnt;
uchar stopFlag;
uchar View_Data[3];
uchar View_L[3];
uchar View_H[3];
uchar heartH = 100; //脉搏上限
uchar heartL = 40;  //脉搏下限

uchar keyFlag;
uchar keyValue; //按键键值
uchar dispIndex;	 //设置的位(0正常工作,1设置上限,2设置下限)
uchar dispFlag;

void main() //主函数
{
	LCD_Init();
	TIM_Init();
	LCD_DispWord(0x80, 16, "Heart Rate:     "); //初始化显示
	TR0 = 1;
	TR1 = 1;  //打开定时器
	while (1) //进入循环
	{
		if (dispFlag) //开始显示变量
		{
			dispFlag = 0; //变量清零
			if (stopFlag == 0)	 //心率正常时
			{
				if (View_Data[0] == '0') //最高位为0时不显示
					View_Data[0] = ' ';
			}
			else //持续未检测到(计数超过5000,也就是两次信号时间超过5s)不显示数据
			{
				View_Data[0] = ' ';
				View_Data[1] = ' ';
				View_Data[2] = ' ';
			}

			switch (dispIndex)
			{
			case 0: //正常显示
			{
				LCD_DispWord(0x80, 16, "Heart Rate:     "); //显示一行数据
				LCD_DispWord(0xc0, 16, "                "); //显示第二行数据
				LCD_DispWord(0xcd, 3, View_Data);			 //第二行显示心率
				break;
			}
			case 1: //设置下限时显示
			{
				LCD_DispWord(0x80, 16, "Heart Rate:     "); //第一行显示心率
				LCD_DispWord(0x8d, 3, View_Data);

				View_L[0] = heartL / 100 + '0'; //将下限数据拆字
				View_L[1] = heartL % 100 / 10 + '0';
				View_L[2] = heartL % 10 + '0';

				if (View_L[0] == '0') //最高位为0时,不显示
					View_L[0] = ' ';

				LCD_DispWord(0xC0, 16, "Warning L :     "); //第二行显示下限数据
				LCD_DispWord(0xCd, 3, View_L);
				break;
			}
			case 2: //设置上限时显示(同上)
			{
				LCD_DispWord(0x80, 16, "Heart Rate:     ");
				LCD_DispWord(0x8d, 3, View_Data);

				View_H[0] = heartH / 100 + '0';
				View_H[1] = heartH % 100 / 10 + '0';
				View_H[2] = heartH % 10 + '0';

				if (View_H[0] == '0')
					View_H[0] = ' ';

				LCD_DispWord(0xC0, 16, "Warning H :     ");
				LCD_DispWord(0xCd, 3, View_H);
				break;
			}
			}
		}
		if (keyFlag) //有按键按下并已经得出键值
		{
			keyFlag = 0; //将按键使能变量清零,等待下次按键按下
			dispFlag = 1;
			switch (keyValue) //判断键值
			{
			case 1: //设置键按下
			{
				dispIndex++;		   //设置的位加
				if (dispIndex == 3) //都设置好后将此变量清零
					dispIndex = 0;
				break; //跳出,下同
			}
			case 2: //加键按下
			{
				if (dispIndex == 2) //判断是设置上限
				{
					if (heartH < 150) //上限数值小于150
						heartH++;	 //上限+
				}
				if (dispIndex == 1) //如果是设置下限
				{
					if (heartL < heartH - 1) //下限值小于上限-1(下限值不能超过上限)
						heartL++;			   //下限值加
				}
				break;
			}
			case 3: //减键按下
			{
				if (dispIndex == 2) //设置上限
				{
					if (heartH > heartL + 1) //上限数据大于下限+1(同样上限值不能小于下限)
						heartH--;			   //上限数据减
				}
				if (dispIndex == 1) //设置下限
				{
					if (heartL > 30) //下限数据大于30时
						heartL--;	//下限数据减
				}
				break;
			}
			}
		}
	}
}

void Time1() interrupt 3 //定时器1服务函数
{
	static uchar keyCon, heartDelay;
	TH1 = 0xDC;		//设置定时初始值
	TL1 = 0x00;		//设置定时初始值 10ms
	switch (keyCon) //无按键按下时此值为0
	{
	case 0: //每10ms扫描此处
	{
		if ((P3 & 0x07) != 0x07) //扫描按键是否有按下
		{
			keyCon++; //有按下此值加1,值为1
		}
		break;
	}
	case 1: // 10ms后二次进入中断后扫描此处(keyCon为1)
	{
		if ((P3 & 0x07) != 0x07) //第二次进入中断时,按键仍然是按下(起到按键延时去抖的作用)
		{
			keyCon++;		   //变量加1,值为2
			switch (P3 & 0x07) //判断是哪个按键按下
			{
			case 0x06:
				keyValue = 1;
				break; //判断好按键后将键值赋值给变量Key_Value
			case 0x05:
				keyValue = 2;
				break;
			case 0x03:
				keyValue = 3;
				break;
			}
		}
		else //如果10ms时没有检测到按键按下(按下时间过短)
		{
			keyCon = 0; //变量清零,重新检测按键
		}
		break;
	}
	case 2: // 20ms后检测按键
	{
		if ((P3 & 0x07) == 0x07) //检测按键是否还是按下状态
		{
			keyFlag = 1; //有按键按下使能变量,(此变量为1时才会处理键值数据)
			keyCon = 0;	//变量清零,等待下次有按键按下
		}
		break;
	}
	}

	switch (heartDelay) //此处与上面按键的检测类似
	{
	case 0: //默认heartDelay是为0的
	{
		if (!HEART) //每10ms(上面的定时器)检测一次脉搏是否有信号
		{
			heartDelay++; //如果有信号,变量加一,程序就会往下走了
		}
		break;
	}
	case 1:
	{
		if (!HEART) //每过10ms检测一下信号是否还存在
		{
			heartDelay++; //存在就加一
		}
		else
		{
			heartDelay = 0; //如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测
		}
		break;
	}
	case 2:
	{
		if (!HEART)
		{
			heartDelay++; //存在就加一
		}
		else
		{
			heartDelay = 0; //如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测
		}
		break;
	}
	case 3:
	{
		if (!HEART)
		{
			heartDelay++; //存在就加一
		}
		else
		{
			heartDelay = 0; //如果不存在了,检测时间很短,说明检测到的不是脉搏信号,可能是其他干扰,将变量清零,跳出此次检测
		}
		break;
	}
	case 4:
	{
		if (HEART) //超过30ms一直有信号,判定此次是脉搏信号,执行以下程序
		{
			if (heartChange == 1) //心率计原理为检测两次脉冲间隔时间计算心率,变量heartChange第一次脉冲时为0的,所有走下面的else,第二次走这里
			{
				View_Data[0] = (60000 / heartCnt) / 100 + '0';
				View_Data[1] = (60000 / heartCnt) % 100 / 10 + '0';
				View_Data[2] = (60000 / heartCnt) % 10 + '0';

				if (((60000 / heartCnt) >= heartH) || ((60000 / heartCnt) <= heartL)) //心率不在范围内报警
					BUZZER = 0;																	  //蜂鸣器响
				else
					BUZZER = 1; //不响

				dispFlag = 1;	//计算出心率后启动显示
				heartCnt = 0;	//心跳计数清零
				heartChange = 0; //计算出心率后该变量清零,准备下次检测心率
				stopFlag = 0;			//计算出心率后stop清零
			}
			else //第一次脉冲时heartChange为0
			{
				heartCnt = 0;	//脉冲计时变量清零,开始计时
				heartChange = 1; // heartChange置1,准备第二次检测到脉冲时计算心率
			}
			heartDelay = 0; //清零,准备检测下一次脉冲
			break;
		}
	}
	}
}

仿真演示视频:
https://www.bilibili.com/video/BV1oG411j7mz/

实物演示视频:
https://www.bilibili.com/video/BV1Qe4y1i7UU/

你可能感兴趣的:(51单片机,proteus,单片机)