|
#include <reg52.h> #include <intrins.h> #include <stdio.h> #define uint unsigned int #define uchar unsigned char #define DASE 60000 // 定義 LM016L 引腳 sbit RS = P2^2; sbit RW = P2^1; sbit EN = P2^0; // 定義 DS18B20 引腳 sbit DQ = P1^4; // 定義心率引腳 sbit HeartRateSensor = P3^2; #define LCD_DATA P0 //定義蜂鳴器引腳 sbit BUZZER = P1^7; //溫度上下限設(shè)置 #define TEMP_lower 35 #define TEMP_higher 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); // 打開顯示,關(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); } /* // 修改復(fù)位函數(shù)使用精確延時(shí) bit ds18b20_reset(void) { bit presence; DQ = 0; delay_us(480); // 拉低至少 480us DQ = 1; delay_us(60); // 等待 15 - 60us presence = !DQ; delay_us(420); // 等待 480 - 960us return presence; } // 向 DS18B20 寫一個(gè)字節(jié) void ds18b20_write_byte(unsigned char dat) { unsigned char i; for (i = 0; i < 8; i++) { DQ = 0; _nop_(); DQ = dat & 0x01; delay_us(60); // 使用精確延時(shí)函數(shù) DQ = 1; dat >>= 1; } } // 從 DS18B20 讀一個(gè)字節(jié) unsigned char ds18b20_read_byte(void) { unsigned char i, dat = 0; for (i = 0; i < 8; i++) { DQ = 0; _nop_(); DQ = 1; _nop_(); if (DQ) { dat |= (1 << i); } delay_us(60); // 使用精確延時(shí)函數(shù) } return dat; } // 讀取 DS18B20 的溫度值 float ds18b20_read_temp(void) { unsigned char low_byte, high_byte; int temp_value; float temperature; int retry = 3; // 重試次數(shù) int reset_failure_count = 0; while (retry--) { if (ds18b20_reset()) { reset_failure_count++; continue; // 復(fù)位失敗,重試 } ds18b20_write_byte(0xCC); // 跳過 ROM 操作 ds18b20_write_byte(0x44); // 啟動(dòng)溫度轉(zhuǎn)換 delay_ms(750); // 等待轉(zhuǎn)換完成 low_byte = ds18b20_read_byte(); high_byte = ds18b20_read_byte(); temp_value = (high_byte << 8) | low_byte; temperature = (float)temp_value * 0.0625; return temperature; } }*/ 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)//寫時(shí)序 { uchar i=0; for(i=8;i>0;i--) { DQ=0; DQ=dat&0x01;//寫1,在15微秒內(nèi)拉低 delay(5);//寫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); } //void Read_Temperature()//讀取溫度函數(shù) float ds18b20_read_temp(void) { Init_DS18b20(); //初始化18b20 write_byte(0xcc);//跳過讀寫序列號(hào) write_byte(0x44);//啟動(dòng)溫度轉(zhuǎn)換 Init_DS18b20(); //初始化18b20 write_byte(0xCC);//跳過讀寫序列號(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ù),用于檢測心率脈沖 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; //開定時(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_higher) { BUZZER = 0; // 蜂鳴器響 delay_ms(500); // 響一段時(shí)間 BUZZER = 1; // 蜂鳴器停 delay_ms(500); // 停一段時(shí)間 } else { BUZZER = 1; // 溫度正常,關(guān)閉蜂鳴器 } } } } |
|