專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

基于18B20和單片機89C52的測溫程序

作者:佚名   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2012年01月02日   【字體:
#include<reg51.h>
 
#include<intrins.h>
 
#include"KEY.h"
 
#include"IIC.h"
 
#define uint unsigned int
 
#define uchar unsigned char
 
#define IICADDR 0x20  //存儲地址
 
#define LEDIO    P0             //P0掃描段碼,P2掃描位選信號 
 
#define LEDCHIP   P2
 
sbit  DQ=P3^2; //18B20接口
 
sbit BEEP=P3^7; // 蜂鳴器接口
 
uchar i=0,mod=0; //掃描變量
 
uchar key1,key2=20;    //按鍵寄存
 
uchar Tmp_max=10,Tmp_min=5,Tmp;    //溫度寄存
 
uint k=0,p=0,num=5000;    //有關(guān)掃描的變量
 
/****************溫度小數(shù)部分用查表法*********************/
 
uchar code LedTab[14]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x063};
 
 /***共陰數(shù)碼管段碼表  0    1    2    3    4    5    6    7    8    9    不亮  -    °  */
 
uchar code selchip[6]={0x01,0x02,0x04,0x08,0x10,0x20};//列掃描位選信號
 
uchar data temp_data[2]={0x00,0x00};//讀出溫度暫放
 
uchar data display[3][7]={{0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x00},  //顯示單元數(shù)據(jù),共6個數(shù)據(jù)一個用作運算                   {0x00,0x3f,0x3f,0x3f,0x3f,0x76,0x00},  //顯示H設(shè)置最大值
 
  {0x00,0x3f,0x3f,0x3f,0x3f,0x38,0x00}};  //顯示L設(shè)置最小值
 
///////////////////////////////////////////////////////////////////////////////
 
void Delay_tmp(uchar time)   //延時10us  
 
{
 
while(time--)
 
{
 
_nop_();
 
_nop_();
 
}
 
}
 
void Delay_2s()    //延時兩秒開機檢測數(shù)碼管
 
{
 
    unsigned char a,b,c;
 
    for(c=23;c>0;c--)
 
        for(b=216;b>0;b--)
 
            for(a=184;a>0;a--);
 
}
 
/*********************定時器初始化***********************************/
 
void TimerInit()
 
{
 
TMOD=0x01; //定時器1定時掃描
 
ET0=1;
 
EA=1;
 
TH0=0xfc;
 
TL0=0xd8;
 
TR0=1;
 
}
 
/******************定時器中斷掃描程序**********************/
 
void timedis() interrupt 1
 
{
 
if(mod) //閃爍程序,提醒用戶正在設(shè)置
 
{
 
if(num--)  //自動退出閃爍,返回主界面
 
{
 
if(k++<190)
 
{
 
P2=0x00;
 
}
 
else
 
{
 
LEDIO=display[mod][i];
 
LEDCHIP=selchip[i];
 
if(i>=5)
 
i=0;
 
else 
 
i++;
 
if(p++>190)
 
{
 
p=0;
 
k=0;
 
}
 
}
 
}
 
else
 
mod=0;
 
}
 
else   //正常數(shù)碼管掃描顯示
 
{
 
LEDIO=display[mod][i];
 
LEDCHIP=selchip[i];
 
if(i>=5)
 
i=0;
 
else 
 
i++;
 
    }
 
TH0=0xfc;
 
TL0=0xd8;
 
}
 
/*********************DS18B20復(fù)位函數(shù)*****************************/
 
void Temp_Reset(void)
 
{
 
EA=0;
 
    CY = 1;
 
    while (CY)
 
    {
 
        DQ = 0;                     //送出低電平復(fù)位信號
 
        Delay_tmp(48);              //延時至少480us
 
        DQ = 1;                     //釋放數(shù)據(jù)線
 
        Delay_tmp(6);               //等待60us
 
        CY = DQ;                    //檢測存在脈沖
 
        Delay_tmp(42);              //等待設(shè)備釋放數(shù)據(jù)線
 
    }
 
EA=1;
 
}
 
/************************寫一字節(jié)********************/
 
void Temp_Write_byte(uchar val)
 
{
 
uchar i;
 
EA=0;
 
for (i=8;i>0;i--)
 
{
 
DQ=0;_nop_();_nop_();
 
val >>=1;; //寫數(shù)據(jù)
 
DQ=CY;
 
Delay_tmp(6); //延時66us等待采樣結(jié)束
 
DQ=1; //右移一位
 
}
 
EA=1;
 
}
 
