/******************************************基于8155的8LED顯示溫度控制器設計***************************/
#include<reg52.h>
#include<absacc.h>
/*******************************************宏定義***************************************************/
#define uint unsigned int
#define uchar unsigned char
/*******************************************定義8155地址***********************************************/
#define COM8155 XBYTE[0X7FF8] //8155的命令口
#define PA8155 XBYTE[0X7FF9] //8155的PA
#define PB8155 XBYTE[0X7FFA] //8155的PB
#define PC8155 XBYTE[0X7FFB] //8155的PC
/*********************************************定義DS18B20引腳**********************************************/
sbit DS18B20=P3^0; //DDS18B20引腳
/*********************************************定義蜂鳴器引腳**********************************************/
sbit lamp=P1^5;
/*******************************************定義數碼管顯示的碼值**************************************/
uchar code du_code[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x39,0x5e,0x79,0x71}; //數碼管顯示0~F的碼值
uchar dis_buf[]={0x3f,0x3f,0x40,0x3f,0x3f,0x40,0x3f,0x3f}; //數碼管顯示緩存,格式為MM-NN-SS;8155內部的RAM開始的地址是0x3f00
uchar code bit_code[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //數碼管顯示的位值
/*********************************************定義系統變量***************************************************/
uchar hour,minute,second; //定義時間變量
//uchar hour3=0,minute3=0,second3=0;//定義總時間的時間變量
//char hour1=0,minute1=0,second1=5; //定義采樣間隔變量 ; 一開始小時數為0,分鐘數為0,秒數為5
char hour2=0,minute2=0,second2=5; //定義采樣總時間變量 ; 一開始小時數為0,分鐘數為0,秒數為5
char highest=99,lowest=0; //裝設定的最大值和最小值
uchar count,count1,num,count2; //定義計數器變量
uint count3=0;
uchar str[8]; //定義數顯示溫度
uchar temp=0; //定義顯示溫度平均值變量
uchar temp1[2]; // 定義數組存儲溫度值
bit flag=0; // 定義時間標志位
bit flag1,flag2,flag3,flag4,flag5; //定義按鍵標志位
uint st=0x3f00; //定義8155RAM起始地址
uint x=0x3f00;//存溫度時指向內存
uchar q=0; //標注是否按下5鍵,是否開始計數
/*********************************************延時程序***************************************************/
//us延時程序
void delayus(uint x)
{
while(x--);
}
//ms延時程序
void delayms(uint x)
{
uchar y;
for(;x>0;x--)
for(y=110;y>0;y--)
;
}
/*********************************************DS18B20程序***************************************************/
//18b20初始化程序
void Init_DS18B20(void)
{
uchar x=0;
DS18B20 = 1; //DS18B20復位
delayus(8); //稍做延時
DS18B20 = 0; //單片機將DS18B20拉低
delayus(80); //精確延時 大于 480us
DS18B20 = 1; //拉高總線
delayus(10);
x=DS18B20; //稍做延時后 如果x=0則初始化成功 x=1則初始化失敗
delayus(5);
}
//讀一個字節
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i>0;i--)
{
DS18B20 = 0; // 給脈沖信號
dat>>=1;
DS18B20 = 1; // 給脈沖信號
if(DS18B20)
dat|=0x80;
delayus(5); //延時
}
return(dat);
}
//寫一個字節
void WriteOneChar(uchar dat)
{
uchar i=0;
for (i=8; i>0; i--)
{
DS18B20 = 0;
DS18B20 = dat&0x01;
delayus(5);
DS18B20 = 1;
dat>>=1;
}
delayus(5);
}
//讀溫度值
uchar ReadTemperature(void) //讀取溫度
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳過讀序號列號的操作
WriteOneChar(0x44); // 啟動溫度轉換
delayus(200);
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度
a=ReadOneChar();
b=ReadOneChar();
b<<=4;
b+=(a&0xf0)>>4;
t=b;
return(t); //返回溫度值
}
/*********************************************掃描鍵盤程序***************************************************/
void keyscan()
{
uchar m;
m=PC8155;
m=m&0x1f;
if(m!=0x1f)//有按鍵被按下
{
delayms(10); //延時消抖
PB8155=0x0f;
m=PC8155;
m&=0x1f;
if(m!=0x1f) //消抖后仍有按鍵被按下
{
m=PC8155;
m&=0x1f;
switch(m)
{
case(0x1e):flag1=1;break; // flag1為1, 按鍵1被按下
case(0x1d):flag2=1;break; //按鍵2被按下,flag2為1
case(0x1b):flag3=1;break; //按鍵3被按下,flag3為1
case(0x17):flag4=1;break; //按鍵4被按下,flag4為1
case(0x0f):flag5=1;break;//按鍵5
}
}
while(PC8155!=0x1f); //等待按鍵松開,松開以后執行下面的程序
}
if(flag5==1)
{
q = !q;
x=0x3f00;
st=0x3f00;
flag5=0;
}
if(flag1==1)
{
count++;
count2=0;
if(count>=4) //按鍵1被按下,功能計數器加1,跳轉到下一個功能
count=0;
flag1=0;
}
if(count==1) //判斷當前是否在功能1狀態下
{
if(flag2==1)
{
count2++; //按鍵2被按下,采樣時間小時加1
if(count2>=3) //判斷時間界限
count2=0;
flag2=0;
}
if(flag3==1)
{
if(count2==0)lowest++ ; if(lowest < 0) lowest=0;
if(count2==2)highest++ ; if(highest > 99) highest=99;
flag3=0;
}
if(flag4==1)
{
if(count2==0) lowest--; if(lowest<0) lowest=0;
if(count2==2) highest--; if(highest>99)highest=99;
flag4=0;
}
}
if(count==2)
{ //判斷當前是否在功能2狀態下
if(flag2==1)
{
if(st<0x3fff)
st++; //判斷RAM地址范圍
flag2=0; //RAM地址加1
}
if(flag3==1)
{
if(st>0x3f00) //判斷RAM地址范圍
st--; //RAM地址減1
flag3=0;
}
}
if (count==3)
{
if(flag2==1)
{
count2++; //按鍵2被按下,采樣時間小時加1
if(count2>=3) //判斷時間界限
count2=0;
flag2=0;
}
if(flag3==1)
{
if(count2==0) second2++; if(second2==60) second2=0;
if(count2==1) minute2++; if(minute2==60) minute2=0;
if(count2==2) hour2++; if(hour2==24) hour2=0;
flag3=0;
}
if(flag4==1)
{
if(count2==0) second2--; if(second2<0) second2=59;
if(count2==1) minute2--; if(minute2<0) minute2=59;
if(count2==2) hour2--; if(hour2<0) hour2=23;
flag4=0;
}
}
}
/*********************************************初始化程序***************************************************/
void initial()
{
COM8155=0x03; //初始化8155
TMOD=0x11; //定時器工作方式初始化,設置T1,T2定時器的工作模式
TH0=(65536-1000)/256;
TL0=(65536-1000)%256; //定時器0裝初值
TH1=(65536-50000)/256;
TL1=(65536-50000)%256; //定時器1裝初值
ET0=1; //開定時器0中斷
ET1=1; //開定時器1中斷
EA=1; //開總中斷
TR0=1; //開定時器0
TR1=1; //開定時器1
}
/*********************************************主程序***************************************************/
void main()
{
uint sumtime;
uint o=0;
uchar ss;
uchar j=0x00;
initial(); //系統初始化,即8051初始化
for(;x<=0x3fff;x++)
XBYTE[x]=0x00; //RAM初始化,8155內部有256字節的RAM
x=0x3f00;
st=0x3f00;
while(1)
{
keyscan(); //鍵盤掃描
sumtime=(60*minute2+second2+0x3f00);
if(flag==1)
{
temp=ReadTemperature(); //讀溫度值
second=0;
minute=0;
hour=0; //時間值清零
flag=0;
if(q==1)
{
if(x<sumtime)
{
XBYTE[x++]=temp/10*16+temp%10; //裝儲存的溫度值
}
}
if(temp < highest && temp > lowest)
{
lamp=0;
if(count==0)
{
str[0]=0;
str[1]=0;
str[2]=du_code[temp/10]; //取除到的數相對應的數碼管顯示的碼組存放在str數組中
str[3]=du_code[temp%10];
str[4]=0x63;
str[5]=0x39;
str[6]=0;
str[7]=0; //裝溫度值
}
}
else
{
for(o=10;o>0;o--)
{
lamp=0;
lamp=~lamp;
delayms(0.3);
}
str[0]= 0;
str[1]=0;
str[2]=du_code[14];
str[3]=du_code[14]; //顯示“EEEE”表示錯誤
str[4]=du_code[14];
str[5]=du_code[14];
str[6]=0;
str[7]=0;
}
}
if(count==1)
{
dis_buf[0]=du_code[highest/10];
dis_buf[1]=du_code[highest%10];
dis_buf[3]=0x40;
dis_buf[4]=0x40;
dis_buf[6]=du_code[lowest/10];
dis_buf[7]=du_code[lowest%10]; //裝門限時間值
}
if(count==2)
{
ss=XBYTE[st];
str[0]=du_code[ss/16];
str[1]=du_code[ss%16];
str[2]=0x63;
str[3]=0x39;
str[4]=0x40;
str[5]=0x40;
str[6]=du_code[(st-0x3f00)/10];
str[7]=du_code[(st-0x3f00)%10]; //裝儲存的溫度值
}
if(count==3)
{
dis_buf[0]=du_code[hour2/10];
dis_buf[1]=du_code[hour2%10];
dis_buf[3]=du_code[minute2/10];
dis_buf[4]=du_code[minute2%10];
dis_buf[6]=du_code[second2/10];
dis_buf[7]=du_code[second2%10]; //裝采樣總時間值
}
}
}
//}
/*********************************************定時器0中斷程序***************************************************/
void timer0() interrupt 1
{
//裝初值
if(count==0)
{
TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
PB8155=bit_code[count1]; //送數碼管的位值
PA8155=str[count1]; //顯示溫度值
}
if(count==2)
{
TH0=(65536-4000)/256;
TL0=(65536-4000)%256;
PB8155=bit_code[count1]; //送數碼管的位值
PA8155=str[count1]; //顯示溫度值
}
if(count==1||count==3)
{
TH0=(65536-500)/256;
TL0=(65536-500)%256;
count3++;
if(count3<=600)
{
PB8155=bit_code[count1];
PA8155=dis_buf[count1]; //顯示采樣時間間隔
}
else
{
if(count2==0)
{
if(count1==6||count1==7)
PB8155=0xff;
else
PB8155=bit_code[count1]; //秒閃爍
PA8155=dis_buf[count1];
}
if(count2==1)
{
if(count1==3||count1==4)
PB8155=0xff;
else
PB8155=bit_code[count1];
PA8155=dis_buf[count1]; //分鐘閃爍
}
if(count2==2)
{
if(count1==0||count1==1)
PB8155=0xff;
else
PB8155=bit_code[count1];
PA8155=dis_buf[count1]; //小時閃爍
}
if(count3>1200)
count3=0;
}
}
count1++;
if(count1>=8)
count1=0;
}
/*********************************************定時器1中斷程序***************************************************/
void timer1() interrupt 3
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256; //裝初值
num++;
if(num==20)
{
num=0;
flag=1;
second++; //1秒時間到
if(second==60)
{
second=0;
minute++; //1分鐘時間到
if(minute==60)
{
minute=0;
hour++; //1小時時間到
if(hour==24)
hour=0;
}
}
}
}
|