基于51单片机心率仪—体温心率血氧蓝牙
基于51单片机心率仪
(程序+原理图+设计报告)
功能介绍
具体功能:
1.采用MKS-SPO2模块检测心率血氧,DS18B20测温;
2.LCD1602显示测得的心率、血氧浓度和温度;
3.按键可以设置心率上下限、血氧浓度的阈值;
4.当测得心率超出设定的范围或血氧浓度低于设定的阈值,蜂鸣器+LED声光报警;
5.数据通过蓝牙模块HC-06传给手机;
程序
#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; //写 0i=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 limitsspo2++;if(sspo2==200)sspo2=0;changgasset(sspo2);iapEraseSector(0x02000);iapProgramByte(0x02000,sspo2);delay(20);}if(selectnum==2){//lg limitshh++;if(shh==200)shh=0;changgasset(shh);iapEraseSector(0x02200);iapProgramByte(0x02200,shh);delay(20);}if(selectnum==3){//lg limitsll++;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 limitsspo2--;if(sspo2==0)sspo2=200;changgasset(sspo2);iapEraseSector(0x02000);iapProgramByte(0x02000,sspo2);delay(20);}if(selectnum==2){//lg limitshh--;if(shh==0)shh=200;changgasset(shh);iapEraseSector(0x02200);iapProgramByte(0x02200,shh);delay(20);}if(selectnum==3){//lg limitsll--;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 ucvrTI = 0;RI = 0;TR1=1;// timer 1 run //启动定时器1ES=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_INTSBUF=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原理图、设计报告、流程图、结构框图、实物图、元件清单等。具体内容如下,全网最全! !
大家共同学习进步:
点赞分享一起学习成长。