紅外時鐘日歷12864(帶字庫) DS1302 DS18B20.rar
(123.74 KB, 下載次數: 64)
2017-6-26 08:40 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
#include <reg52.h>
#include "LCD12864.h"
#include "DS1302.h"
#include "DS18B20.h"
#include "nongli.h"
#include "displaytime.h"
#include "zk.h"
#include "bell.h"
#include "HW.H"
#include "delay.h"
#define uint unsigned int
#define uchar unsigned char
/*--------------------定義按鍵-----------------------------------------------*/
sbit K1 = P1^0; //K1-設置
sbit K2 = P1^1; //K2-確認、返回
sbit K3 = P1^2; //K3-加
sbit K4 = P1^3; //K4-減
//K5=P1^4,K5-控制鬧鐘的打開與關閉,在"hw.h"中定義
/*---------------------函數聲明------------------------------*/
void ds_w0(void);
void ds_w(void);
void Conver_week(bit c,uchar year,uchar month,uchar day);
/*-----------------------------定義全局變量------------------------------*/
bit w=0; //調時標志位
unsigned char yy,mo,dd,xq,hh,mm,ss,month_moon,day_moon,week,tiangan,dizhi,moontemp1,moontemp2;//定義時間映射全局變量(專用寄存器)
signed char address,item,item0,max,mini;
unsigned char clk_ala[2]={0x00,0x00};//鬧鐘數據存放初,始值為00:00
unsigned char hour,minute,time;//用于鬧鈴的設置
/*-----------------------------日期、時間設置函數-----------------------------*/
void tiaozheng(void){
yy = read_clock(0x8d);//調用1302時鐘數據中的年數據,從地址0x8d中
mo = read_clock(0x89);//調用1302時鐘數據中的月數據,從地址0x89中
dd = read_clock(0x87);//從1302芯片中讀取日數據,從地址0x87中
week = read_clock(0x8b);//從1302芯片中讀取星期數據,從地址0x8b中
//----------------------------------
lcm_w_test(0,0x80);
lcm_w_word("20");//顯示內容字符20
lcm_w_test(1,(yy/16)+0x30);//函數參數1,代表本行寫數據,YY/16+0X30得出年十位數字的顯示碼地址,送顯示
lcm_w_test(1,yy%16+0x30);//函數
lcm_w_word("年");
//----------------------------------
lcm_w_test(1,(mo/16)+0x30);
lcm_w_test(1,mo%16+0x30);//與16取余數,得到月份的個位數,加0x30得到該數字的液晶內定顯示碼送顯示
lcm_w_word("月");//調用字符顯示函數,顯示文字 月
//----------------------------------
/*
lcm_w_test(0,0x88);//第一個參數0,表示本行寫入LCM的是指令,指定顯示位置88H(第三行左端)
lcm_w_word("星期");//調用字符顯示函數,顯示文字 星期
lcm_w_test(1,mo%16+0x30);//與16取余數,得到月份的個位數,加0x30得到該數字的液晶內定顯示碼送顯示
*/
//----------------------------------
lcm_w_test(1,(dd/16)+0x30);
lcm_w_test(1,dd%16+0x30);//第一個1參數,表示本行寫數據,日數據與16取余得個位數,加0x30得到顯示碼
lcm_w_word("日");//顯示字符 日
//----------------------------------
if(read_clock(0x85) != hh){//如果程序中的小時與1302芯片中的不同,
hh = read_clock(0x85);//刷新程序中的小時數據
}
lcm_w_test(0,0x91);//第一個參數0,表示本行寫入LCM的是指令,指定顯示位置88H(第三行左端)
lcm_w_test(1,(hh/16)+0x30);//顯示十位
lcm_w_test(1,hh%16+0x30);//顯示個位
lcm_w_word("時");
//----------------------------------
if(read_clock(0x83) != mm){//如果1302芯片中的分鐘數據與程序中的分鐘變量不相等
mm = read_clock(0x83);//刷新程序中的分鐘數據
}
lcm_w_test(1,(mm/16)+0x30);//向液晶寫數據,顯示分鐘的十位數
lcm_w_test(1,mm%16+0x30);//向液晶寫數據,顯示分鐘的個位數
lcm_w_word("分");
//----------------------------------
if(read_clock(0x81) != ss){//如果1302芯片中的分鐘數據與程序中的秒鐘變量不相等(0x81為讀秒數據0x80為寫秒數據)
ss = read_clock(0x81);//刷新程序中的秒鐘數據
}
lcm_w_test(1,(ss/16)+0x30);//向液晶寫數據,顯示分鐘的十位數
lcm_w_test(1,ss%16+0x30);//向液晶寫數據,顯示分鐘的個位數
lcm_w_word("秒");
//////////////////////////////////////////////////////////////////////
//=========顯示鬧鐘的設置時間===================
hour=clk_ala[0]; //取出上一次的鬧鐘小時值
minute=clk_ala[1]; //取出上一次的鬧鐘分鐘值
lcm_w_test(0,0x88);
lcm_w_word("鬧鐘---");
//----------------------------
lcm_w_test(1,(hour/10)+0x30);//顯示小時十位
lcm_w_test(1,(hour%10)+0x30);//顯示小時個位
//----------------------------
lcm_w_word(":");
//----------------------------
lcm_w_test(1,(minute/10)+0x30);//顯示分鐘的十位
lcm_w_test(1,(minute%10)+0x30);//顯示分鐘的個位
//----------------------------
lcm_w_word("----");
/////////////////////////////////////////////////////////////////////////
}
/*****************************************************************************/
//被調數據加一或減一,并檢查數據范圍,寫入1302指定地址保存
void ds_w(void)
{
item0=time;
item=((read_clock(address+1))/16)*10 + (read_clock(address+1))%16;//時間的調整
if(K3 == 0||key_add==1){//如果按動上調鍵
item++;//數加 1
}
if(K4 == 0||key_minish==1){//如果按動下調鍵
item--;//數減 1
}
if(item>max) item=mini;//查看數值是否在有效范圍之內
if(item<mini) item=max;//如果數值小于最小值,則自動等于最大值
write_clock(0x8e,0x00);//允許寫1302芯片操作
write_clock(address,(item/10)*16+item%10);//轉換成16進制寫入1302
write_clock(0x8e,0x80);//寫保護,禁止寫操作
}
/********************************************************************/
//===============鬧鐘時間的加減設置======================
void ds_w0(void)
{
item0=time;
if(K3 == 0||key_add==1){//如果按動上調鍵
item0++;//數加 1
}
if(K4 == 0||key_minish==1){//如果按動下調鍵
item0--;//數減 1
}
if(item0>max) item0=mini;//查看數值是否在有效范圍之內
if(item0<mini)item0=max;//如果數值小于最小值,則自動等于最大值
time=item0;//調整后的時間重新賦值給time(time為hour或minute),這步很重要,沒有將無法更新鬧鐘數據
}
/**********************************************************************************************************/
//調整時間子函數,設置鍵、數據范圍、上調加一,下調減一功能。
void Set_time(unsigned char sel){ //根據選擇調整的相應項目加1并寫入DS1302,函數參數是按動設置鍵的次數
write_com(0x30); write_com(0x06);
lcm_w_test(0,0x98);//第一參數0表示本行寫入指令,指定下面行的 調整 顯示起始位置為9AH
lcm_w_word(">>調整>> <<<<");//調用字符顯示函數,顯示 調整字樣
/* if(sel==8) {lcm_w_word("星期");address=0x8a; max=7;mini=1;
tiaozheng();
ds_w();
tiaozheng();
}
*/
//================================================================
lcm_w_test(0,0x9c);
if(sel==7) {lcm_w_word("鬧鐘分"); time=minute;max=59;mini=0;
tiaozheng();//顯示調整前的內容
ds_w0();//設置鬧鐘
clk_ala[1]=time;//把更新后的分鐘數據重新保存
tiaozheng();//顯示調整后的內容
}//按動8次顯示 調整鬧鐘的分鐘部分
if(sel==6) {lcm_w_word("鬧鐘時");time=hour; max=23;mini=0;
tiaozheng();
ds_w0();
clk_ala[0]=time;//把更新后的小時數據重新保存
tiaozheng();
}//按動7次顯示 調整鬧鐘的小時部分
//================================================================
if(sel==5) {lcm_w_word("秒鐘");address=0x80; max=59;mini=0;
tiaozheng(); //調用日期、時間調整函數
ds_w(); //被調數據加一或減一函數
tiaozheng();
} //秒6,按動6次顯示 調整秒鐘
//并指定秒鐘數據寫入1302芯片的寫入地址是0x80,秒鐘數據的最大值是59,最小值是0
if(sel==4) {lcm_w_word("分鐘");address=0x82; max=59;mini=0;
tiaozheng();
ds_w();
tiaozheng();
} //分鐘5,按動5次顯示 調整分鐘
//并指定分鐘數據寫入1302芯片的地址是0x82,分鐘數據的最大值是59,最小值是0
if(sel==3) {lcm_w_word("小時");address=0x84; max=23;mini=0;
tiaozheng();
ds_w();
tiaozheng();
} //小時4,按動4次顯示 調整小時
//規(guī)定小時數據寫入1302芯片的位置是0x84,小時數據最大值23,最小值是0
if(sel==2) {lcm_w_word("日期");address=0x86;
mo = read_clock(0x89);//讀月數據
moontemp1=mo/16;
moontemp2=mo%16;
mo=moontemp1*10+moontemp2;//轉換成10進制月份數據
yy = read_clock(0x8d);//讀年數據
moontemp1=yy/16;
moontemp2=yy%16;
yy=moontemp1*10+moontemp2;//轉換成10進制年份數據
if(mo==2&&yy%4!=0){max=28;mini=1;}//平年2月28天
if(mo==2&&yy%4==0){max=29;mini=1;}//閏年2月29天
if(mo==1||mo==3||mo==5||mo==7||mo==8||mo==10||mo==12){max=31;mini=1;}//31天的月份
if(mo==4||mo==6||mo==9||mo==11){max=30;mini=1;}//30天的月份
tiaozheng();
ds_w();
tiaozheng(); //調用日期、時間調整函數
} //日3,按動3次顯示 調整日期
//規(guī)定日期數據寫入1302的位置地址是0x86,日期最大值31,最小值是1
if(sel==1) {lcm_w_word("月份");address=0x88; max=12;mini=1;
tiaozheng();
ds_w();
tiaozheng();
} //月2,按動2次顯示 調整月份
//規(guī)定月份寫入1302的位置地址是0x88,月份最大值12,最小值1
if(sel==0) {lcm_w_word("年份");address=0x8c; max=99; mini=0;
tiaozheng();
ds_w(); //被調數據加一或減一函數
tiaozheng(); //調用日期、時間調整函數
} //年1,按動1次顯示 調整年份,
//規(guī)定年份寫入1302的地址是0x8c,年份的最大值99,最小值0
}
/*********************************************************************
**********************************************************************
************** 主函數 ****************
**********************************************************************
/********************************************************************/
void main()
{
unsigned char e=0,f=0,tmp,i;
IE = 0x81; //允許總中斷中斷,使能 INT0 外部中斷
TCON = 0x01; //觸發(fā)方式為脈沖負邊沿觸發(fā)
IRIN=1; //IO口初始化
BEEP=1;
K1=1;K2=1;K3=1;K4=1;
Init_1302(); //時鐘芯片初始化
lcm_init(); //液晶初始化
welcome0(); //調用歡迎信息1
DelayM(2000);//延時
//welcome();DelayM(1000); //調用歡迎信息2
lcm_clr(); //清屏
Clean_12864_GDRAM(); //清屏
while(1)
{
if (w == 0) //正常走時
{
displaydate(); //顯示日期
displaynl(); //顯示農歷
displaytime(); //顯示時間
read_temp(); //讀取溫度
ds1820disp(); //顯示溫度
displayxq(); //顯示星期
//=================以下是鬧鐘的相關處理===================
if(ala_flag==1){//鬧鐘標志位
set1616pic(6,1,0,2);} //顯示"鬧鐘圖標"
else{
set1616pic(6,1,0,3);}//關閉"鬧鐘圖標"顯示
//----------------------------------------
tmp=read_clock(0x85);//取出1302小時
i = tmp/16;
tmp = tmp&0x0f;
tmp = tmp + i*10;
if(clk_ala[0]==tmp)//與鬧鐘設定的小時值相同
{
tmp=read_clock(0x83);//取出1302分鐘
i = tmp/16;
tmp = tmp&0x0f;
tmp = tmp + i*10;
if(clk_ala[1]==tmp)//與鬧鐘設定的分鐘值相同
{
if(ala_flag==1)//鬧鐘打開
{
alarmbeep();//鬧鈴聲響1分鐘后自動關閉,
DelayM(200);//控制鬧鐘響的間隔即頻率
}
else BEEP=1;//關閉蜂鳴器
}
else BEEP=1;//關閉蜂鳴器
}
//==============鬧鐘處理結束=======================
}
else {} //========否則啟動調時=========================
/*---------------按鍵及紅外遙控設置時間------------------------------*/
if (K1 == 0||key_manue==1)
{
DelayM(8); //按鍵消抖
/*當是調時狀態(tài) 本鍵用于調整下一項---------------------------------------------------*/
if((K1 == 0 && w == 1)||(key_manue==1&&w==1)) //
{
e++;
if (e >= 8 ) {e = 0;}
while(! K1 ); //等待鍵松開
key_manue=0;
Set_time(e); beep(); //調整
}
/*當是正常狀態(tài)時就進入調時狀態(tài)---------------------------------------------------*/
if((K1 == 0 && w == 0)||(key_manue==1&&w==0)) //
{
key_manue=0;
lcm_clr();
Clean_12864_GDRAM(); //清屏
w=1; //進入調時
Set_time(e);beep();
}
while(K1 == 0); //等待鍵松開
}
/*當在調時狀態(tài)時就退出調時---------------------------------------------------*/
if (K2 == 0||key_ok==1) //
{ beep();
DelayM(8);
if((K2 == 0 && w == 1)||(key_ok==1&&w==1))
{
w = 0; //退出調時
e = 0; //"下一項"計數器清0
}
if((K2 == 0 && w == 0)||(key_ok==1&&w==0))
{
lcm_clr(); Clean_12864_GDRAM();
write_com(0x30); write_com(0x06);
welcome();
while(K2 == 0); //按下K2是顯示歡迎信息
DelayM(500);key_ok=0;//紅外"OK"按鍵按下時顯示0.5秒鐘的歡迎界面2
}
lcm_clr(); Clean_12864_GDRAM();
// ds_write(0x0a,0x20); //調時完畢,開啟時鐘振蕩器
displaydate();
displayxq();
displaynl();
displaytime();
read_temp();
ds1820disp();
while(K2 == 0);
}
/*加調整--------------------------------------------------------------------*/
if ((K3 == 0 && w == 1)||(key_add==1&&w==1))
{
DelayM(8);
if((K3 == 0 && w == 1)||(key_add==1&&w==1))
{
Set_time(e);
beep();
while(!K3);
key_add=0;
}
key_add=0;
while(! K3 );
}
/*減調整--------------------------------------------------------------------*/
if ((K4 == 0 && w == 1)||(key_minish==1&&w==1))
{
DelayM(10);
if((K4 == 0 && w == 1)||(key_minish==1&&w==1))
{
Set_time(e);
beep();
while(! K4 );
key_minish=0;
}
key_minish=0;
while(! K4 );
}
/*----------------------------------------------------------------*/
if(K5==0||key_alarm==1)//鬧鐘的開與關的設置標志位
{
DelayM(20);
if(K5==0||key_alarm==1)
{ beep();
while(!K5);//松手檢測
key_alarm=0;
ala_flag=~ala_flag;
}
while(!K5);//松手檢測
key_alarm=0;
}
EX0 = 1; //開中斷
}
}
|