|
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#define uint unsigned int
#define uchar unsigned char
#define DASE 60000
// 定義 LM016L 引腳
sbit RS = P2^7;
sbit RW = P2^6;
sbit EN = P2^5;
// 定義 DS18B20 引腳
sbit DQ = P1^0;
// 定義心率引腳
sbit HeartRateSensor = P3^3;
#define LCD_DATA P0
// 定義蜂鳴器引腳
sbit BUZZER = P1^7;
// 定義MAX30102的SDA引腳
sbit SDA = P3^4;
sbit INT = P3^2;
// 溫度上下限設(shè)置
#define TEMP_LOWER 35
#define TEMP_UPPER 40
// 函數(shù)聲明
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);
void lcd_init();
void lcd_command(unsigned char cmd);
void lcd_data(unsigned char dat);
void lcd_string(const char *str);
void display_heart_rate(unsigned int heart_rate);
void display_temperature(float temperature);
// DS18B20 相關(guān)函數(shù)聲明
bit ds18b20_reset(void);
void ds18b20_write_byte(unsigned char dat);
unsigned char ds18b20_read_byte(void);
float ds18b20_read_temp(void);
uint D_num; // 定時(shí)器中斷計(jì)數(shù)變量
// 聲明 str 數(shù)組為全局變量
static unsigned char str[10];
// 全局變量用于心率計(jì)算
unsigned int pulse_count = 0;
unsigned int prev_pulse_count = 0;
unsigned int heart_rate = 0;
uint temp; // 臨時(shí)變量
uint count; // 計(jì)數(shù)
float tempF;
bit flag_S = 0;
// 定時(shí)器0初始化函數(shù)
void InitTimer0(void)
{
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x18;
EA = 1;
ET0 = 1;
TR0 = 1;
}
void delay_ms(unsigned int ms) // @12MHz
{
unsigned i, j;
for (i = ms; i > 0; i--)
for (j = 120; j > 0; j--);
}
// 初始化 LCD
void lcd_init()
{
delay_ms(15);
lcd_command(0x38); // 設(shè)置 16x2 顯示,5x7 點(diǎn)陣,8 位數(shù)據(jù)
delay_ms(5);
lcd_command(0x38);
delay_ms(5);
lcd_command(0x38);
lcd_command(0x0C); // 打開(kāi)顯示,關(guān)閉光標(biāo)
lcd_command(0x06); // 光標(biāo)右移,字符不移動(dòng)
lcd_command(0x01); // 清屏
delay_ms(5);
}
// 發(fā)送 LCD 命令
void lcd_command(unsigned char cmd)
{
RS = 0;
RW = 0;
LCD_DATA = cmd;
delay_ms(1);
EN = 1;
_nop_();
EN = 0;
}
// 發(fā)送 LCD 數(shù)據(jù)
void lcd_data(unsigned char dat)
{
RS = 1;
RW = 0;
LCD_DATA = dat;
delay_ms(1);
EN = 1;
_nop_();
EN = 0;
}
// 發(fā)送字符串到 LCD
void lcd_string(const char *str)
{
while (*str)
{
lcd_data(*str++);
}
}
// 顯示心率
void display_heart_rate(unsigned int heart_rate)
{
lcd_command(0x87); // 設(shè)置顯示位置
sprintf(str, "%d bpm ", heart_rate);
lcd_string(str);
}
// 顯示溫度
void display_temperature(float temperature)
{
lcd_command(0xC7); // 設(shè)置顯示位置
if (temperature == -1)
{
sprintf(str, "Err");
}
else
{
sprintf(str, "%.1f C", temperature);
}
lcd_string((const char *)str);
}
void delay(uint t) // @12T 1us
{
while (t--);
}
void Init_DS18b20() // 18b20初始化函數(shù)
{
DQ = 1; // DQ復(fù)位
delay(8);
DQ = 0; // 釋放DQ
delay(80); // DS18B20收到信號(hào)后延時(shí)
DQ = 1; // 讀取DQ
delay(30);
}
void write_byte(uchar dat) // 寫(xiě)時(shí)序
{
uchar i = 0;
for (i = 8; i > 0; i--)
{
DQ = 0;
DQ = dat & 0x01; // 寫(xiě)1,在15微秒內(nèi)拉低
delay(5); // 寫(xiě)0,拉低60微秒
DQ = 1;
dat >>= 1;
}
delay(4);
}
uchar read_byte() // 讀時(shí)序
{
uchar i = 0;
uchar dat = 0;
for (i = 8; i > 0; i--)
{
DQ = 0; // 拉低ds18b20單總線
dat >>= 1;
DQ = 1; // 15微秒內(nèi)拉釋放總線
if (DQ)
dat |= 0x80;
delay(4);
}
return (dat);
}
float ds18b20_read_temp(void)
{
Init_DS18b20(); // 初始化18b20
write_byte(0xcc); // 跳過(guò)讀寫(xiě)序列號(hào)
write_byte(0x44); // 啟動(dòng)溫度轉(zhuǎn)換
Init_DS18b20(); // 初始化18b20
write_byte(0xCC); // 跳過(guò)讀寫(xiě)序列號(hào)
write_byte(0xBE); // 讀溫度寄存器
temp = read_byte(); // 讀取溫度低8位
temp = read_byte() << 8 | temp; // 讀取溫度高8位
tempF = temp * 0.0625;
return tempF;
}
void Timer0Interrupt() interrupt 1
{
static uint i;
TH0 = 0xFC;
TL0 = 0x18;
count++;
i++;
if (i >= 500) // 0.5秒
{
i = 0;
flag_S = 1; // 0.5秒標(biāo)志
}
}
// 外部中斷 0 服務(wù)函數(shù),用于檢測(cè)心率脈沖
void External0_ISR() interrupt 0
{
TR0 = 0; // 關(guān)定時(shí)器0
D_num = count; // 讀取定時(shí)器1ms中斷計(jì)數(shù)值
count = 0; // 定時(shí)器1ms中斷計(jì)數(shù)值清0
TH0 = 0xFC;
TL0 = 0x18;
TR0 = 1; // 開(kāi)定時(shí)器0
}
// 主程序
void main()
{
float temperature = 0.0;
unsigned int time_count = 0;
// 初始化 LCD
lcd_init();
lcd_string("Heart: ");
lcd_command(0xC0); // 第二行
lcd_string("Temp: ");
InitTimer0();
// 初始化外部中斷 0
IT0 = 1; // 下降沿觸發(fā)
EX0 = 1; // 使能外部中斷 0
EA = 1; // 使能全局中斷
IE0 = 0; // INT0中斷請(qǐng)求標(biāo)志清0
while (1)
{
if (flag_S) // 0.5秒
{
flag_S = 0;
heart_rate = DASE / D_num; // 計(jì)算心率
display_heart_rate(heart_rate);
// 獲取溫度
temperature = ds18b20_read_temp();
display_temperature(temperature);
// 溫度報(bào)警檢查
if (temperature < TEMP_LOWER || temperature > TEMP_UPPER)
{
BUZZER = 0; // 蜂鳴器響
delay_ms(500); // 響一段時(shí)間
}
else
{
BUZZER = 1; // 溫度正常,關(guān)閉蜂鳴器
}
}
}
} |
|