/***********************讀一字節(jié)****************************/
 
char Temp_Read_byte()
 
{
 
uchar i;
 
uchar value=0;
 
EA=0;
 
for(i=0;i<8;i++)
 
{
 
value >>=1; //18B20右移一位
 
DQ=0;_nop_();_nop_();   //2us
 
DQ=1;_nop_();_nop_(); //2us
 
if(DQ) //讀出來的是1
 
value |=0x80;
 
Delay_tmp(6);    //66us
 
}
 
DQ=1;
 
EA=1;
 
return value;
 
}
 
/***********************讀出溫度函數(shù)*****************************************/
 
void Read_temp()
 
{
 
Temp_Reset();  //總線復(fù)位
 
Temp_Write_byte(0xcc);//發(fā)skip ROM命令
 
Temp_Write_byte(0xbe);//發(fā)讀命令
 
temp_data[0]=Temp_Read_byte();//讀低8位
 
temp_data[1]=Temp_Read_byte();//讀高8位
 
Temp_Reset();
 
Temp_Write_byte(0xcc);//發(fā)skip ROM命令
 
Temp_Write_byte(0x44); //溫度變換
 
while(!DQ);
 
}
 
/************************溫度數(shù)據(jù)處理函數(shù)************************************/
 
void Temp_Change()
 
{
 
bit n=0,n1=0,n2=0;
 
Tmp= ((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4); //記錄當(dāng)前的溫度值,用于比較
 
if(temp_data[1]>127) // 溫度為負(fù)時
 
{
 
temp_data[1]=(256-temp_data[1]);  //負(fù)溫度求補碼
 
temp_data[0]=(256-temp_data[0]);
 
n=1;
 
}                                                                  
 
display[0][6]=temp_data[0]&0x0f;
 
display[0][4]=LedTab[(uchar)display[0][6]*5/8]; //小數(shù)部分
 
display[0][6]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4);  //整數(shù)部分
 
display[0][1]=LedTab[display[0][6]/100]; //十六進制轉(zhuǎn)BCD碼
 
display[0][6]=display[0][6]%100;
 
display[0][2]=LedTab[display[0][6]/10]; //十位段碼
 
display[0][3]=LedTab[(display[0][6]%10)]|0x80;    //個位段碼帶小數(shù)點
 
display[0][5]=LedTab[12]; //顯示度
 
if(display[0][1]==LedTab[0]) //最高位為零時都不顯示
 
{
 
display[0][1]=LedTab[10];
 
if(display[0][2]==LedTab[0]) //次高位處理
 
{
 
display[0][2]=LedTab[10];
 
}
 
}                                                            
 
if(n)  //負(fù)溫度時最高位顯示“-”
 
display[0][0]=LedTab[11];
 
else 
 
display[0][0]=LedTab[10];
 
//////////////////////////////////////////////////處理鍵盤值
 
if(Tmp_max>127) //最高溫度上限處理
 
{
 
n1=1;
 
display[1][6]=(256-Tmp_max);  //負(fù)數(shù)去反
 
}
 
else
 
display[1][6]=Tmp_max;
 
display[1][1]=LedTab[display[1][6]/100];  //求最高位
 
display[1][6]=display[1][6]%100;   //求次高位
 
display[1][2]=LedTab[display[1][6]/10];
 
display[1][3]=LedTab[display[1][6]%10]|0x80;         //求個位段碼帶小數(shù)點
 
if(display[1][1]==LedTab[0]) //最高位為0不顯示
 
{
 
display[1][1]=LedTab[10];
 
if(display[1][2]==LedTab[0])  //最高位為0次高位為0不顯示
 
{
 
display[1][2]=LedTab[10];
 
}
 
}                                                            
 
if(n1)  //負(fù)溫度時最高位顯示“-”
 
display[1][0]=LedTab[11];
 
else 
 
{
 
display[1][0]=LedTab[10];   //不顯示正
 
}
 
//////////////////////////////////////////////////////////////
 
if(Tmp_min>127) //最低溫度下限處理
 
{
 
n2=1;
 
display[2][6]=(256-Tmp_min);  //取反
 
}
 
else
 
display[2][6]=Tmp_min;
 
display[2][1]=LedTab[display[2][6]/100];   //求最高位
 
display[2][6]=display[2][6]%100;    //求次高位
 
display[2][2]=LedTab[display[2][6]/10];
 
display[2][3]=LedTab[display[2][6]%10]|0x80;    //求個位段碼帶小數(shù)點
 
if(display[2][1]==LedTab[0]) //最高位為0不顯示
 
{
 
display[2][1]=LedTab[10];
 
if(display[2][2]==LedTab[0]) //最高位為0次高位為0不顯示
 
{
 
display[2][2]=LedTab[10];
 
}
 
}                                                            
 
if(n2)   
 
display[2][0]=LedTab[11];      //負(fù)溫度時最高位顯示“-”
 
else
 
{
 
display[2][0]=LedTab[10]; //不顯示正
 
}   
 
}
 
