/******************************************基于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;
}
}
}
}
|