基于51单片机心率仪—体温心率血氧蓝牙

基于51单片机心率仪

(程序+原理图+设计报告)

功能介绍

具体功能:

1.采用MKS-SPO2模块检测心率血氧,DS18B20测温;

2.LCD1602显示测得的心率、血氧浓度和温度;

3.按键可以设置心率上下限、血氧浓度的阈值;

4.当测得心率超出设定的范围或血氧浓度低于设定的阈值,蜂鸣器+LED声光报警;

5.数据通过蓝牙模块HC-06传给手机;

程序

cs 复制代码
#include<reg52.h>
#include <intrins.h>
#include <stdio.h>
#include <stc89c52_eeprom.h>
#include"LCD1602.h"
#include"math.h"

#define	PAUSE_INT	EA=0;
#define	START_INT	EA=1;
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
sbit key_set=P1^3;
sbit up=P1^4;//定义key
sbit down=P1^5;//定义key
sbit ok=P1^6;//定义key
sbit alarm=P2^0;
sbit sensor=P3^6;     
sbit ds=P3^7;     //温度传感器信号线
uint temp,AlarmTemp;//定义温度值变量
uint q;
float f_temp;
ulong selectnum=0,select=0,vspo2=0,vhear=0;
//unsigned char date;
unsigned char time_buf2[4];//定义接收4个字节数组
unsigned char   Tx_Buf[12];
ulong Value,num=0;
unsigned char data1;
uchar a1=0,a2=0,a3=0,a4=0,a5=0,a6=0;
//uint Alarm_temp_up=35,Alarm_temp_low=10,Alarm_humidity_up=85,Alarm_humidity_low=20;
//uint	 Alarm_light_up=50,Alarm_light_down=10;

void UART_Init();
unsigned char Receive(void);
void Send(unsigned char back);
void	send_char_com(uchar ch);
void	send_string_com(uchar *str, uchar strlen);

void Init_Timer0(void);


long sspo2=50,shh=60,sll=120;
void delay1ms()//延时1ms函数
{
   unsigned char i,j;
	 for(i=0;i<10;i++)
	  for(j=0;j<33;j++)
	   ;
 }
 void delaynms(int n)//延时毫秒函数
 {
   unsigned char i;
	for(i=0;i<n;i++)
	   delay1ms();
}


/*****************************************************
函数名称:dsreset(void) 
函数功能:18B20复位,初始化函数
****************************************************/
void dsreset(void)    
{
  uint i;
  ds=0;
  i=103;
  while(i>0)i--;
  ds=1;
  i=4;
  while(i>0)i--;
}
/*****************************************************
函数名称:tempreadbit(void) 
函数功能:读1位函数
****************************************************/
bit tempreadbit(void)   
{
   uint i;
   bit dat;
   ds=0;i++;          //i++ 起延时作用
   ds=1;i++;i++;
   dat=ds;
   i=8;while(i>0)i--;
   return (dat);
}
/*****************************************************
函数名称:tempread(void) 
函数功能:读1个字节
****************************************************/
uchar tempread(void)  
{
  uchar i,j,dat;
  dat=0;
  for(i=1;i<=8;i++)
  {
    j=tempreadbit();
    dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好一个字节在DAT里
  }
  return(dat);
}
/*****************************************************
函数名称:tempwritebyte(uchar dat)
函数功能:向18B20写一个字节数据
****************************************************/
void tempwritebyte(uchar dat)   
{
  uint i;
  uchar j;
  bit testb;
  for(j=1;j<=8;j++)
  {
    testb=dat&0x01;
    dat=dat>>1;
    if(testb)     //写 1
    {
      ds=0;
      i++;i++;
      ds=1;
      i=8;while(i>0)i--;
    }
    else
    {
      ds=0;       //写 0
      i=8;while(i>0)i--;
      ds=1;
      i++;i++;
    }

  }
}
//完整资料
/***微信公众号:木子单片机****/
/*****************************************************
函数名称:tempchange(void)
函数功能:DS18B20 开始获取温度并转换
****************************************************/
void tempchange(void)  
{
  dsreset();
  delay(1);
  tempwritebyte(0xcc);  // 写跳过读ROM指令
  tempwritebyte(0x44);  // 写温度转换指令
}