/***************************鍵盤掃描***************************************/
 
void Key_scanf()
 
{
 
key1=KeyTab[KeyRvs()]; //讀取鍵盤值
 
if(key2!=key1)   //防止連續(xù)跳動,釋放按鍵
 
{
 
if(key1=='*') //mod選擇
 
{
 
mod=mod%2+1;
 
num=5000;
 
}
 
if((key1=='0')&&(mod)) //按鍵加
 
{
 
num=5000;
 
if(mod==1)
 
{
 
if(Tmp_max==125) //最高上限溫度
 
Tmp_max=202;  //最低溫度下限
 
else
 
Tmp_max++;
 
}
 
if(mod==2)
 
{
 
if(Tmp_min==125)   //最高上限溫度
 
Tmp_min=202;  //最低溫度下限
 
else
 
Tmp_min++;
 
}
 
}
 
if((key1=='#')&&(mod))   //按鍵減
 
{
 
num=5000;
 
if(mod==1)
 
{
 
if(Tmp_max==202)      //最低溫度下限
 
Tmp_max=125;   //最高上限溫度
 
else
 
Tmp_max--;
 
}
 
if(mod==2)
 
{
 
if(Tmp_min==202)      //最低溫度下限
 
Tmp_min=125; //最高上限溫度
 
else
 
Tmp_min--;
 
}
 
}
 
if(key1=='D')    //確定以后把修改的數(shù)據(jù)保存起來
 
{
 
mod=0;  //恢復(fù)正常顯示
 
EA=0;   //IIC寫時候保護
 
while(!Write_Byte_iic(IICADDR,0xaa));      //寫判斷是否設(shè)置標(biāo)志
 
while(!Write_Byte_iic(IICADDR+2,Tmp_max));   //寫溫度上限
 
while(!Write_Byte_iic(IICADDR+4,Tmp_min));   //寫溫度下限
 
EA=1;
 
}
 
}
 
key2=key1;   //鍵值保存。釋放按鍵用
 
}
 
/**************************蜂鳴器報警***************************/
 
void Beep()
 
{
 
char a,b,c;
 
a=Tmp;b=Tmp_max;c=Tmp_min;
 
if((a>=b)||(a<c))    //比較上下限溫度,
 
BEEP=~BEEP;    //開蜂鳴器
 
else
 
BEEP=1;    //關(guān)閉蜂鳴器
 
}
 
///////////////////////////////////////////////////////////
 
main()
 
{
 
if(Read_Byte_iic(IICADDR)==0xaa) //判斷是否修改過,若是修改過則讀取溫度上下限
 
{
 
Tmp_max=Read_Byte_iic(IICADDR+2);  //讀取報警溫度上限
 
Tmp_min=Read_Byte_iic(IICADDR+4);  //讀取報警溫度下限
 
}
 
Temp_Reset();   //開機先轉(zhuǎn)換一次
 
Temp_Write_byte(0xcc);                 //Skip ROM
 
Temp_Write_byte(0x44);   //發(fā)轉(zhuǎn)換命令
 
while(!DQ);
 
TimerInit();
 
for(i=0;i<6;i++)
 
{
 
display[0][i]=LedTab[8];
 
}   //開機顯示“888888”
 
Delay_2s();              //顯示兩秒               
 
while(1)
 
{   //讀出溫度數(shù)據(jù)
 
  Read_temp();   //處理溫度數(shù)據(jù)
 
  Temp_Change(); //溫度數(shù)據(jù)轉(zhuǎn)換
 
Key_scanf(); //鍵盤掃描
 
Beep(); //蜂鳴器掃描;
 
  }
 
}
 
//////////////////////////////////////////////////////////
 
頭文件與電子鐘類似
關(guān)閉窗口

相關(guān)文章