基于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原理图、设计报告、流程图、结构框图、实物图、元件清单等。具体内容如下,全网最全! !

大家共同学习进步:
点赞分享一起学习成长。