標(biāo)題:
多功能單片機電子鐘Proteus仿真+程序 LCD1602顯示
[打印本頁]
作者:
gms335
時間:
2019-11-13 10:31
標(biāo)題:
多功能單片機電子鐘Proteus仿真+程序 LCD1602顯示
(1)在1602液晶上顯示年、月、日、時、分、秒,并且按秒實時更新顯示。
(2)在1602液晶上顯示當(dāng)前采集到的環(huán)境溫度。
(3)當(dāng)環(huán)境溫度低于0℃和高于34℃時,蜂鳴器報警。
(4)每次開機時,蜂鳴器響。
(5)能夠使用板上的按鍵調(diào)節(jié)各參數(shù),按鍵可設(shè)計4個有效鍵,分別為切換鍵、加鍵、減鍵、跳出鍵。
(6)利用 DS1302時鐘芯片通過簡單的串行通信與單片機進行通信,時鐘/日歷電路能夠?qū)崟r提供年、月、日、時、分、秒信息,采用雙電源供電,當(dāng)外部電源掉電時能夠利用后備電池準(zhǔn)確計時的特性,設(shè)計實現(xiàn)斷電時間不停、再次上電時時間仍然準(zhǔn)確顯示在液晶上的功能。
每次開機時,蜂鳴器長鳴一身,按下功能鍵可以調(diào)節(jié)時間、年、月、日,加鍵和減鍵可以實現(xiàn)時間、年、月、日的加減,跳出鍵可以結(jié)束當(dāng)前正在執(zhí)行的時間調(diào)整,該電子表附帶有溫度報警功能,當(dāng)溫度超過34℃和低于0℃時,蜂鳴器長鳴報警。
51hei.png
(15.78 KB, 下載次數(shù): 39)
下載附件
2019-11-13 14:58 上傳
51hei.png
(4.49 KB, 下載次數(shù): 33)
下載附件
2019-11-13 14:58 上傳
單片機源程序如下:
/***************************************************************************************************************
基于DS18B20、DS1302、單片機的時鐘與溫度測控
***************************************************************************************************************/
#include <REG52.H>
#include "LCD1602.H"
#include "DS18B20.H"
#include "DS1302.H"
#define uint unsigned int
#define uchar unsigned char
#define TH 35 //設(shè)置溫度上限
extern unsigned char week_value[2],TempBuffer[5]; //聲明外部變量
extern int temp_value;
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,時到日,月,年位閃的計數(shù)
sbit Set = P3^0; //模式切換鍵
sbit Up = P3^1; //加法按鈕
sbit Down = P3^2; //減法按鈕
sbit out = P3^3; //立刻跳出調(diào)整模式按鈕
sbit deng = P1^1;
char done,count,temp,flag,up_flag,down_flag;
char SD=1;
void show_time(); //液晶顯示函數(shù)聲明
/**************************************************************
延時子程序
**************************************************************/
void mdelay(uint delay)
{ uint i;
for(;delay>0;delay--)
{for(i=0;i<62;i++) //1ms延時.
{;}
}
}
/**************************************************************
升序按鍵
**************************************************************/
void Upkey()
{
Up=1;
if(Up==0)
{
mdelay(8);
switch(count)
{case 1:
temp=Read1302(DS1302_SECOND); //讀取秒數(shù)
temp=temp+1; //秒數(shù)加1
up_flag=1; //數(shù)據(jù)調(diào)整后更新標(biāo)志
if((temp&0x7f)>0x59) //超過59秒,清零
temp=0;
break;
case 2:
temp=Read1302(DS1302_MINUTE); //讀取分?jǐn)?shù)
temp=temp+1; //分?jǐn)?shù)加1
up_flag=1;
if(temp>0x59) //超過59分,清零
temp=0;
break;
case 3:
temp=Read1302(DS1302_HOUR); //讀取小時數(shù)
temp=temp+1; //小時數(shù)加1
up_flag=1;
if(temp>0x23) //超過23小時,清零
temp=0;
break;
/*case 4:
temp=Read1302(DS1302_WEEK); //讀取星期數(shù)
temp=temp+1; //星期數(shù)加1
up_flag=1;
if(temp>0x7)
temp=1;
break; */
case 5:
temp=Read1302(DS1302_DAY); //讀取日數(shù)
temp=temp+1; //日數(shù)加1
up_flag=1;
if(temp>0x31)
temp=1;
break;
case 6:
temp=Read1302(DS1302_MONTH); //讀取月數(shù)
temp=temp+1; //月數(shù)加1
up_flag=1;
if(temp>0x12)
temp=1;
break;
case 7:
temp=Read1302(DS1302_YEAR); //讀取年數(shù)
temp=temp+1; //年數(shù)加1
up_flag=1;
if(temp>0x85)
temp=0;
break;
default:break;
}
while(Up==0);
}
}
/**************************************************************
降序按鍵
**************************************************************/
void Downkey()
{
Down=1;
if(Down==0)
{
mdelay(8);
switch(count)
{case 1:
temp=Read1302(DS1302_SECOND); //讀取秒數(shù)
temp=temp-1; //秒數(shù)減1
down_flag=1; //數(shù)據(jù)調(diào)整后更新標(biāo)志
if(temp==0x7f) //小于0秒,返回59秒
temp=0x59;
break;
case 2:
temp=Read1302(DS1302_MINUTE); //讀取分?jǐn)?shù)
temp=temp-1; //分?jǐn)?shù)減1
down_flag=1;
if(temp==-1)
temp=0x59; //小于0分,返回59分
break;
case 3:
temp=Read1302(DS1302_HOUR); //讀取小時數(shù)
temp=temp-1; //小時數(shù)減1
down_flag=1;
if(temp==-1)
temp=0x23;
break;
/*case 4:
temp=Read1302(DS1302_WEEK); //讀取星期數(shù)
temp=temp-1; //星期數(shù)減1
down_flag=1;
if(temp==0)
temp=0x7;;
break; */
case 5:
temp=Read1302(DS1302_DAY); //讀取日數(shù)
temp=temp-1; //日數(shù)減1
down_flag=1;
if(temp==0)
temp=31;
break;
case 6:
temp=Read1302(DS1302_MONTH); //讀取月數(shù)
temp=temp-1; //月數(shù)減1
down_flag=1;
if(temp==0)
temp=12;
break;
case 7:
temp=Read1302(DS1302_YEAR); //讀取年數(shù)
temp=temp-1; //年數(shù)減1
down_flag=1;
if(temp==-1)
temp=0x85;
break;
default:break;
}
while(Down==0);
}
}
/**************************************************************
模式選擇按鍵
**************************************************************/
void Setkey()
{
Set=1;
if(Set==0)
{
mdelay(8);
count=count+1; //Setkey按一次,count就加1
done=1; //進入調(diào)整模式
while(Set==0);
}
}
/**************************************************************
跳出調(diào)整模式,返回默認(rèn)顯示
**************************************************************/
void outkey()
{ uchar Second;
out=1;
if(out==0)
{
count=0;
hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
Second=Read1302(DS1302_SECOND);
Write1302(0x8e,0x00); //寫入允許
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止寫入
done=0;
while(out==0);
}
}
/**************************************************************
按鍵功能執(zhí)行
**************************************************************/
void keydone()
{ uchar Second;
if(flag==0) //關(guān)閉時鐘,停止計時
{ Write1302(0x8e,0x00); //寫入允許
temp=Read1302(0x80);
Write1302(0x80,temp|0x80);
Write1302(0x8e,0x80); //禁止寫入
flag=1;
}
Setkey(); //掃描模式切換按鍵
switch(count)
{case 1:do //count=1,調(diào)整秒
{
outkey(); //掃描跳出按鈕
Upkey(); //掃描加按鈕
Downkey(); //掃描減按鈕
if(up_flag==1||down_flag==1) //數(shù)據(jù)更新,重新寫入新的數(shù)據(jù)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x80,temp|0x80); //寫入新的秒數(shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_sec++; //位閃計數(shù)
if(hide_sec>3)
hide_sec=0;
show_time(); //液晶顯示數(shù)據(jù)
}while(count==2);break;
case 2:do //count=2,調(diào)整分
{
hide_sec=0;
outkey();
Upkey();
Downkey();
if(temp>0x60)
temp=0;
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x82,temp); //寫入新的分?jǐn)?shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_min++;
if(hide_min>3)
hide_min=0;
show_time();
}while(count==3);break;
case 3:do //count=3,調(diào)整小時
{
hide_min=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x84,temp); //寫入新的小時數(shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_hour++;
if(hide_hour>3)
hide_hour=0;
show_time();
}while(count==4);break;
/* case 4:do //count=4,調(diào)整星期
{
hide_hour=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x8a,temp); //寫入新的星期數(shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_week++;
if(hide_week>3)
hide_week=0;
show_time();
}while(count==5);break; */
case 5:do //count=5,調(diào)整日
{
hide_week=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x86,temp); //寫入新的日數(shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_day++;
if(hide_day>3)
hide_day=0;
show_time();
}while(count==6);break;
case 6:do //count=6,調(diào)整月
{
hide_day=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x88,temp); //寫入新的月數(shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_month++;
if(hide_month>3)
hide_month=0;
show_time();
}while(count==7);break;
case 7:do //count=7,調(diào)整年
{
hide_month=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x8c,temp); //寫入新的年數(shù)
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_year++;
if(hide_year>3)
hide_year=0;
show_time();
}while(count==8);break;
case 8: count=0;hide_year=0; //count8, 跳出調(diào)整模式,返回默認(rèn)顯示狀態(tài)
Second=Read1302(DS1302_SECOND);
Write1302(0x8e,0x00); //寫入允許
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止寫入
done=0;
break; //count=7,開啟中斷,標(biāo)志位置0并退出
default:break;
}
}
/**************************************************************
液晶顯示程序
**************************************************************/
void show_time()
{
DS1302_GetTime(&CurrentTime); //獲取時鐘芯片的時間數(shù)據(jù)
TimeToStr(&CurrentTime); //時間數(shù)據(jù)轉(zhuǎn)換液晶字符
DateToStr(&CurrentTime); //日期數(shù)據(jù)轉(zhuǎn)換液晶字符
ReadTemp(); //開啟溫度采集程序
temp_to_str(); //溫度數(shù)據(jù)轉(zhuǎn)換成液晶字符
GotoXY(12,1); //液晶字符顯示位置
Print(TempBuffer); //顯示溫度
GotoXY(0,1);
Print(CurrentTime.TimeString); //顯示時間
GotoXY(0,0);
Print(CurrentTime.DateString); //顯示日期
GotoXY(15,0);
/*Print(week_value); //顯示星期
GotoXY(11,0);
Print("Week"); //在液晶上顯示 字母 week */
mdelay(500); //掃描延時
}
/**************************************************************
報警檢測與取消
**************************************************************/
void warming()
{
if(temp_value>=TH)
{if(SD==1&&SD!=0)ET0=1;}
else {deng=0;ET0=0;SD=1;}
out=1;
if(out==0){ET0=0;SD=0;}
}
/**************************************************************
主程序
**************************************************************/
main()
{
TMOD=0x02; //設(shè)置模式為定時器T0的模式2 (8位自動重裝計數(shù)初值的計數(shù)值)
TH0=0x03; //設(shè)置計數(shù)器初值,靠TH0存儲重裝的計數(shù)值
TL0=0x03;
TR0=1; //啟動T0
ET0=0; //關(guān)定時器T0中斷
EA=1;
P1=0;
flag=1; //時鐘停止標(biāo)志
LCD_Initial(); //液晶初始化
Init_DS18B20( ) ; //DS18B20初始化
Initial_DS1302(); //時鐘芯片初始化
up_flag=0; //調(diào)整標(biāo)志位置零
down_flag=0;
done=0; //進入默認(rèn)液晶顯示
while(1)
{
while(done==1)
{keydone(); //進入調(diào)整模式
warming();
}
while(done==0)
{
show_time(); //液晶顯示數(shù)據(jù)
flag=0;
Setkey(); //掃描各功能鍵
warming();
}
warming();
}
}
/**************************************************************
定時器中斷
**************************************************************/
void t0 (void) interrupt 1 using 1
{deng=!deng;}
復(fù)制代碼
所有資料51hei提供下載:
仿真程序.7z
(409.03 KB, 下載次數(shù): 106)
2019-11-13 15:01 上傳
點擊文件名下載附件
多功能電子鐘課程設(shè)計
下載積分: 黑幣 -5
作者:
waxhy32145
時間:
2020-4-22 17:08
感謝感謝,打算學(xué)習(xí)
作者:
2653701223
時間:
2020-4-25 10:28
博主真心厲害,向博主學(xué)習(xí)
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1