?? 溫度傳感器程序.txt
字號:
/*=============================================
溫度控制器
廣州工程職業(yè)技術學院
傳感器課程設計
指導老師: 馮偉
作者: GIT-3408-YOUJJYY (方暢,曹文榮,梁銳權)
時間: 2007-4-25
溫度傳感器用單總線DS18B20
CPU為AT89S52,三個按鍵(UP,DOWN,SET)
溫度調節(jié)上限為125度,下限為-55度(本程序只能用于單只18B20)
================================================*/
#include <at89x52.h>
#include <intrins.h>
#include <main_led_display.h>
/*--------用于按鍵可位尋址的狀態(tài)寄存器-----------*/
static unsigned char bdata StateREG;
sbit DS1820ON=StateREG^0; //DS18B20是否存在
sbit SetTF=StateREG^1; //是否是在溫度設置狀態(tài)
sbit KeySETDown=StateREG^2; //"1"為已按過SET鍵,"0"為沒按過SET按
sbit PowTF=StateREG^3; //電源標識("0"為開電源,"1"為關電源)
sbit KeyTF=StateREG^4; //"0"為按鍵允許,"1"為不允許
sbit KeySETDowning=StateREG^5; //SET是否正在按下
sbit LEDTF=StateREG^6; //開機LOG標志位
static unsigned char bdata TLV _at_ 0x0029; //溫度變量高低位
static unsigned char bdata THV _at_ 0x0028;
static signed char TMV; //轉換后的溫度值
static unsigned char KeyV,TempKeyV; //鍵值
static signed char TMRomV _at_ 0x0027; //高溫度限制
static signed char TMSetV _at_ 0x0026; //溫度設定值
static unsigned char KSDNum; //SET鍵連按時的采集次數(shù)
static unsigned char IntNum,IntNum2,IntNum3;//中斷發(fā)生次數(shù)(IntNum用于SET長按檢測,IntNum2用于設定狀態(tài)時LED閃爍,IntNum用于連按其他鍵)
static unsigned int IntNum4,IntNum5;
static signed char Sign; //負號標識
static unsigned char LED_One,LED_Two,LED_Three;
/*------------------------------------------
數(shù)值轉換
-------------------------------------------*/
void V2ToV(void)
{
TLV>>=4;
THV<<=4; //讀出的高低位數(shù)值移位
TMV=TLV|THV; //合并高低位放入TM為實際溫度值
Sign=0;
if(SetTF||!Key_SET)Sign=TMSetV>>7; //取符號
else Sign=TMV>>7;
if(Sign)
{
if(SetTF||!Key_SET)
{
LED_One=(~(TMSetV-1))/100; //SET狀態(tài)下顯示設定值
LED_Two=((~(TMSetV-1))-LED_One*100)/10;
LED_Three=(~(TMSetV-1))-LED_One*100-LED_Two*10;
}
else
{
LED_One=(~(TMV-1))/100; //轉換百位數(shù)值
LED_Two=((~(TMV-1))-LED_One*100)/10;
LED_Three=(~(TMV-1))-LED_One*100-LED_Two*10;
}
}
else
{
if(SetTF||!Key_SET)
{
LED_One=TMSetV/100; //SET狀態(tài)下顯示設定值
LED_Two=(TMSetV-LED_One*100)/10;
LED_Three=TMSetV-LED_One*100-LED_Two*10;
}
else
{
LED_One=TMV/100; //轉換百位數(shù)值
LED_Two=(TMV-LED_One*100)/10;
LED_Three=TMV-LED_One*100-LED_Two*10;
}
}
//=================轉換LED字段==================
if(LED_One)LED_Two=BCD_ASCII[LED_Two+1]; //超過百時十位的處理
else
{
if(LED_Two==0)LED_Two=BCD_ASCII[0];
else LED_Two=BCD_ASCII[LED_Two+1];
}
if(Sign)LED_One=0xf7;
else
{
if(LED_One==0)LED_One=BCD_ASCII[0];
else LED_One=BCD_ASCII[LED_One+1];
}
LED_Three=BCD_ASCII[LED_Three+1];
}
/*-------------------------------------------
初始化DS1820
--------------------------------------------*/
void InitDS1820(void)
{
TMPort=1;
_nop_();
TMPort=0;
Delay_6n5_8us(77); //延時 DS1820復位時間要500US的抵電平
TMPort=1;
Delay_6n5_8us(16); //延時112US 等待DS1820的回應
if(!TMPort){DS1820ON=1;ON_DS1820=1;} //檢測是否有DS1820
else {DS1820ON=0;ON_DS1820=0;}
Delay_6n5_8us(55);
TMPort=1;
}
/*------------------寫數(shù)據(jù)-------------------*/
void Write_Data(uchar T_DATA)
{
uchar i,DATA_T;
DATA_T=T_DATA;
for(i=0;i<=7;i++)
{
TMPort=0;
Delay_6n5_8us(1); //延時14微秒
if(DATA_T&0x01)TMPort=1;
else TMPort=0;
DATA_T>>=1;
Delay_6n5_8us(7); //延時54微秒
TMPort=1;
_nop_();
}
TMPort=1;
}
/*--------------------------------------------
寫入溫度限制值
發(fā)出4EH寫ROM指令后連發(fā)兩個字節(jié)
---------------------------------------------*/
void WriteDS1820(void)
{
uchar TM_H,TM_L;
TM_H>>=4;
TM_L<<=4;
Write_Data(TM_H);
Write_Data(TM_L);
}
/*-----------------讀數(shù)據(jù)-------------------*/
uchar ReadTM(void)
{
uchar i,TM_DATA;
for(i=0;i<=7;i++)
{
TM_DATA>>=1;
TMPort=1;
_nop_();_nop_();
TMPort=0;
_nop_();_nop_();_nop_();
TMPort=1;
Delay_6n5_8us(1);
if(TMPort)TM_DATA|=0x80;
Delay_6n5_8us(6);
}
return (TM_DATA);
}
/*-------------------------------------------
讀出溫度值
將溫度高位和低位,高溫度限制位從DS1820中讀出
低位存入29H(TEMPER_L),
高位存入28H(TEMPER_H),
高溫度限制位存入27H(TMRomV)
---------------------------------------------*/
void ReadDS1820(void)
{
TLV=ReadTM();
THV=ReadTM();
TMRomV=ReadTM();
}
/*====================主程序===================*/
void main(void)
{
StateREG=0; //初始化變量
SetTF=1; //在設置溫度狀態(tài)
PowTF=1; //關電源
THV=0; //溫度數(shù)據(jù)存儲(高地址:0x0028,低地址:0x0029) TLV=0;
TMV=0; //轉換后的溫度值
KeyV=0;
KSDNum=0; //SET鍵連按時的采集次數(shù)
IntNum=0; //用于SET長按檢測
IntNum2=0; //用于設定狀態(tài)時LED閃爍
IntNum3=0;
LED_One=0;
LED_Two=0;
Beep=1;
LEDTF=0;
InitDS1820();//初始化
Write_Data(0xcc);//跳過ROM
Write_Data(0xb8);//E2RAM中的溫度上限值調入RAM
InitDS1820();
Write_Data(0xcc);//跳過ROM
Write_Data(0xbe);//讀出溫度指令
ReadDS1820();//讀出溫度值和上限值
TMSetV=TMRomV;//拷貝保存在DS1820ROM里的上限值到TMSet
EA=1; //允許CPU中斷
ET0=1; //定時器0中斷開
TMOD=0x01; //設定時器0為模式1,16位模式
TH0=0XB1;
TL0=0XDF; //設定時值為20MS
TR0=1; //開定時
while(1);
}
/*----------------------------------
定時器0中斷處理中鍵掃描和顯示
------------------------------------*/
void KeyAndDis_Time0(void) interrupt 1 using 2
{
TH0=0XB1;
TL0=0XDF; //設定時值為20MS
LEDPort=0xff; //關閉LED
/*--------------對按下的鍵值附值-------------*/
if(!Key_UP)KeyV=1; //檢測Key_UP是否按下
if(!Key_DOWN)KeyV=2; //檢測Key_DOWN是否按下
if(!Key_SET)KeyV=3; //檢測Key_SET是否按下
KeySETDowning=0; //清除
/*--------------檢測是否有鍵按下----------------*/
if(KeyV!=0) //KeyV不等于零表示有鍵按下
{
Delay_1ms(10); //延時防抖 按下10MS再測
if(!Key_UP)TempKeyV=1;
if(!Key_DOWN)TempKeyV=2;
if(!Key_SET)TempKeyV=3;
if(KeyV==TempKeyV) //兩次值相等為確定接下了鍵
{
/*---判斷是否是Key_SET按下---*/
if(KeyV==3) //按下SET鍵,如在SET狀態(tài)就退出,否則進入
{
KeySETDowning=1; //表明SET正在按下
PowTF=0; //電源標識開
if(!KeyTF) //KeyTF為1不允許執(zhí)行下程序
if(SetTF)
{
SetTF=0; //是否是在溫度設置狀態(tài)標識位標識退出設定
InitDS1820();
Write_Data(0xcc); //跳過ROM
Write_Data(0x4e); //寫溫度上限指令
WriteDS1820(); //寫溫度上限到DS1820ROM
InitDS1820();
Write_Data(0xcc); //跳過ROM匹配
Write_Data(0x48); //溫度上限值COPY回E2PRAM
}
else SetTF=1; //為下一次沒按SET時,按其他鍵作準備
if(!KeySETDown){KeySETDown=1;OPen=1;} //是否已按過SET鍵標識
else KSDNum+=1; //前一秒內有按SET則開始計數(shù)
}
/*--------Key_UP和Key_DOWN的檢測---------*/
if(SetTF) //在SET狀態(tài)下
{
if((KeyV==1)&&(!KeyTF))TMSetV+=1,OPen=0; //上調溫度
if((KeyV==2)&&(!KeyTF))TMSetV-=1,OPen=0; //下調溫度
if(TMSetV<=-55)TMSetV=-55;
if(TMSetV>=125)TMSetV=125;
}
if((!KeyTF)&&(IntNum3==0))KeyTF=1; //判斷鍵盤是否處于可用時
}
/*---------按鍵長按的處理----------*/
if(KeySETDown)IntNum+=1; //在2秒內按下了SET則計中斷發(fā)生次數(shù)用于長按SET時計時用
if(IntNum>60)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -