#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code tab2[]="00:00:00 000";
uchar code tab3[]="temp: . ";
int tab5[]={0,0,00};
sbit DQ = P2^4;
char code tab[4][4]={ {1,4,7,10},
{2,5,8,0},{3,6,9,11},{12,13,14,15}};
uchar a,miao,shi,fen,tt,key1n,key3n,key2n,nian,yue,r,nianb,speak,wendu,wendu1,wendu3,miao1,shu,shu1,wendu4;
unsigned char code dotcode[167]={0,6,12,19,25,31,37,44,50,56,62,69,75,81,87,94};
sbit rs=P2^5;sbit en=P2^7;sbit rw=P2^6;
#define yh 0x80 //第壹行的初始位置
#define er 0x80+0x40 //第二行初始位置
sfr DBPort = 0x80;
unsigned char tt,tt1;
unsigned char t[2],*pt;
void delay(uint z)
{uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//定義DQ引腳為P3.4
/***********ds18b20延遲子函數(晶振12MHz )*******/
/************DS18B20對時間要求很嚴,但只能長不能短
*************在11.0592M下也行,因為時間長些********/
void delay_18B20(unsigned int i)
{while(i--);
}
/**********ds18b20初始化函數**********************/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ復位
delay_18B20(8); //稍做延時
DQ = 0; //單片機將DQ拉低
delay_18B20(80); //精確延時 大於 480us
DQ = 1; //拉高總線
delay_18B20(14);
x=DQ; //稍做延時後 如果x=0則初始化成功 x=1則初始化失敗
delay_18B20(20);
}
/***********ds18b20讀壹個字節**************/
unsigned char ReadOneChar(void)
{unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; // 給脈沖信號
dat>>=1;
DQ = 1; // 給脈沖信號
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20寫壹個字節****************/
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/**************讀取ds18b20當前溫度************/unsigned char *ReadTemperature()
{
unsigned char tt[2];
Init_DS18B20();
WriteOneChar(0xCC); // 跳過讀序號列號的操作
WriteOneChar(0x4E); // //寫入"寫暫存器"命令,修改TH和TL和分辯率配置寄存器
//先寫TH,再寫TL,最後寫配置寄存器
WriteOneChar(100); //寫入想設定的溫度報警上限
WriteOneChar(4); //寫入想設定的溫度報警下限
WriteOneChar(0x7f); //寫配置寄存器,格式為0 R1 R0 1,1 1 1 1
//R1R0=00分辨率婁9位,R1R0=11分辨率為12位
delay_18B20(80); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); // 跳過讀序號列號的操作
WriteOneChar(0x44); // 啟動溫度轉換
delay_18B20(80); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器等(***可讀9個寄存器) 前兩個就是溫度
delay_18B20(80);
tt[0]=ReadOneChar(); //讀取溫度值低位
tt[1]=ReadOneChar();
return(tt);
}
void covert1(void) //將溫度轉換為LCD顯示的數據
{
unsigned char TH=110,TL=-20;
unsigned char x=0x00,y=0x00;
pt=ReadTemperature();
t[0]=*pt;pt++;t[1]=*pt;
if(t[1]>0x07) //判斷正負溫度
{wendu3=1; //0x2d為"-"的ASCII碼
t[1]=~t[1]; /*下面幾句把負數的補碼*/
t[0]=~t[0]; /* 換算成絕對值*********/
x=t[0]+1; /***********************/
t[0]=x; /***********************/
if(x>255) /**********************/
t[1]++; /*********************/
}
else wendu3=0; //0xfe為變"+"的ASCII碼
t[1]<<=4; //將高字節左移4位
t[1]=t[1]&0x70; //取出高字節的3個有效數字位
x=t[0]; //將t[0]暫存到X,因為取小數部分還要用到它
x>>=4; //右移4位
x=x&0x0f; //和前面兩句就是取出t[0]的高四位
x=t[1]|x; //將高低字節的有效值的整數部分拼成壹個字節
wendu=x;
t[0]=t[0]&0x0f; //取有效的兩位小數
x=t[0];
wendu1=dotcode[x]; //分離出百分位
}
unsigned char LCD_Wait(void)
{rs=0;
rw=1; delay(1);
en=1; delay(1);
// while(DBPort&0x80);//在用Proteus仿真時,註意用屏蔽此語句,在調用GotoXY()時,會進入死循環,
//可能在寫該控制字時,該模塊沒有返回寫入完備命令,即DBPort&0x80==0x80
//實際硬件時打開此語句
en=0;
return DBPort;
}
void LCD_Write(bit style, unsigned char input)
{en=0;rs=style;
rw=0; _nop_();
DBPort=input; _nop_();//註意順序
en=1; _nop_();//註意順序
en=0; _nop_();
LCD_Wait();
}
void GotoXY(unsigned char x, unsigned char y)
{
if(y==0)
LCD_Write(0,0x80|x);
if(y==1)
LCD_Write(0,0x80+0x40+x);
}
//sbit s4=P0^3;
uchar num,count,flag,flag1,flag2,flag3,s1num,j;
void keyscan();
write_1602com(uchar com)//液晶寫入指令函數
{en=0;
rs=0;//置為寫入命令
rw=0;_nop_();P0=com;//送入數據
_nop_();
en=1;//拉高使能端
_nop_();
en=0;//完成高脈沖
_nop_();LCD_Wait();
}
write_1602dat(uchar dat)
{en=0;
rs=1;//置為寫入數據
rw=0;_nop_();P0=dat;//送入數據
_nop_();
en=1;_nop_();en=0;
_nop_();
LCD_Wait();
}
void write_sfm(uchar add,uchar dat)//寫時分秒
{uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(add+er);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
void write_nyr(uchar add,uchar dat)//寫時分秒
{uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(add+yh);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
void write(uchar add)//寫時分秒
{write_1602com(add+yh);
write_1602dat(58);
}
void init()
{write_1602com(0x38);//設置液晶工作模式
write_1602com(0x0c);//開顯示不顯示光標
write_1602com(0x06);//整屏不移動,指針加壹
write_1602com(0x01);
write_1602com(yh);//字符寫入的位置
for(a=0;a<16;a++)
{write_1602dat(tab3[a]);
//delay(3);
}
write_1602com(er+2);
for(a=0;a<16;a++)
{
write_1602dat(tab2[a]);
//delay(3);
}
}
keys()
{unsigned char hang,lie,key;
if(P3!=0x0f)
delay(5);
if(P3!=0x0f)
{switch(P3&0x0f)
{case 0x0e:lie=0;break;
case 0x0d:lie=1;break;
case 0x0b:lie=2;break;
case 7:lie=3;break;
}
P3=0xf0;
P3=0xf0;
switch(P3&0xf0)
{case 0xe0:hang=0;break;
case 0xd0:hang=1;break;
case 0xb0:hang=2;break;
case 0x70:hang=3;break;
}
P3=0x0f;
while(P3!=0x0f)
P1_1=1;
P1_1=0;key=tab[hang][lie];
else
key=20;
speak=0;
return(key);
}
char kbscan() //鍵盤掃描
{int key;key=keys();
if(key==10)
{key1n++;
if(key1n==6)
key1n=0;
}
if(key==12)
{
key3n++;
if(key3n==2)
key3n=0;
}
if(key==11)
{
key2n++;
if(key2n==6)
key2n=0;
}
while(key1n!=0)
{
key=keys();
if(key==10)
{
key1n++;
if(key1n==7)
key1n=0;
}
switch(key1n)
{
case 1: TR1=0;//關閉定時器
//TR1=0;
write_1602com(er+0x02);//寫入光標位置
write_1602com(0x0f);//設置光標為閃爍
break;
case 2: write_1602com(er+3);//fen
//write_1602com(0x0f);
break;
case 3: write_1602com(er+5);//shi
//write_1602com(0x0f);
break;
case 4: write_1602com(er+6);//fen
//write_1602com(0x0f)
break;
case 5: write_1602com(er+8);//shi
//write_1602com(0x0f);
break;
case 6: write_1602com(er+9);//fen
//write_1602com(0x0f);
break;
case 0:
write_1602com(0x0c);//設置光標不閃爍
TR1=1;//打開定時器
break;
}
if(key<10)
{
write_1602dat(0x30+key);
switch(key1n)
{
case 1: shi=shi%10+key*10;break;
case 2: shi=shi/10*10+key;
break;
case 3: fen=fen%10+key*10;
break;
case 4: fen=fen/10*10+key;
break;
case 5: miao=miao%10+key*10;
break;
case 6: miao=miao/10*10+key;
break;
case 0:
write_1602com(0x0c);//設置光標不閃爍
TR1=1;//打開定時器
break;
}
}
while(key2n!=0)
{key=keys();speak=0;
if(key==11)
{key2n++;
if(key2n==4)
key2n=0;
}
switch(key2n)
{case 1: TR1=0;//關閉定時器
//TR1=0;
write_1602com(er+13);//寫入光標位置
write_1602com(0x0f);//設置光標為閃爍
break;
case 2: write_1602com(er+14);//fen
//write_1602com(0x0f);
break;case 3: write_1602com(er+15);//shi
//write_1602com(0x0f);
break;
case 0:
write_1602com(0x0c);//設置光標不閃爍
TR1=1;//打開定時器
break;
}
if(key<10)
{write_1602dat(0x30+key);
switch(key2n)
{
case 2: shu=shu%10+key*10;
break;
case 3: shu=shu/10*10+key;
break;
case 1: shu1=key*100;
break;
case 0:
write_1602com(0x0c);//設置光標不閃爍
TR1=1;//打開定時器
break;
}
miao1=shu;r=1;
}
}
}
main()
{nian=0;nianb=20;
yue=0;miao1=1;
init();
TMOD = 0x10;
TH1 = 0xFF;
TL1 = 0x0E0;
EA = 1;
ET1 = 1;
TR1 = 1;
P1=0X00;
covert1();
P3=0X0F;
while(1)
{kbscan() ;
covert1();
if(miao1==0)
wendu4=wendu;
write_sfm(8,miao);
write_sfm(5,fen);
write_sfm(2,shi);
write_nyr(5,wendu);
write_nyr(8,wendu1);
if(key3n==1)
write_nyr(12,wendu4);
else
{write_1602com(yh+12);//字符寫入的位置
write_1602dat(' ');
write_1602dat(' ');}
}
}
void timer1() interrupt 3{
TH1 = 0x3c;TL1 = 0x0b0;
tt++;
if(tt==20)
{tt=0;miao++;
if(r==1)
miao1--;
}
if(miao==60)
{miao=0;fen++;}
if(fen==60)
{fen=0;
shi++;
}
}