uint get_temp()         //读取寄存器中存储的温度数据
{
  uchar a,b;
  dsreset();
  delay(1);
  tempwritebyte(0xcc);
  tempwritebyte(0xbe);
  a=tempread();         //读低8位
  b=tempread();         //读高8位
  temp=b;
  temp<<=8;            //两个字节组合为1个字
  temp=temp|a;
  f_temp=temp*0.0625;      //温度在寄存器中为12位 分辨率位0.0625°
  temp=f_temp;
  AlarmTemp=temp;
  temp=f_temp*10+0.5;    //如f_temp乘以10表示小数点后面只取1位,加0.5是四舍五入
  f_temp=f_temp+0.05; 

  return temp;        //temp是整型
}
void display_temp(int temp)
{
   uchar a,b,c;
   if(temp>=1000)temp=999;
     a=temp/100;//求百位
    b=temp%100/10;//求十位
    c=temp%100%10;//求个位
////////////////////////////////////
    LCDDispNum(10,1,a);
    LCDDispNum(11,1,b);
    LCDDispString(12,1,".");
    LCDDispNum(13,1,c);
		Tx_Buf[0]='T';						//帧头
	  	Tx_Buf[1]=a+0x30;		 	//将温湿度数据送往发送数组,送给蓝牙模块让手机APP显示
	  	Tx_Buf[2]=b+0x30;
	    Tx_Buf[3]='.';
	    Tx_Buf[4]=c+0x30;	
} 
void display_spo2hear()
{
	unsigned int a,b,c,d,e,f,g,e2,f2,g2;
	a=vspo2/1000;
	b=(vspo2%1000)/100;
	c=(vspo2%100)/10;
	d= vspo2%10; 
	LCDDispString(0,1,"SPO2:");
	LCDDispNum(5,1,b);			 				 
	LCDDispNum(6,1,c);	
	LCDDispNum(7,1,d);
	 Tx_Buf[5]=b+0x30; 
	 Tx_Buf[6]=c+0x30;
	 Tx_Buf[7]=d+0x30;
	            e=vhear/1000;
				f=(vhear%1000)/100;
				g=(vhear%100)/10;
				e2= vhear%10; 
				LCDDispString(0,2,"Hear:");
				LCDDispNum(5,2,f);			 				 
				LCDDispNum(6,2,g);
		        LCDDispNum(7,2,e2);
			    Tx_Buf[8]=f+0x30; 
	            Tx_Buf[9]=g+0x30;
	            Tx_Buf[10]=e2+0x30;
}
void changgasset(int temp)
{
    uchar d,e,f;
	
    d=temp/100;//求十位
    e=temp%100/10;//求个位
	 f=temp%100%10;
 	LCDDispNum(13,2,d);
    LCDDispNum(14,2,e); 
    LCDDispNum(15,2,f);
}
void Key_set_scan()
{


    if(key_set==0)
	{
		delay(10);
		if(key_set==0)
		{ 
			selectnum++;
			if(selectnum==1)
			{
			   LCDDispString(10,2,"SP:   ");
        	   changgasset(sspo2);
			}
			if(selectnum==2)
			{
               LCDDispString(10,2,"SH:   ");
        	   changgasset(shh);
			}
				if(selectnum==3)
			{
               LCDDispString(10,2,"SL:   ");
        	   changgasset(sll);
			}
	
			if(selectnum==4)
			{	   
			   LCDDispString(10,2,"      ");
			  selectnum=0; 

			}
		 	while(!key_set);//等待按键释放	
		}
	  
	}
	  ///////////////////////////

	if(up==0)//设置温度上限加键
	{  
		delay(10);
		if(up==0)
		{      
		    if(selectnum==1)
			{//gas limit
			   sspo2++;
         	  if(sspo2==200)sspo2=0;
			  changgasset(sspo2);
			  iapEraseSector(0x02000);
               iapProgramByte(0x02000,sspo2);
			   delay(20);
			}
			if(selectnum==2)
			{//lg limit
			   shh++;
         	  if(shh==200)shh=0;
			  changgasset(shh);
			  iapEraseSector(0x02200);
               iapProgramByte(0x02200,shh);
			   delay(20);
			}
				if(selectnum==3)
			{//lg limit
			   sll++;
         	  if(sll==200)sll=0;
			  changgasset(sll);
			  iapEraseSector(0x02400);
               iapProgramByte(0x02400,sll);
			   delay(20);
			}		
			 while(!up);//等待按键释放		 
		} 
	}
	/////////
	if(down==0)
	{  
		delay(10);
		if(down==0)
		{    
         	  if(selectnum==1)
			{//gas limit
			   sspo2--;
         	  if(sspo2==0)sspo2=200;
			  changgasset(sspo2);
			  iapEraseSector(0x02000);
               iapProgramByte(0x02000,sspo2);
			   delay(20);
			}
			if(selectnum==2)
			{//lg limit
			   shh--;
         	  if(shh==0)shh=200;
			  changgasset(shh);
			  iapEraseSector(0x02200);
               iapProgramByte(0x02200,shh);
			   delay(20);
			}
				if(selectnum==3)
			{//lg limit
			   sll--;
         	  if(sll==0)sll=200;
			  changgasset(sll);
			  iapEraseSector(0x02400);
               iapProgramByte(0x02400,sll);
			   delay(20);
			}
			 while(!down);//等待按键释放		 
		} 
	}

}
bit hearflag=1;
bit recflag=1;
bit spo2aflag=1;
void main(void)
{	 
    LCDInit(); //初始化LCD1602	
	LCDClear();//LCD1602显示清屏
    LCDDispString(0,1,"SPO2:");//液晶显示字符串 
	LCDDispString(0,2,"Hear:");
	LCDDispString(10,1,"36.2");
	LCDDispChar(14,1,0xdf);//液晶显示字符串.
    LCDDispString(15,1,"C");//液晶显示字符串C 
	UART_Init();//初始化串口通信
	  alarm=1;
//		  iapEraseSector(0x02000);
//               iapProgramByte(0x02000,95);
//			   delay(20);
//	  iapEraseSector(0x02200);
//               iapProgramByte(0x02200,120);
//			   delay(20);	  
//			    iapEraseSector(0x02400);
//               iapProgramByte(0x02400,60);
//			   delay(20);	
	sspo2=iapReadByte(0x02000);
	shh=iapReadByte(0x02200);
	sll=iapReadByte(0x02400);
    hearflag=1;recflag=1;
	while(1)
	{	   
	        tempchange();  //调用开始获取温度并转换函数
		    get_temp(); // 调用获取实际温度值函数
		    display_temp(temp); //调用显示温度值函数
			display_spo2hear();
			Key_set_scan();

                   if(recflag==0&&vhear>0)
				   {  
				      if(vhear>=sll&&vhear<=shh)
					  {
						hearflag=1;
					  }
					  else
					  {
					   hearflag=0;  
					  }
					 if(vspo2<sspo2)
					   {
					   spo2aflag=0;
					   }
					   else
					   {
					   spo2aflag=1;
					   }
					   recflag=1;
				   }
					  if(spo2aflag==0||temp>=375||hearflag==0||sensor==0)
					   {
					   alarm=0;
					   }
					   else
					   {
					   alarm=1;
					   }

			          if(sensor==0)
					   {
					   Tx_Buf[11]=0+0x30;
					   }
					   else
					   {
					    Tx_Buf[11]=1+0x30;
					   }
			send_string_com(Tx_Buf,12);
		    delay(1000);
	}
		
}
void UART_Init()     
{
    TMOD|=0x20;    //TMOD: timer 1, mode 2, 8-bit reload 
    TH1=0xfd;      //Baud:9600 fosc="11.0592"MHz 
    TL1=0xfd; 
    SCON|=0x50;    //SCON: serail mode 1, 8-bit UART, enable ucvr
    TI = 0;
    RI = 0;
    TR1=1;// timer 1 run //启动定时器1
    ES=1; //Enable Serial Interrupt 打开中断         
    EA=1; //打开所有中断
}

