|
一、摘要
我們介紹的是一種基于單片機(jī)控制的數(shù)字溫度報警,本溫度系統(tǒng)具有多功能性,即可以當(dāng)數(shù)字溫度計使用,顯示當(dāng)前環(huán)境溫度,又可以作為報警器使用,設(shè)置報警溫度,當(dāng)溫度不在設(shè)置范圍內(nèi)時,可以報警,并采取措施使溫度下降。
該溫度報警系統(tǒng)控制器使用單片機(jī)AT89C51,測溫傳感器使DS18B20,用2位共陽極LED數(shù)碼管,實現(xiàn)溫度顯示,能準(zhǔn)確達(dá)到以上要求。
二、設(shè)計方案
1、方案一
由于本設(shè)計是測溫電路,可以使用熱敏電阻之類的器件利用其感溫效應(yīng),在將隨被測溫度變化的電壓或電流采集過來,進(jìn)行A/D轉(zhuǎn)換后,就可以用單片機(jī)進(jìn)行數(shù)據(jù)的處理,在顯示電路上,就可以將被測溫度顯示出來,這種設(shè)計需要用到A/D轉(zhuǎn)換電路,感溫電路比較麻煩。
2、 方案二
進(jìn)而考慮到用溫度傳感器,在單片機(jī)電路設(shè)計中,大多都是使用傳感器,所以這是非常容易想到的,所以可以采用一只溫度傳感器DS18B20,此傳感器,可以很容易直接讀取被測溫度值,進(jìn)行轉(zhuǎn)換,就可以滿足設(shè)計要求。
從以上兩種方案,很容易看出,采用方案二,電路比較簡單,軟件設(shè)計也比較簡單,故采用了方案二。
溫度報警系統(tǒng)電路設(shè)計總體設(shè)計方框圖如圖1所示
三、模塊功能分析
1、單片機(jī)主板電路
單片機(jī)AT89C51具有低電壓供電和體積小等特點,該模塊包括中央處理CPU -AT89C51、時鐘電路及復(fù)位電路;2、DS18B20溫度傳感器與單片機(jī)的接口電路
DS18B20溫度傳感器是美國DALLAS半導(dǎo)體公司最新推出的一種改進(jìn)型智能溫度傳感器,與傳統(tǒng)的熱敏電阻等測溫元件相比,它能直接讀出被測溫度,并且可根據(jù)實際要求通過簡單的編程實現(xiàn)9~12位的數(shù)字值讀數(shù)方式。
DS18B20是采用電源供電方式,此時DS18B20的1腳接地,2腳作為信號線,3腳接電源。
該電路完成了信號的采集、轉(zhuǎn)換和傳輸。
圖4
3、上下限報警調(diào)整電路
分別調(diào)整溫度的上下限報警設(shè)置,有“+“、”“-”、“確定”等鍵
圖5上下限報警調(diào)整電路
4、溫度顯示電路
顯示當(dāng)前測得的溫度,數(shù)碼管采用74LS247驅(qū)動
5、報警電路
當(dāng)環(huán)境溫度超過設(shè)定溫度時,蜂鳴器鳴叫,紅燈點亮,發(fā)生報警;當(dāng)人員發(fā)現(xiàn)警報時,可按圖8中的按鈕,暫時中斷蜂鳴器的鳴叫。6、控制電路
該電路的作用是:當(dāng)測量溫度超過設(shè)定溫度時,小風(fēng)扇以下轉(zhuǎn)動,加快儀器散熱,使溫度保持在設(shè)定溫度以下。
圖9控制電路
四、整體構(gòu)造及功能
整體電路圖如下:
實現(xiàn)的總體功能:
l 實現(xiàn)對環(huán)境溫度的測量和顯示
l 能通過按鍵設(shè)置報警溫度
l 溫度超過設(shè)置值時,產(chǎn)生光聲報警
l 報警同時系統(tǒng)自帶小風(fēng)扇轉(zhuǎn)動以降低溫度
主程序
主程序的主要功能是負(fù)責(zé)溫度的實時顯示、讀出并處理DS18B20的測量的當(dāng)前溫度值,溫度測量每1s進(jìn)行一次。這樣可以在一秒之內(nèi)測量一次被測溫度,其程序流程見下圖所示
附錄:
源程序
/*******************************************************************/
/*溫度報警器*/
/*******************************************************************/
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define Tube P0 //數(shù)碼管端口
#define Key P1 //鍵盤端口
sbit DQ = P1^4; //溫度傳感器DS18B20數(shù)據(jù)傳輸端
sbit BUZZER = P1^5; //蜂鳴器端口
sbit RUN = P1^6; //運行指示燈端口
sbit SET = P1^7; //設(shè)置指示燈端口
sbit Feng = P3^3; //風(fēng)扇端口
bit Status; //設(shè)置狀態(tài)標(biāo)志位
bit Warning; //警報標(biāo)志位
bit Int; //外部中斷標(biāo)志位
uchar OP1L; //原P1端低4位狀態(tài)
uchar NP1L; //現(xiàn)P1端低4位狀態(tài)
uchar FinT; //最終測得溫度
uchar LimT; //警報溫度下限
uchar Count; //定時器計數(shù)
/*******************************************************************/
#include"Delay.h"
#include"Display.h"
#include"Initialize.h"
#include"Error.h"
#include"KeyScan.h"
#include"Measure.h"
#include"Interrupt.h"
/*******************************************************************/
/*主程序*/
/*******************************************************************/
void main()
{
Initialize(); //初始化
do{ //開機(jī)自檢,跳過默認(rèn)初始的85℃
Measure();
}while( FinT == 0X55);
while(1){
KeyScan(); //鍵盤掃描
Measure(); //獲取測量溫度
Display(); //顯示
}
}
/*******************************************************************/
/*初始化*/
/*******************************************************************/
void Initialize()
{
Status = 0; //初始化設(shè)置狀態(tài)標(biāo)志位
Warning = 0; //初始化警報標(biāo)志位
BUZZER = 1; //初始化蜂鳴器狀態(tài)
RUN = 0; //初始化運行指示燈
SET = 1; //初始化設(shè)置指示燈
Feng = 1; //初始化風(fēng)扇端口
OP1L = 0X00; //初始化原P1低4位
NP1L = 0X00; //初始化新P1低4位
LimT = 0X1B; //初始化警報溫度下限為27℃
Count = 0X00; //初始化定時器計數(shù)單元
EA = 1; //開總中斷
EX0 = 1; //開外部中斷0中斷允許
IT0 = 1; //設(shè)置外部中斷0為邊沿觸發(fā)方式
}
/*******************************************************************/
/*溫度測量*/
/*******************************************************************/
void InitDS18B20(); //初始化DS18B20
void WriteDS18B20( uchar ch ); //寫DS18B20數(shù)據(jù)
uchar ReadDS18B20(); //讀DS18B20數(shù)據(jù)
void Measure()
{
uchar TemH; //保存?zhèn)鞲衅靼l(fā)送數(shù)據(jù)高8位
uchar TemL; //保存?zhèn)鞲衅靼l(fā)送數(shù)據(jù)低8位
InitDS18B20();
WriteDS18B20( 0XCC ); //跳過ROM
_nop_();
InitDS18B20();
WriteDS18B20( 0XCC ); //跳過ROM
_nop_();
WriteDS18B20( 0X44 ); //發(fā)送溫度轉(zhuǎn)換指令
Delay1ms( 25 );
Delay1ms( 25 );
Delay1ms(25 );
Delay1ms( 25 ); //等待1s轉(zhuǎn)換
InitDS18B20();
WriteDS18B20( 0XCC ); //跳過ROM
WriteDS18B20( 0XBE ); //發(fā)送溫度轉(zhuǎn)換指令
TemL = ReadDS18B20(); //讀低位溫度值
TemH = ReadDS18B20(); //讀高位溫度值
Delay1ms( 2 );
TemH = ( TemH<<4 )|( TemL>>4 ); //保留溫度值整數(shù)部分
FinT = TemH;
if( FinT > LimT ){ //判斷是否警報
Warning = 1;
}
else{
Warning = 0;
}
}
uchar ReadDS18B20() //讀DS18B20數(shù)據(jù)
{
uchar ch;
uchar q ;
for( q=0; q<8; q++ ){
ch = ch >> 1;
DQ = 0;
_nop_();
DQ = 1;
_nop_();
_nop_();
_nop_();
_nop_();
if( DQ == 1 ){
ch = ch | 0X80;
}
else{
ch = ch &0X7f;
}
Delay15us( 3 );
DQ = 1;
}
return( ch );
}
void WriteDS18B20( uchar ch ) //寫DS18B20數(shù)據(jù)
{
uchar i;
for( i=0; i<8; i++ )
{
DQ=0;
Delay15us( 1 );
DQ = ch & 0X01;
Delay15us( 3 );
DQ = 1;
ch = ch >> 1;
_nop_();
}
}
void InitDS18B20() //初始化DS18B20
{
DQ = 0;
Delay15us( 33 ); //至少延時480us
DQ = 1;
Delay15us( 10 ); //至少延時100us
}
/*******************************************************************/
/*顯示*/
/*******************************************************************/
void Display()
{
uchar T;
if( Status == 1 ){ //判斷狀態(tài)
T = LimT;
}
else{
T = FinT;
}
T = T % 10 + T / 10 *16; //將2進(jìn)制碼轉(zhuǎn)化為BCD碼
Tube = T; //數(shù)碼管顯示
RUN = Warning; //運行指示燈顯示
BUZZER = !Warning ||Int; //蜂鳴器
Feng = !Warning; //風(fēng)扇
SET = !Status; //設(shè)置指示燈顯示
Delay1ms( 20 );
}
/*******************************************************************/
/*鍵盤掃描*/
/*******************************************************************/
void KeyScan()
{
NP1L = Key; //讀取按鍵狀態(tài)
NP1L = NP1L &0X0F;
NP1L = NP1L ^ 0X0F;
if( NP1L != OP1L ){
switch(NP1L){ //判斷按鍵
case 0X01: //按鍵為“設(shè)置”
Status = 1; //進(jìn)入設(shè)置狀態(tài)
break;
case 0X02: //按鍵為“+1”
if( Status== 1){ //判斷是否為設(shè)置狀態(tài)
LimT++; //警報溫度下限+1
LimT =LimT % 100; //超過99清零
Delay1ms(255);
}
else{
Error();
}
break;
case 0X04: //按鍵為“-1”
if( Status== 1){ //判斷是否為設(shè)置狀態(tài)
LimT--; //警報溫度下限-1
if(LimT < 0 ){
LimT = 0X63; //低于0變?yōu)?9
}
Delay1ms(255);
}
else{
Error();
}
break;
case 0X08: //按鍵為“確認(rèn)”
Status = 0; //返回測溫狀態(tài)
break;
default: //多鍵按下
Error(); //出錯復(fù)位
break;
}
NP1L = 0X00; //重新初始化
}
}
/*******************************************************************/
/*中斷服務(wù)*/
/*******************************************************************/
void Int0( void ) interrupt 0
{
Int = 1; //外部中斷標(biāo)志位置1
EX0 = 0; //關(guān)外部中斷0中斷允許
TMOD = 0X01; //設(shè)置定時器0工作在模式1
TH0 = 0X3C;
TL0 = 0XB0; //為T0賦初值,令其定時50ms
Count = 0X3C; //設(shè)置計數(shù)次數(shù)
ET0 = 1; //開T0中斷允許
TR0 = 1; //開T0中斷
}
/*******************************************************************/
void Timer0( void ) interrupt1
{
if( Count == 0 ){ //判斷定時計數(shù)是否結(jié)束
ET0 = 0; //關(guān)T0中斷允許
TR0 = 0; //關(guān)T0中斷
Int = 0; //外部中斷標(biāo)志位置0
EX0 = 1; //開外部中斷0中斷允許
}
else{
TL0 = 0XB0; //重新賦T0初值
TH0 = 0X3C;
Count --; //定時計數(shù)減1
}
}
/*******************************************************************/
/*延遲函數(shù)*/
/*******************************************************************/
void Delay15us( uchar n ) //延遲n*15us
{
do{
_nop_(); _nop_();_nop_();
_nop_(); _nop_();_nop_();
_nop_(); _nop_();_nop_();
_nop_(); _nop_();_nop_();
_nop_();
n--;
}while( n );
}
void Delay1ms( uchar delay ) //延遲delay*1ms
{
uchar i;
while( delay-- )
{
for( i=0; i<124; i++);
}
}
/*******************************************************************/
/*報錯復(fù)位*/
/*******************************************************************/
void Error()
{
Tube = 0XAA; //出錯顯示
BUZZER = 0; //鳴蜂鳴器
RUN = 1; //LED警報
Delay1ms( 255 ); //延遲
Delay1ms( 255 );
Delay1ms( 255 );
Delay1ms( 255 );
Delay1ms( 255 );
( *(void(*)())0 )(); //軟復(fù)位
}
|
|