#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; //有關掃描的變量
/****************溫度小數部分用查表法*********************/
uchar code LedTab[14]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40,0x063};
/***共陰數碼管段碼表 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}, //顯示單元數據,共6個數據一個用作運算 {0x00,0x3f,0x3f,0x3f,0x3f,0x76,0x00}, //顯示H設置最大值
{0x00,0x3f,0x3f,0x3f,0x3f,0x38,0x00}}; //顯示L設置最小值
///////////////////////////////////////////////////////////////////////////////
void Delay_tmp(uchar time) //延時10us
{
while(time--)
{
_nop_();
_nop_();
}
}
void Delay_2s() //延時兩秒開機檢測數碼管
{
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) //閃爍程序,提醒用戶正在設置
{
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 //正常數碼管掃描顯示
{
LEDIO=display[mod][i];
LEDCHIP=selchip[i];
if(i>=5)
i=0;
else
i++;
}
TH0=0xfc;
TL0=0xd8;
}
/*********************DS18B20復位函數*****************************/
void Temp_Reset(void)
{
EA=0;
CY = 1;
while (CY)
{
DQ = 0; //送出低電平復位信號
Delay_tmp(48); //延時至少480us
DQ = 1; //釋放數據線
Delay_tmp(6); //等待60us
CY = DQ; //檢測存在脈沖
Delay_tmp(42); //等待設備釋放數據線
}
EA=1;
}
/************************寫一字節********************/
void Temp_Write_byte(uchar val)
{
uchar i;
EA=0;
for (i=8;i>0;i--)
{
DQ=0;_nop_();_nop_();
val >>=1;; //寫數據
DQ=CY;
Delay_tmp(6); //延時66us等待采樣結束
DQ=1; //右移一位
}
EA=1;
}
/***********************讀一字節****************************/
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;
}
/***********************讀出溫度函數*****************************************/
void Read_temp()
{
Temp_Reset(); //總線復位
Temp_Write_byte(0xcc);//發skip ROM命令
Temp_Write_byte(0xbe);//發讀命令
temp_data[0]=Temp_Read_byte();//讀低8位
temp_data[1]=Temp_Read_byte();//讀高8位
Temp_Reset();
Temp_Write_byte(0xcc);//發skip ROM命令
Temp_Write_byte(0x44); //溫度變換
while(!DQ);
}
/************************溫度數據處理函數************************************/
void Temp_Change()
{
bit n=0,n1=0,n2=0;
Tmp= ((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4); //記錄當前的溫度值,用于比較
if(temp_data[1]>127) // 溫度為負時
{
temp_data[1]=(256-temp_data[1]); //負溫度求補碼
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]; //小數部分
display[0][6]=((temp_data[0]&0xf0)>>4)|((temp_data[1]&0x0f)<<4); //整數部分
display[0][1]=LedTab[display[0][6]/100]; //十六進制轉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; //個位段碼帶小數點
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) //負溫度時最高位顯示“-”
display[0][0]=LedTab[11];
else
display[0][0]=LedTab[10];
//////////////////////////////////////////////////處理鍵盤值
if(Tmp_max>127) //最高溫度上限處理
{
n1=1;
display[1][6]=(256-Tmp_max); //負數去反
}
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; //求個位段碼帶小數點
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) //負溫度時最高位顯示“-”
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; //求個位段碼帶小數點
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]; //負溫度時最高位顯示“-”
else
{
display[2][0]=LedTab[10]; //不顯示正
}
}
/***************************鍵盤掃描***************************************/
void Key_scanf()
{
key1=KeyTab[KeyRvs()]; //讀取鍵盤值
if(key2!=key1) //防止連續跳動,釋放按鍵
{
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') //確定以后把修改的數據保存起來
{
mod=0; //恢復正常顯示
EA=0; //IIC寫時候保護
while(!Write_Byte_iic(IICADDR,0xaa)); //寫判斷是否設置標志
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; //關閉蜂鳴器
}
///////////////////////////////////////////////////////////
main()
{
if(Read_Byte_iic(IICADDR)==0xaa) //判斷是否修改過,若是修改過則讀取溫度上下限
{
Tmp_max=Read_Byte_iic(IICADDR+2); //讀取報警溫度上限
Tmp_min=Read_Byte_iic(IICADDR+4); //讀取報警溫度下限
}
Temp_Reset(); //開機先轉換一次
Temp_Write_byte(0xcc); //Skip ROM
Temp_Write_byte(0x44); //發轉換命令
while(!DQ);
TimerInit();
for(i=0;i<6;i++)
{
display[0][i]=LedTab[8];
} //開機顯示“888888”
Delay_2s(); //顯示兩秒
while(1)
{ //讀出溫度數據
Read_temp(); //處理溫度數據
Temp_Change(); //溫度數據轉換
Key_scanf(); //鍵盤掃描
Beep(); //蜂鳴器掃描;
}
}
//////////////////////////////////////////////////////////
頭文件與電子鐘類似