//串行中断服务程序,读取17个字节
void UART_SER (void) interrupt 4 
{
    unsigned char Temp;          //定义临时变量 

    unsigned char i;
    if(RI)                        //判断是接收中断产生
     {
	  RI=0;                      //标志位清零
	  Temp=SBUF;                 //读入缓冲区的值
	  time_buf2[i]=Temp;
	  i++;
	  if(i==4)                  //连续接收4个字符信息
	   {
	        i=0;
			if(time_buf2[0]==0XFF)
			{
			  //Send(time_buf2[1]);//	  xie yang
			  //Send(time_buf2[2]);//	 心率
			  
			  a1=(unsigned int)((time_buf2[1]/100)%10);
			  a2=(unsigned int)((time_buf2[1]/10)%10);
			  a3=(unsigned int)((time_buf2[1]/1)%10);
			    vspo2=a1*100+a2*10+a3;
			   					 
			


              a4=(unsigned int)((time_buf2[2]/100)%10);
		  	  a5=(unsigned int)((time_buf2[2]/10)%10);
			  a6=(unsigned int)((time_buf2[2]/1)%10);
			  vhear=a4*100+a5*10+a6;
			  recflag=0; 
		    
			}
			
						
	   }  
	 }
    if(TI)  //如果是发送标志位,清零
    TI=0;
}

