標題:
基于單片機的脈搏測量儀設(shè)計
[打印本頁]
作者:
lqh_fairy
時間:
2021-5-12 19:32
標題:
基于單片機的脈搏測量儀設(shè)計
#include <reg52.h> //調(diào)用單片機頭文件
#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:數(shù)據(jù)寄存器 L:指令寄存器
sbit rw=P1^1; //寄存器選擇信號 H:數(shù)據(jù)寄存器 L:指令寄存器
sbit e =P1^2; //片選信號 下降沿觸發(fā)
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延時函數(shù)*****************************/
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--);
}
/******************把數(shù)據(jù)保存到單片機內(nèi)部eeprom中******************/
void write_eeprom()
{
SectorErase(0x2000);
byte_write(0x2000, bj % 256);
byte_write(0x2001, bj / 256);
byte_write(0x2058, a_a);
}
/******************把數(shù)據(jù)從單片機內(nèi)部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) //新的單片機初始單片機內(nèi)問eeprom
{
bj = 95;
a_a = 1;
write_eeprom(); //保存數(shù)據(jù)
}
}
/********************************************************************
* 名稱 : write_com(uchar com)
* 功能 : 1602命令函數(shù)
* 輸入 : 輸入的命令值
* 輸出 : 無
***********************************************************************/
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寫數(shù)據(jù)函數(shù)
* 輸入 : 需要寫入1602的數(shù)據(jù)
* 輸出 : 無
***********************************************************************/
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" ,調(diào)用該函數(shù)如下
write_string(1,5,"ab cd ef;")
* 輸入 : 行,列,需要輸入1602的數(shù)據(jù)
* 輸出 : 無
***********************************************************************/
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上顯示兩位十進制數(shù)************************/
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上顯示兩位十進制數(shù)************************/
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初始化設(shè)置************************/
void init_1602()
{
write_com(0x38); //設(shè)置顯示模式
write_com(0x0c); //開顯示不顯示光標,光標不閃爍
write_com(0x06); //寫一個數(shù)據(jù),指針加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++) //先對整個數(shù)組的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;
/****************主函數(shù)***************/
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)//如果顯示關(guān)
{
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中斷服務(wù)程序***************/
void int0() interrupt 0
{
static uchar value;
EX0=0;//暫時關(guān)外部中斷
if(timecount<8) //當連續(xù)兩次檢測時間間隔小于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計數(shù)清零
i++;
flag_en = 1;
if(i==6)//記錄到超過等于6次時間
{
i=1;//計數(shù)從1開始
displayOK=1; //測得5次開始顯示?
}
} else
{
flag_value = 0;
timecount = 0;
}
EX0=1;
}
/*************定時器0中斷服務(wù)程序***************/
void time0_int() interrupt 1
{
TH0 = 0x3c;
TL0 = 0xb0; // 50ms 12M
timecount++;//每50ms一次計數(shù)
if(timecount>70) //當超過25*50ms=1.5s沒有檢測到信號停止顯示
{
i=0;//數(shù)據(jù)個數(shù)清零
timecount=0;//50ms計數(shù)清零
displayOK=0;//顯示關(guān)
TR0=0;//定時器關(guān)
TH0 = 0x3c;
TL0 = 0xb0; // 50ms 12M
}
}
復(fù)制代碼
系統(tǒng)總體設(shè)計由
STC89C52
、按鍵、
LCD1602
、光電傳感器、時鐘模塊、運放等構(gòu)成,系統(tǒng)設(shè)有四個按鍵,可以設(shè)置上下限脈搏數(shù),當超過范圍的時候單片機會驅(qū)動蜂鳴器發(fā)響,脈搏測量的時候需要人把手輕輕的按在光電傳感器上面,由于人脈搏跳動的時候,血液的透光性不一樣會導(dǎo)致接收器那邊接收的信號強弱不一樣,間接的把人脈搏信號傳回,通過運放對其進行放大、整形后連接到單片機的
IO
口,單片機利用外部中斷對其進行計數(shù),最終換算成人一分鐘脈搏的跳動次數(shù),最終顯示在液晶屏上。
作者:
safoji
時間:
2025-4-15 13:48
eeprom52.h 文件有嗎
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1