标题:
基于单片机的脉搏测量仪设计
[打印本页]
作者:
lqh_fairy
时间:
2021-5-12 19:32
标题:
基于单片机的脉搏测量仪设计
#include <reg52.h> //调用单片机头文件
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
#include <intrins.h>
#include "eeprom52.h"
sbit beep = P2^0; //蜂鸣器IO口定义
sbit k1 = P1^3;
sbit k2 = P1^4;
sbit k3 = P1^5;
bit flag_300ms ;
uchar flag_en;
uchar code table_num[]="0123456789abcdefg";
sbit rs=P1^0; //寄存器选择信号 H:数据寄存器 L:指令寄存器
sbit rw=P1^1; //寄存器选择信号 H:数据寄存器 L:指令寄存器
sbit e =P1^2; //片选信号 下降沿触发
char flag=0,bj=90;
unsigned char i=0,timecount=0,displayOK=0,aa=0;
float time[6]={0};
uint rate;
float rate1[6];
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;i++)
for(j=0;j<110;j++);
}
/********************************************************************
* 名称 : delay_uint()
* 功能 : 小延时。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay_uint(uint q)
{
while(q--);
}
/******************把数据保存到单片机内部eeprom中******************/
void write_eeprom()
{
SectorErase(0x2000);
byte_write(0x2000, bj % 256);
byte_write(0x2001, bj / 256);
byte_write(0x2058, a_a);
}
/******************把数据从单片机内部eeprom中读出来*****************/
void read_eeprom()
{
bj = byte_read(0x2001);
bj<<= 8;
bj |= byte_read(0x2000);
a_a = byte_read(0x2058);
}
/**************开机自检eeprom初始化*****************/
void init_eeprom()
{
read_eeprom(); //先读
if(a_a != 1) //新的单片机初始单片机内问eeprom
{
bj = 95;
a_a = 1;
write_eeprom(); //保存数据
}
}
/********************************************************************
* 名称 : write_com(uchar com)
* 功能 : 1602命令函数
* 输入 : 输入的命令值
* 输出 : 无
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_data(uchar dat)
* 功能 : 1602写数据函数
* 输入 : 需要写入1602的数据
* 输出 : 无
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名称 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
write_string(1,5,"ab cd ef;")
* 输入 : 行,列,需要输入1602的数据
* 输出 : 无
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
while(1)
{
if(*p == '\0') break;
write_data(*p);
p++;
}
}
/***********************lcd1602上显示特定的字符************************/
void write_zifu(uchar hang,uchar add,uchar date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(date);
}
/***********************lcd1602上显示两位十进制数************************/
void write_sfm3(uchar hang,uchar add,uint date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(0x30+date/100%10);
write_data(0x30+date/10%10);
write_data(0x30+date%10);
}
/***********************lcd1602上显示两位十进制数************************/
void write_sfm1(uchar hang,uchar add,uint date)
{
if(hang==1)
write_com(0x80+add);
else
write_com(0x80+0x40+add);
write_data(0x30+date%10);
}
/***********************lcd1602初始化设置************************/
void init_1602()
{
write_com(0x38); //设置显示模式
write_com(0x0c); //开显示不显示光标,光标不闪烁
write_com(0x06); //写一个数据,指针加1
delay_uint(1000);
write_string(1,0," Heart Rate ");
write_string(2,0," 000/min ");
}
/*************定时器0初始化程序***************/
void time_init()
{
EA = 1; //开总中断
TMOD = 0X01; //定时器0、定时器1工作方式1
ET0 = 1; //开定时器0中断
TR0 = 1; //允许定时器0定时
}
/***********外部中断0初始化程序****************/
void init_int0() //外部中断0初始化程序
{
EX0=1; //允许外部中断0中断
EA=1; //开总中断
IT0 = 1; //外部中断0负跳变中断
}
/************ 排序***************/
void pingjun_zhi(float *p)
{
static float value;
static uchar i,j;
for(j=1;j<5;j++) //先对整个数组的5个值进行从小到大的排列
for(i=0;i<5 - j;i++)
{
if(p[i] > p[i+1])
{
value = p[i];
p[i] = p[i+1];
p[i+1] = value;
}
}
}
void key()
{
if(k1==0)
{
while(k1==0);
flag++;
if(flag==2){flag=0;write_eeprom();}
if(flag==0)
{
write_string(1,0," Heart Rate ");
write_string(2,0," 000/min ");
}
if(flag==1)
{
write_string(1,0," set Rate ");
write_string(2,0," 000/min ");
}
}
if(flag==1)
{
if(k2==0)
{
while(k2==0);
if(bj<99)bj++;
}
if(k3==0)
{
while(k3==0);
if(bj>5) bj--;
}
}
}
uchar flag_value;
/****************主函数***************/
void main()
{
beep = 0; //开机叫一声
delay_1ms(150);
P0 = P1 = P2 = P3 = 0xff;
init_1602(); //1602初始化
time_init(); //初始化定时器
init_int0(); //外部中断0初始化程序
init_eeprom();
while(1)
{
key();
if(flag==0)
{
if(displayOK==0)//如果显示关
{
rate = 0;
flag_value = 0;
}
else//如果显示开
{
if(flag_en == 1)
{
flag_en = 0;
flag_value ++;
if(flag_value == 1)
rate1[0]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
if(flag_value == 2)
rate1[1]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
if(flag_value == 3)
rate1[2]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
if(flag_value == 4)
rate1[3]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
if(flag_value >= 5)
{
rate1[4]=60000/(time[1]/5+time[2]/5+time[3]/5+time[4]/5+time[5]/5);
pingjun_zhi(rate1);
flag_value = 0;
rate = (rate1[1] / 3 + rate1[2] / 3 + rate1[3] / 3);
}
}
}
write_sfm3(2,5,rate);
if(rate>bj)beep=0;
else beep=1;
}
if(flag==1)
{
write_sfm3(2,5,bj);
}
// write_sfm3(1,13,b1);
// write_sfm3(1,14,b2);
// write_sfm3(1,15,b3);
delay_1ms(300);
}
}
/************外部0中断服务程序***************/
void int0() interrupt 0
{
static uchar value;
EX0=0;//暂时关外部中断
if(timecount<8) //当连续两次检测时间间隔小于8*50ms=400ms不处理
{
value ++;
if(value >= 4)
{
value = 0;
// flag_value = 0;
}
TR0=1;//开定时器
}
else if(timecount <= 18)
{
value = 0;
time[i]=timecount*50+TH0*0.256+TL0/1000;//算出间隔时间
TH0 = 0x3c;
TL0 = 0xb0; // 50ms 12M
timecount=0;//50ms计数清零
i++;
flag_en = 1;
if(i==6)//记录到超过等于6次时间
{
i=1;//计数从1开始
displayOK=1; //测得5次开始显示?
}
} else
{
flag_value = 0;
timecount = 0;
}
EX0=1;
}
/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{
TH0 = 0x3c;
TL0 = 0xb0; // 50ms 12M
timecount++;//每50ms一次计数
if(timecount>70) //当超过25*50ms=1.5s没有检测到信号停止显示
{
i=0;//数据个数清零
timecount=0;//50ms计数清零
displayOK=0;//显示关
TR0=0;//定时器关
TH0 = 0x3c;
TL0 = 0xb0; // 50ms 12M
}
}
复制代码
系统总体设计由
STC89C52
、按键、
LCD1602
、光电传感器、时钟模块、运放等构成,系统设有四个按键,可以设置上下限脉搏数,当超过范围的时候单片机会驱动蜂鸣器发响,脉搏测量的时候需要人把手轻轻的按在光电传感器上面,由于人脉搏跳动的时候,血液的透光性不一样会导致接收器那边接收的信号强弱不一样,间接的把人脉搏信号传回,通过运放对其进行放大、整形后连接到单片机的
IO
口,单片机利用外部中断对其进行计数,最终换算成人一分钟脉搏的跳动次数,最终显示在液晶屏上。
作者:
safoji
时间:
2025-4-15 13:48
eeprom52.h 文件有吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1