找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 7624|回復(fù): 10
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)時(shí)鐘溫度計(jì)小制作

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:83710 發(fā)表于 2015-6-24 22:14 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
     最近利用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;
}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:62973 發(fā)表于 2015-6-25 17:04 | 只看該作者
精度如何;誤差率多少!
回復(fù)

使用道具 舉報(bào)

板凳
ID:61954 發(fā)表于 2015-6-26 07:48 | 只看該作者
晶振多少M(fèi)HZ?上原理圖啊
回復(fù)

使用道具 舉報(bào)

地板
ID:19947 發(fā)表于 2015-8-21 13:42 | 只看該作者
是個(gè)沃,樓主你發(fā)下原理圖嗎,我們小輩學(xué)習(xí)學(xué)習(xí)!
回復(fù)

使用道具 舉報(bào)

5#
ID:19947 發(fā)表于 2015-9-5 21:29 | 只看該作者
程序中晶振已經(jīng)提示了,可是,1302需不需要電池供電?
回復(fù)

使用道具 舉報(bào)

6#
ID:1 發(fā)表于 2015-9-6 13:26 來自手機(jī) | 只看該作者
wxgzf 發(fā)表于 2015-9-5 21:29
程序中晶振已經(jīng)提示了,可是,1302需不需要電池供電?

晶振需要電池,不然無法斷電保存時(shí)間。
回復(fù)

使用道具 舉報(bào)

7#
ID:258202 發(fā)表于 2017-12-6 15:37 | 只看該作者
大神,厲害了
回復(fù)

使用道具 舉報(bào)

8#
ID:256736 發(fā)表于 2017-12-6 17:36 | 只看該作者
這個(gè)不錯(cuò)啊,能有原理圖就好了,初學(xué)者的好制作。
回復(fù)

使用道具 舉報(bào)

9#
ID:275642 發(fā)表于 2018-1-17 18:49 | 只看該作者
我是初學(xué)者,也想要原理圖,謝謝!
回復(fù)

使用道具 舉報(bào)

10#
ID:257136 發(fā)表于 2018-2-8 14:07 | 只看該作者
應(yīng)該弄個(gè)時(shí)間日期溫度自動(dòng)輪流顯示的。我剛自己做了個(gè)時(shí)鐘,想實(shí)現(xiàn)時(shí)間日期溫度輪流顯示,可是試了好多辦法都不行,還是只能顯示時(shí)間。
回復(fù)

使用道具 舉報(bào)

11#
ID:286600 發(fā)表于 2018-3-5 09:52 | 只看該作者
chen19890708 發(fā)表于 2018-2-8 14:07
應(yīng)該弄個(gè)時(shí)間日期溫度自動(dòng)輪流顯示的。我剛自己做了個(gè)時(shí)鐘,想實(shí)現(xiàn)時(shí)間日期溫度輪流顯示,可是試了好多辦法 ...

這很容易,設(shè)一個(gè)標(biāo)志位,0--顯時(shí)間,1--顯溫度,在走時(shí)程序中隔幾秒取反一次該位。這是我用過的方法。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表