void Send(unsigned char back)
{
   SBUF=back;
   while(TI==0)
      ;
    TI=0;
}
unsigned char Receive(void)
{
	unsigned long i = 10000;
	
	while( RI == 0 )
	{
		i--;
		if( i == 0 ) return -1;//
	}
	
	RI = 0;
	return SBUF;
}
//向串口发送一个字符 
void	send_char_com(uchar ch)  
{
	PAUSE_INT
    SBUF=ch;
    while(TI==0);
    TI=0;
	START_INT
}
//
//向串口发送一个字符串,strlen为该字符串长度 
void	send_string_com(uchar *str, uchar strlen)
{
    uchar k=0;
    do 
    {
        send_char_com(*(str+k));
        k=k+1;
    } while(k<strlen);

}

硬件设计

使用元器件:

单片机:STC89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

电源开关;DC座子;

9012三极管;蜂鸣器;

LCD1602液晶显示屏;

1.5K电阻;10K电阻;

30P电容;单片机座子;

DS18B20温度传感器;

心率血氧检测模块;

按键;10UF电容;

11.0592M晶振;

蓝牙模块;

导线:若干;

流程图:

设计资料

01原理图

本系统原理图采用Altium Designer19设计,具体如图!

02程序

本设计使用软件keil版本编程设计!具体如图!

03设计报告

一万两千字设计报告,具体如下!

04设计资料

全部资料包括程序(含注释)、AD原理图、设计报告、流程图、结构框图、实物图、元件清单等。具体内容如下,全网最全! !

​大家共同学习进步:

点赞分享一起学习成长。

相关推荐
济6172 小时前
FreeRTOS 通信任务设计(2)----UART+DMA 环形缓冲 + 空闲中断+ 流缓冲区--- 高效接收方案详解
stm32·单片机·嵌入式·freertos
千谦阙听2 小时前
数据结构最终章:万字详解排序算法!(内部排序)
c语言·数据结构·学习·算法·排序算法
QH139292318802 小时前
是德科技KEYSIGHT N5183B 9 kHz~40 GHz微波模拟信号发生器
网络·数据库·科技·嵌入式硬件·集成测试
W.W.H.2 小时前
嵌入式常见面试题——硬件与中断篇
经验分享·单片机·嵌入式硬件
灰子学技术2 小时前
Envoy 中 UDP 网络通信实现分析
网络·单片机·嵌入式硬件·网络协议·udp
念恒123063 小时前
Linux基础开发工具(Vim篇)
linux·c语言
三佛科技-187366133973 小时前
便携式一字美甲灯方案开发
单片机·嵌入式硬件
飞睿科技3 小时前
从 Mesh 到无线视频,ESP32-E22 的场景落地指南,飞睿科技乐鑫代理商
单片机·嵌入式硬件
念恒123063 小时前
Linux基础开发工具(yum篇)
linux·c语言