#include<AT89X52.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P3^5;
sbit lcden=P3^4;
sbit ce=P2^2;
sbit io=P2^1;
sbit sclk=P2^0;
sbit DQ=P2^6;
sbit s1=P3^0; // 功能模式选择键
sbit s2=P3^1; // 加一键
sbit s3=P3^2; // 减一键
uchar code tab[]="0123456789";
uchar code disp_start0[]=" Please insert";
uchar code disp_start1[]=" DS18B20";
uchar code disp_init1[]="20**-**-** *";
uchar code disp_init2[]="??:??:??";
uchar code ditab[16]= //温度小数部分用查表法
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
uchar code weektab[]={"***MONTUSWENTHUFRISATSUN"};
uchar timbuf[]={0,0,0,0,0,0,0,0,0,0,0,0,0};
uchar tembuf[]={0,0,0,0,0};
uchar nian,zhou,yue,ri,shi,fen,miao;
uchar nian_h,nian_l,yue_h,yue_l,ri_h,ri_l,
shi_h,shi_l,fen_h,fen_l,miao_h,miao_l;
uchar s1num;
uint wendu; //16位温度值
uchar wendu_H,wendu_L; //温度值的高低8位
bit sw=0;
void delay(uint z) // 当z=1时,延时1ms
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void delayus(uchar t) //当t=1时,延时11us
{
for(;t>0;t--);
}
void init_18b20() //18B20初始化
{
bit flag=1;
while(flag)
{
while(flag)
{
DQ=1;
delayus(1);
DQ=0;
delayus(50); //550us
DQ=1; delayus(6); //66us
flag=DQ;
}
delayus(45);
flag=~DQ;
}
DQ=1;
}
void write1820_byte(uchar dat) // 写一个字节
{
uchar i;
for(i=0;i<8;i++)
{
DQ=1;_nop_();_nop_();
DQ=0;
delayus(1); //11us
DQ=dat&0x01;
delayus(6); //66us
dat=dat>>1;
}
DQ=1;
delayus(1);
}
uchar read1820_byte() //读一个字节
{
uchar i,temp;
for(i=0;i<8;i++)
{
DQ=1;_nop_();_nop_();
temp=temp>>1;
DQ=0;_nop_();_nop_();
DQ=1;_nop_();_nop_();
if(DQ)
temp=temp|0x80;
delayus(6);//66us
}
DQ=1;
return (temp);
}
void write_com(uchar com) // 液晶写命令函数
{
lcdrs=0; P0=com; delay(1); lcden=1; delay(1); lcden=0;
}
void write_date(uchar date) // 液晶写数据函数
{
lcdrs=1; P0=date; delay(1); lcden=1; delay(1); lcden=0;
}
void display(uchar hang,uchar lie,uchar date) //向某一行、某一列写一个数据
{
if(hang==0) write_com(0x80+lie); else write_com(0xc0+lie) ; write_date(date);
}
void lcd_init() // 液晶初始化
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
void lcd_dispstart() //开机液晶显示界面
{
uchar i;
write_com(0x80); //显示第一行
for(i=0;i<15;i++)
write_date(disp_start0[i]);
write_com(0xc0); //显示第二行
for(i=0;i<11;i++)
write_date(disp_start1[i]);
}
void lcd_dispinit1() // 液晶初始显示
{
uchar i;
delay(10);
write_com(0x80); //显示第一行
for(i=0;i<13;i++)
write_date(disp_init1[i]);
write_com(0xc0); //显示第二行
for(i=0;i<8;i++)
write_date(disp_init2[i]);
write_com(0xc0+12); // 显示小数点
write_date('.'); write_com(0xc0+14); // 显示温度标志
write_date(0xdf);
write_date('C');
}
void write1302_byte(uchar temp) //逐位向1302写一个字节
{
uchar i;
for(i=0;i<8;i++)
{ sclk=0; //拉低时钟引脚
io=temp&0x01; //从低位开始送
sclk=1; //置高电平,产生上跳沿,写入数据
delayus(1);
temp>>=1; //数据右移一位
}
}
uchar read1302_byte() // 逐位从1302读一个字节
{
uchar i,temp;
for(i=0;i<8;i++)
{ temp>>=1; //右移一位,从最左边放入一个0
sclk=1; //置高时钟引脚
delayus(1);
sclk=0; // 拉低电平,产生下降沿,准备读引脚
delayus(1);
if(io==1)
temp=temp|0x80; //
}
return temp;
}
void write_1302(uchar addr,uchar dat) //向指定地址写一个数据
{
ce=0; //初始ce置0
sclk=0; // 初始sclk置0
delayus(1);
ce=1; // ce置1,开始数据传输
delayus(1);
write1302_byte(addr); // 写命令字,给出寄存器地址
delayus(1);
sclk=0; //sclk置0,为写入下一个字节做准备
delayus(1);
write1302_byte(dat); // 向指定寄存器写入数据
delayus(1);
sclk=0;
ce=0; //ce置0,结束数据传输
}
uchar read_1302(uchar addr) //从指定地址读一个数据
{
uchar dat;
ce=0; //初始ce置0
sclk=0; // 初始sclk置0
delayus(1);
ce=1; // ce置1,开始数据传输
delayus(1);
write1302_byte(addr); // 写命令字,给出时间寄存器地址
delayus(1);
dat=read1302_byte(); // 从指定地址读出数据
sclk=0;
ce=0; //ce置0,结束数据传输
return dat;
}
/*void time_disp(uchar add,char date) // 时间在液晶的显示程序
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+add);
write_date(tab1[shi]);
write_date(tab1[ge]);
}*/
void read_time()//从1302中读出时间数据并转换为ASCII码存入timbuf数组中
{
miao=read_1302(0x81); //读秒寄存器
fen=read_1302(0x83); // 读分钟寄存器
shi=read_1302(0x85); // 读小时寄存器
ri=read_1302(0x87); //读日寄存器
yue=read_1302(0x89); // 读月寄存器
zhou=read_1302(0x8b); // 读周寄存器
nian=read_1302(0x8d); // 读年寄存器
timbuf[0]=tab[nian>>4]; //向缓冲器里写年份数据
timbuf[1]=tab[nian&0x0f];
timbuf[2]=tab[yue>>4]; //向缓冲器里写月份数据
timbuf[3]=tab[yue&0x0f];
timbuf[4]=tab[ri>>4]; //向缓冲器里写日份数据
timbuf[5]=tab[ri&0x0f];
timbuf[6]=zhou&0x0f; //向缓冲器里写周数据
timbuf[7]=tab[shi>>4]; //向缓冲器里写小时数据
timbuf[8]=tab[shi&0x0f];
timbuf[9]=tab[fen>>4]; //向缓冲器里写分钟数据
timbuf[10]=tab[fen&0x0f];
timbuf[11]=tab[(miao&0x7f)>>4]; //向缓冲器里写秒钟数据
timbuf[12]=tab[miao&0x0f];
}
void init_1302()
{
write_1302(0x8e,0x00);//写不保护指令
write_1302(0x90,0xaa);//定义充电方式
write_1302(0x80,0x50);//定义秒
write_1302(0x82,0x59);//分
write_1302(0x84,0x23);//时
write_1302(0x86,0x30);//日
write_1302(0x88,0x04);//月
write_1302(0x8a,0x04);//星期
write_1302(0x8c,0x11);//年
write_1302(0x8e,0x80);//写保护指令
}
uint read_wendu()
{
init_18b20(); //DS18B20初始化
write1820_byte(0xcc); //发出跳过对ROM操作的命令
write1820_byte(0x44); //发温度转换命令
init_18b20(); //DS18B20初始化
write1820_byte(0xcc); //发出跳过对ROM操作的命令
write1820_byte(0xbe); //发出读暂存器命令
wendu_L=read1820_byte(); //读温度值的低字节
wendu_H=read1820_byte(); //读温度值的高字节
wendu=wendu_H;
wendu=wendu<<8;
wendu=wendu|wendu_L;
return (wendu) ;
}
/****************温度数据处理函数************************/
//二进制高字节的低半字节和低字节的高半字节组成一字节,这个
//字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩
//下的低字节的低半字节转化成十进制后,就是温度值的小数部分
/********************************************************/
void work_temp(uint tem)
{
uchar n=0,temp;
if(tem>64656) // 温度值正负判断
{
tem=65536-tem;
n=1; // 负温度求补码,标志位置1
}
temp=tem&0x0f; // 取小数部分的值
tembuf[0]=ditab[temp]+0x30; // 存入小数部分显示值
temp=tem>>4; // 取中间八位,即整数部分的值
tembuf[3]=temp/100+0x30; // 取百位数据暂存
tembuf[2]=temp%100/10+0x30; // 取后两位数据暂存
tembuf[1]=temp%100%10+0x30;
/******************符号位显示判断**************************/
if(tembuf[3]=='0')
{ tembuf[3]=' '; //最高位为0时不显示
if(tembuf[2]=='0')
{
tembuf[2]=' '; //次高位为0时不显示
}
}
if(n)
tembuf[4]='-'; //负温度时最高位显示"-"
else
tembuf[4]=' ';
}
void lcd_display() //液晶显示
{
display(0,2,timbuf[0]); //显示各种时间信息
display(0,3,timbuf[1]);
display(0,5,timbuf[2]);
display(0,6,timbuf[3]);
display(0,8,timbuf[4]);
display(0,9,timbuf[5]);
display(0,12,weektab[timbuf[6]*3]);
display(0,13,weektab[timbuf[6]*3+1]);
display(0,14,weektab[timbuf[6]*3+2]);
display(1,0,timbuf[7]);
display(1,1,timbuf[8]);
display(1,3,timbuf[9]);
display(1,4,timbuf[10]);
display(1,6,timbuf[11]);
display(1,7,timbuf[12]);
display(1,8,tembuf[4]); //显示温度信息
display(1,9,tembuf[3]);
display(1,10,tembuf[2]);
display(1,11,tembuf[1]);
display(1,13,tembuf[0]);
}
void keyscan() // 键盘扫描
{
if(s1==0)
{ delay(200);
if(s1==0)
{ sw=1;
s1num++;
while(!s1);
if(s1num==1)
{
write_1302(0x80,(miao|0x80));//停止振荡器
write_1302(0x8e,0x00);//写不保护指令
write_com(0x0d); //光标闪烁
write_com(0xc0+6);
}
if(s1num==2)
{
write_com(0xc0+3);
}
if(s1num==3)
{
write_com(0xc0+0);
}
if(s1num==4)
{
write_com(0x80+12);
}
if(s1num==5)
{
write_com(0x80+8);
}
if(s1num==6)
{
write_com(0x80+5);
}
if(s1num==7)
{
write_com(0x80+2);
}
if(s1num==8)
{
s1num=0;
write_com(0x0c);
write_1302(0x80,miao&0x7f);
write_1302(0x8e,0x80);//写保护指令
sw=0;
}
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(200);
if(s2==0)
{
while(!s2);
if(s1num==1)
{
miao_l=miao&0x0f;
miao_h=(miao&0x7f)>>4;
miao_l++;
if(miao_l==10)
{ miao_l=0;
miao_h++;
if(miao_h==6)
miao_h=0; }
miao=(miao_h<<4)|miao_l;
write_1302(0x80,miao|0x80);//保持振荡器停止状态
write_com(0xc0+6);
write_date(tab[(miao&0x7f)>>4]);
write_date(tab[miao&0x0f]);
write_com(0xc0+6);
}
if(s1num==2)
{
fen_l=fen&0x0f;
fen_h=(fen&0x7f)>>4;
fen_l++;
if(fen_l==10)
{
fen_l=0;
fen_h++;
if(fen_h==6)
fen_h=0;
}
fen=(fen_h<<4)|fen_l;
write_1302(0x82,fen);
write_com(0xc0+3);
write_date(tab[fen_h]);
write_date(tab[fen_l]);
write_com(0xc0+3);
}
if(s1num==3)
{
shi_l=shi&0x0f;
shi_h=shi>>4;
shi_l++;
if(shi_l==4)
{
if(shi_h==2)
{
shi_l=0;
shi_h=0;
}
}
if(shi_l==10)
{
shi_l=0;
shi_h++;
}
shi=(shi_h<<4)|shi_l;
write_1302(0x84,shi);
write_com(0xc0+0);
write_date(tab[shi_h]);
write_date(tab[shi_l]);
write_com(0xc0+0);
}
if(s1num==4)
{
zhou++;
if(zhou==8)
{
zhou=1;
}
write_1302(0x8a,zhou);
write_com(0x80+12);
write_date(weektab[zhou*3]);
write_date(weektab[zhou*3+1]);
write_date(weektab[zhou*3+2]);
write_com(0x80+12); }
}
if(s1num==5)
{
ri_l=ri&0x0f;
ri_h=ri>>4;
ri_l++;
if(ri_l==2)
{
if(ri_h==3)
{
ri_l=1;
ri_h=0;
}
}
if(ri_l==10)
{
ri_l=0;
ri_h++;
}
ri=(ri_h<<4)|ri_l;
write_1302(0x86,ri);
write_com(0x80+8);
write_date(tab[ri_h]);
write_date(tab[ri_l]);
write_com(0x80+8);
}
if(s1num==6)
{
yue_l=yue&0x0f;
yue_h=yue>>4;
yue_l++;
if(yue_l==3)
{
if(yue_h==1)
{
yue_l=1;
yue_h=0;
}
}
if(yue_l==10)
{
yue_l=0;
yue_h++;
}
yue=(yue_h<<4)|yue_l;
write_1302(0x88,yue);
write_com(0x80+5);
write_date(tab[yue_h]);
write_date(tab[yue_l]);
write_com(0x80+5);
}
if(s1num==7)
{
nian_l=nian&0x0f;
nian_h=nian>>4;
nian_l++;
if(nian_l==10)
{
nian_l=0;
nian_h++;
if(nian_h==10)
nian_h=0;
}
nian=(nian_h<<4)|nian_l;
write_1302(0x8c,nian);
write_com(0x80+2);
write_date(tab[nian_h]);
write_date(tab[nian_l]);
write_com(0x80+2);
}
}
}
if(s3==0)
{
delay(200);
if(s3==0)
{
while(!s3);
if(s1num==1)
{
miao_l=miao&0x0f;
miao_h=(miao&0x7f)>>4;
miao_l--;
if(miao_l==0xff)
{
miao_l=9;
miao_h--;
if(miao_h==0xff)
miao_h=5;
}
miao=(miao_h<<4)|miao_l;
write_1302(0x80,miao|0x80);//保持振荡器停止状态
write_com(0xc0+6);
write_date(tab[(miao&0x7f)>>4]);
write_date(tab[miao&0x0f]);
write_com(0xc0+6);
}
if(s1num==2)
{
fen_l=fen&0x0f;
fen_h=(fen&0x7f)>>4;
fen_l--;
if(fen_l==0xff)
{
fen_l=9;
fen_h--;
if(fen_h==0xff)
fen_h=5;
}
fen=(fen_h<<4)|fen_l;
write_1302(0x82,fen);
write_com(0xc0+3);
write_date(tab[fen_h]);
write_date(tab[fen_l]);
write_com(0xc0+3);
}
if(s1num==3)
{
shi_l=shi&0x0f;
shi_h=shi>>4;
shi_l--;
if(shi_l==0xff)
{
shi_l=0;
shi_h--;
if(shi_h==0xff)
{
shi_l=3;
shi_h=2;
}
}
shi=(shi_h<<4)|shi_l;
write_1302(0x84,shi);
write_com(0xc0+0);
write_date(tab[shi_h]);
write_date(tab[shi_l]);
write_com(0xc0+0);
}
if(s1num==4)
{
zhou--;
if(zhou==0)
{
zhou=7;
}
write_1302(0x8a,zhou);
write_com(0x80+12);
write_date(weektab[zhou*3]);
write_date(weektab[zhou*3+1]);
write_date(weektab[zhou*3+2]);
write_com(0x80+12);
}
if(s1num==5)
{
ri_l=ri&0x0f;
ri_h=ri>>4;
ri_l--;
if(ri_l==0)
{
if(ri_h==0)
{
ri_l=1;
ri_h=3;
}
}
if(ri_l==0xff)
{
ri_l=0;
ri_h--;
}
ri=(ri_h<<4)|ri_l;
write_1302(0x86,ri);
write_com(0x80+8);
write_date(tab[ri_h]);
write_date(tab[ri_l]);
write_com(0x80+8);
}
if(s1num==6)
{
yue_l=yue&0x0f;
yue_h=yue>>4;
yue_l--;
if(yue_l==0)
{
if(yue_h==0)
{
yue_l=2;
yue_h=1;
}
}
if(yue_l==0xff)
{
yue_l=0;
yue_h--;
}
yue=(yue_h<<4)|yue_l;
write_1302(0x88,yue);
write_com(0x80+5);
write_date(tab[yue_h]);
write_date(tab[yue_l]);
write_com(0x80+5);
}
if(s1num==7)
{
nian_l=nian&0x0f;
nian_h=nian>>4;
nian_l--;
if(nian_l==0xff)
{
nian_l=9;
nian_h--;
if(nian_h==0xff)
nian_h=9;
}
nian=(nian_h<<4)|nian_l;
write_1302(0x8c,nian);
write_com(0x80+2);
write_date(tab[nian_h]);
write_date(tab[nian_l]);
write_com(0x80+2);
}
}
}
}
void main()
{
lcd_init();
lcd_dispstart();
init_18b20(); //开机先转换一次
write1820_byte(0xcc); //Skip ROM
write1820_byte(0x44); //发转换命令
lcd_init(); lcd_dispinit1();
write_1302(0x80,0x00);//启动振荡器
init_1302(); // 设置1302初始时间
while(1)
{
if(!sw)
{
read_time();
work_temp(read_wendu()); //处理温度数据
lcd_display();
}
keyscan();
}
}
|
|