|
最近利用DS1302與DS18B20做了一個(gè)能顯示當(dāng)前時(shí)間、日期、溫度的東西。有三個(gè)按鍵,正常運(yùn)行時(shí)顯示當(dāng)前的時(shí)間,利用按鍵2、3可以切換到日期與溫度。按下按鍵1進(jìn)入設(shè)置時(shí)間狀態(tài),在設(shè)置時(shí)間狀態(tài)利用按鍵2、3可調(diào)整時(shí)間與日期。調(diào)整好后不進(jìn)行任何操作6秒退出設(shè)置狀態(tài)。
實(shí)物圖:
顯示當(dāng)前時(shí)間:(11時(shí):24分:47秒)

顯示當(dāng)前日期:(09年:01月:15日)
顯示當(dāng)前溫度:(17.2度)

源程序:
#include <reg51.h>
#include<intrins.h>
sbit dq = P0^0;//定義P0.0為DS18B20的數(shù)據(jù)線
sbit t_rst=P0^2;//DS1302數(shù)據(jù)線
sbit t_clk=P0^4;
sbit t_io=P0^3;
sbit P2_0=P2^0;//按鍵
sbit P2_1=P2^1;
sbit P2_2=P2^2;
sbit P3_0=P3^0;//顯示
sbit P3_1=P3^1;
sbit P3_2=P3^2;
sbit P3_3=P3^3;
sbit P3_4=P3^4;
sbit P3_5=P3^5;
sbit P3_6=P3^6;
sbit P3_7=P3^7;
void delay(unsigned char i);//定義延時(shí)函數(shù)
bit init_18b20();//定義DS18B20初始化復(fù)位函數(shù)
void w_18b20(unsigned char dat);//定義寫DS18B20函數(shù)
unsigned char r_18b20();//定義讀DS18B20函數(shù)
void GetTem(void);//定義獲得溫度函數(shù)
void Temdisp(void);//溫度顯示函數(shù)
void in_1302(unsigned char tdat);//定義寫一個(gè)字節(jié)到DS1302函數(shù)
unsigned char out_1302(void);//定義從DS1302讀一個(gè)字節(jié)函數(shù)
void w_1302(unsigned char ucAddr, unsigned char ucDa);//定義寫DS1302函數(shù)
void set1302(void);//設(shè)置時(shí)間
void get1302(void);//讀取時(shí)間
void timedisp(void);//時(shí)間顯示函數(shù)
void datedisp(void);//日期顯示函數(shù)
void setbom(void);
unsigned char TemL;//溫度低位
unsigned char TemH;//溫度高位
unsigned char Tem1;//轉(zhuǎn)換后溫度個(gè)位
unsigned char Tem2;//轉(zhuǎn)換后溫度十位
unsigned char Led[4];
unsigned char dis[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//不帶點(diǎn)的0~9
unsigned char dis1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};//帶點(diǎn)的0~9
bit TempS;//溫度符號(hào)位
unsigned int ms;
unsigned char time[7]={0x00,0x24,0x11,0x15,0x01,0x04,0x09};
main()
{
set1302();
while(1)
{
if(!P2_1){get1302();datedisp();}
if(!P2_2){GetTem();Temdisp();}
if(P2_1 && P2_2){ get1302();timedisp();}
if(!P2_0)
{
TMOD=0x01; EA=1;ET0=1;TH0=0xFC;TL0=0x66;
while(!P2_0);delay(255);delay(255);delay(255);
setbom();
}
}
}
void delay (unsigned char i) //延時(shí)程序,12M晶振下延時(shí)為:(2i+3)us ,i=0~255
{
while (--i);
}
bit init_18b20() //初始化,init_18b20=0初始化成功,init_18b20=1初始化失敗,可能18b20不存在
{
bit SS;
dq=1;
_nop_();
dq=0;
delay(255);
dq=1;
delay(34);
SS=dq;
delay(120);
return (SS);
}
void w_18b20(unsigned char dat) //寫一個(gè)字節(jié)到18b20
{
unsigned char i=0;
for(i=8;i>0;i--)
{
dq=0;
delay(5);
dq=dat&0x01;
delay(22);//延時(shí)
dq=1;
dat>>=1;
}
}
unsigned char r_18b20()//從18b20讀一個(gè)字節(jié)
{
unsigned char i=0;
unsigned char dat=0;
for(i=8;i>0;i--)
{
dq=0;
dat>>=1;
dq=1;
delay(6);
if(dq) dat|=0x80;
delay(22);
}
return(dat);
}
void GetTem() //獲得溫度函數(shù)
{
bit SS;
unsigned char A;
unsigned long Tem;//溫度變量
unsigned char TemLH;//低位溫度高位
unsigned char TemLL;//低位溫度低位
do SS=init_18b20();while(SS);//初始化DS18B20,檢測(cè)是否存在,存在繼續(xù)
w_18b20(0xCC);//跳過ROM匹配
w_18b20(0x44);//開始溫度轉(zhuǎn)換
do//等待溫度轉(zhuǎn)換完成
{
dq=0;
_nop_();
_nop_();
_nop_();
dq=1;
delay(6);
SS=dq;
delay(22);
Temdisp();
}
while (!SS);//溫度轉(zhuǎn)換完成后繼續(xù)
init_18b20();//復(fù)位
w_18b20(0xCC);//跳過ROM匹配
w_18b20(0xBE);//讀取溫度值
TemL=r_18b20();//低位
TemH=r_18b20();//高位
if (TemH&0x80)//把讀取的溫度值進(jìn)行轉(zhuǎn)換,并存進(jìn)Led[]中
{
TemH=~TemH;
TemL=(~TemL)+1;
TempS=1;
Led[0]=0x40;//顯示負(fù)號(hào)
}
else TempS=0;
TemLH=TemL>>4;
TemLL=TemL&0x0F;
Tem=(TemH*16 + TemLH + TemLL*0.0625)*10000;
A=Tem/100000;
Led[1]=dis[A];
Tem=Tem%100000;
A=Tem/10000;
Led[2]=dis1[A];
Tem=Tem%10000;
A=Tem/1000;
Led[3]=dis[A];
}
void Temdisp()//溫度顯示函數(shù),符號(hào)位(為負(fù)號(hào)顯示),十位(為0不顯示,個(gè)位(帶小數(shù)點(diǎn)),小數(shù)位
{
if (TempS==1)//溫度為負(fù)則顯示負(fù)號(hào),否則不顯示
{
if (Led[1]!=0x3f)
{
P1=Led[0];
P3_5=0;
delay(255);
P3_5=1;
}
else
{
P1=Led[0];
P3_4=0;
delay(255);
P3_4=1;
}
}
if (Led[1]!=0x3f)//十位不為零則顯示,否則不顯示
{
P1=Led[1];
P3_4=0;
delay(255);
P3_4=1;
}
P1=Led[2];//個(gè)位
P3_3=0;
delay(255);
P3_3=1;
P1=Led[3];//小數(shù)位
P3_2=0;
delay(255);
P3_2=1;
}
void in_1302(unsigned char tdat) //寫一個(gè)字節(jié)到DS1302
{
unsigned char i;
for(i=8;i>0;i--)
{
t_io=tdat&0x01;
_nop_();
t_clk=1;
_nop_();
t_clk=0;
tdat>>=1;
}
}
unsigned char out_1302(void) //從DS1302讀一個(gè)字節(jié)
{
unsigned char i;
unsigned char tdat;
for(i=8;i>0;i--)
{
tdat>>=1;
if(t_io){tdat=tdat|0x80;}
t_clk=1;
_nop_();
t_clk=0;
}
return(tdat);
}
void w_1302(unsigned char ucAddr, unsigned char ucDa) //往DS1302寫入數(shù)據(jù),先寫地址,后寫命令/數(shù)據(jù)
{
t_rst = 0;
t_clk = 0;
t_rst = 1;
in_1302(ucAddr); /* 地址,命令 */
in_1302(ucDa); /* 寫1Byte數(shù)據(jù)*/
t_clk = 1;
t_rst =0;
}
unsigned char r_1302(unsigned char ucAddr)//從DS1302讀出數(shù)據(jù),先寫地址,后讀命令/數(shù)據(jù)
{
unsigned char ucDa;
t_rst = 0;
t_clk = 0;
t_rst = 1;
in_1302(ucAddr); /* 地址,命令 */
ucDa = out_1302(); /* 讀1Byte數(shù)據(jù) */
t_clk = 1;
t_rst =0;
return(ucDa);
}
void set1302(void)
{
unsigned char i;
unsigned char ucAddr = 0x80;
w_1302(0x8e,0x00); /* 控制命令,WP=0,寫操作?*/
for(i =0;i<7;i++)
{
w_1302(ucAddr,time[ i]); /* 秒 分 時(shí) 日 月 星期 年 */
ucAddr +=2;
}
w_1302(0x8e,0x80); /* 控制命令,WP=1,寫保護(hù)?*/
}
void get1302(void)
{
unsigned char i;
unsigned char ucAddr = 0x81;
for (i=0;i<7;i++)
{
time = r_1302(ucAddr);/*格式為: 秒 分 時(shí) 日 月 星期 年 */
ucAddr += 2;
}
}
void timedisp(void)
{
unsigned char m;unsigned char n;
m=time[0]>>4;n=time[0]&0x0f;//顯示秒
P1=dis[m];
P3_3=0;
delay(255);delay(255);delay(255);delay(255);
P3_3=1;
P1=dis1[n];
P3_2=0;
delay(255);delay(255);delay(255);delay(255);
P3_2=1;
m=time[1]>>4;n=time[1]&0x0f;//顯示分
P1=dis[m];
P3_5=0;
delay(255);delay(255);delay(255);delay(255);
P3_5=1;
P1=dis1[n];
P3_4=0;
delay(255);delay(255);delay(255);delay(255);
P3_4=1;
m=time[2]>>4;n=time[2]&0x0f;//顯示時(shí)
P1=dis[m];
P3_7=0;
delay(255);delay(255);delay(255);delay(255);
P3_7=1;
P1=dis1[n];
P3_6=0;
delay(255);delay(255);delay(255);delay(255);
P3_6=1;
}
void datedisp(void)
{
unsigned char m;unsigned char n;
m=time[3]>>4;n=time[3]&0x0f;//顯示日
P1=dis[m];
P3_3=0;
delay(255);delay(255);delay(255);delay(255);
P3_3=1;
P1=dis1[n];
P3_2=0;
delay(255);delay(255);delay(255);delay(255);
P3_2=1;
m=time[4]>>4;n=time[4]&0x0f;//顯示月
P1=dis[m];
P3_5=0;
delay(255);delay(255);delay(255);delay(255);
P3_5=1;
P1=dis1[n];
P3_4=0;
delay(255);delay(255);delay(255);delay(255);
P3_4=1;
m=time[6]>>4;n=time[6]&0x0f;//顯示年
P1=dis[m];
P3_7=0;
delay(255);delay(255);delay(255);delay(255);
P3_7=1;
P1=dis1[n];
P3_6=0;
delay(255);delay(255);delay(255);delay(255);
P3_6=1;
}
void setbom(void)
{
unsigned char i,m,n;
TR0=1;
while(ms<6000)
{
if(!P2_0)
{
i++;ms=0;
if(i==5) {i=6;}
if(i==7) {i=0;}
while(!P2_0);
delay(255);delay(255);delay(255);
ms=0;
}
if(!P2_1)
{
m=time>>4; n=time&0x0f;
if(n!=9) n=n+1;
else{m=m+1;n=0;}
time=(m<<4)|n;
while(!P2_1);
delay(255);delay(255);delay(255);
ms=0;
}
if(!P2_2)
{
m=time>>4; n=time&0x0f;
if(m!=0 && n==0) {n=9;m=m-1;}
else if(n!=0) {n=n-1;}
time=(m<<4)|n;
while(!P2_2);
delay(255);delay(255);delay(255);
ms=0;
}
if (time[0]==0x60)time[0]=0x00;
if (time[1]==0x60)time[1]=0x00;
if (time[2]==0x24)time[2]=0x00;
if (time[3]==0x32)time[3]=0x00;
if (time[4]==0x13)time[4]=0x00;
if (time[6]==0x99)time[6]=0x00;
set1302();
if(i<3){get1302();timedisp();}
else {get1302();datedisp();}
}
TR0=0;
ms=0;
}
void time0() interrupt 1 //定時(shí)器0中斷
{
TR0=0;
TH0=0xFC;TL0=0x66;
ms++;
TR0=1;
}
|
|