#include <intrins.h>
//#include "LCD1602.h"
//#include "DS1302.h"
#define uint unsigned int
#define uchar unsigned char
sbit DS1302_CLK = P1^7; //實時時鐘時鐘線引腳
sbit DS1302_IO = P1^6; //實時時鐘數據線引腳
sbit DS1302_RST = P1^5; //實時時鐘復位線引腳
sbit wireless_1 = P3^0;
sbit wireless_2 = P3^1;
sbit wireless_3 = P3^2;
sbit wireless_4 = P3^3;
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,時到日,月,年位閃的計數
sbit Set = P2^0; //模式切換鍵
sbit Up = P2^1; //加法按鈕
sbit Down = P2^2; //減法按鈕
sbit out = P2^3; //立刻跳出調整模式按鈕
char done,count,temp,flag,up_flag,down_flag;
uchar TempBuffer[5],week_value[2];
/***********DS1302時鐘部分子程序******************/
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTEMTIME; //定義的時間類型
SYSTEMTIME CurrentTime;
#define AM(X) X
#define PM(X) (X+12) // 轉成24小時制
#define DS1302_SECOND 0x80 //時鐘芯片的寄存器位置,存放時間
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C
void DS1302InputByte(unsigned char d) //實時時鐘寫入壹字節(內部函數)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相當於匯編中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}
unsigned char DS1302OutputByte(void) //實時時鐘讀取壹字節(內部函數)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相當於匯編中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}
void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要寫的數據
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 寫1Byte數據
DS1302_CLK = 1;
DS1302_RST = 0;
}
unsigned char Read1302(unsigned char ucAddr) //讀取DS1302某地址的數據
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 讀1Byte數據
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}
void DS1302_GetTime(SYSTEMTIME *Time) //獲取時鐘芯片的時鐘數據到自定義的結構型數組
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}
void DateToStr(SYSTEMTIME *Time) //將時間年,月,日,星期數據轉換成液晶顯示字符串,放到數組裏DateString[]
{ if(hide_year<2) //這裏的if,else語句都是判斷位閃爍,<2顯示數據,>2就不顯示,輸出字符串為 2007/07/22
{
Time->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + '0';
Time->DateString[3] = Time->Year%10 + '0';
}
else
{
Time->DateString[0] = ' ';
Time->DateString[1] = ' ';
Time->DateString[2] = ' ';
Time->DateString[3] = ' ';
}
Time->DateString[4] = '/';
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + '0';
Time->DateString[6] = Time->Month%10 + '0';
}
else
{
Time->DateString[5] = ' ';
Time->DateString[6] = ' ';
}
Time->DateString[7] = '/';
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + '0';
Time->DateString[9] = Time->Day%10 + '0';
}
else
{
Time->DateString[8] = ' ';
Time->DateString[9] = ' ';
}
if(hide_week<2)
{
week_value[0] = Time->Week%10 + '0'; //星期的數據另外放到 week_value[]數組裏,跟年,月,日的分開存放,因為等壹下要在最後顯示
}
else
{
week_value[0] = ' ';
}
week_value[1] = '\0';
Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判斷結束字符
}
void TimeToStr(SYSTEMTIME *Time) //將時,分,秒數據轉換成液晶顯示字符放到數組 TimeString[];
{ if(hide_hour<2)
{
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
}
else
{
Time->TimeString[0] = ' ';
Time->TimeString[1] = ' ';
}
Time->TimeString[2] = ':';
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
}
else
{
Time->TimeString[3] = ' ';
Time->TimeString[4] = ' ';
}
Time->TimeString[5] = ':';
if(hide_sec<2)
{
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
}
else
{
Time->TimeString[6] = ' ';
Time->TimeString[7] = ' ';
}
Time->DateString[8] = '\0';
}
void Initial_DS1302(void) //時鐘芯片初始化
{
unsigned char Second="Read1302"(DS1302_SECOND);
if(Second&0x80) //判斷時鐘芯片是否關閉
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x8c,0x07); //以下寫入初始化時間 日期:07/07/25.星期: 3. 時間: 23:59:55
Write1302(0x88,0x07);
Write1302(0x86,0x25);
Write1302(0x8a,0x07);
Write1302(0x84,0x23);
Write1302(0x82,0x59);
Write1302(0x80,0x55);
Write1302(0x8e,0x80); //禁止寫入
}
}
void Upkey()//升序按鍵
{
Up=1;
if(Up==0||wireless_2==1)
{
mdelay(8);
switch(count)
{case 1:
temp="Read1302"(DS1302_SECOND); //讀取秒數
temp="temp"+1; //秒數加1
up_flag=1; //數據調整後更新標誌
if((temp&0x7f)>0x59) //超過59秒,清零
temp="0";
break;
case 2:
temp="Read1302"(DS1302_MINUTE); //讀取分數
temp="temp"+1; //分數加1
up_flag=1;
if(temp>0x59) //超過59分,清零
temp="0";
break;
case 3:
temp="Read1302"(DS1302_HOUR); //讀取小時數
temp="temp"+1; //小時數加1
up_flag=1;
if(temp>0x23) //超過23小時,清零
temp="0";
break;
case 4:
temp="Read1302"(DS1302_WEEK); //讀取星期數
temp="temp"+1; //星期數加1
up_flag=1;
if(temp>0x7)
temp="1";
break;
case 5:
temp="Read1302"(DS1302_DAY); //讀取日數
temp="temp"+1; //日數加1
up_flag=1;
if(temp>0x31)
temp="1";
break;
case 6:
temp="Read1302"(DS1302_MONTH); //讀取月數
temp="temp"+1; //月數加1
up_flag=1;
if(temp>0x12)
temp="1";
break;
case 7:
temp="Read1302"(DS1302_YEAR); //讀取年數
temp="temp"+1; //年數加1
up_flag=1;
if(temp>0x85)
temp="0";
break;
default:break;
}
while(Up==0);
while(wireless_2==1);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Downkey()//降序按鍵
{
Down=1;
if(Down==0||wireless_3==1)
{
mdelay(8);
switch(count)
{case 1:
temp="Read1302"(DS1302_SECOND); //讀取秒數
temp="temp-1"; //秒數減1
down_flag=1; //數據調整後更新標誌
if(temp==0x7f) //小於0秒,返回59秒
temp="0x59";
break;
case 2:
temp="Read1302"(DS1302_MINUTE); //讀取分數
temp="temp-1"; //分數減1
down_flag=1;
if(temp==-1)
temp="0x59"; //小於0秒,返回59秒
break;
case 3:
temp="Read1302"(DS1302_HOUR); //讀取小時數
temp="temp-1"; //小時數減1
down_flag=1;
if(temp==-1)
temp="0x23";
break;
case 4:
temp="Read1302"(DS1302_WEEK); //讀取星期數
temp="temp-1"; //星期數減1
down_flag=1;
if(temp==0)
temp="0x7";;
break;
case 5:
temp="Read1302"(DS1302_DAY); //讀取日數
temp="temp-1"; //日數減1
down_flag=1;
if(temp==0)
temp="31";
break;
case 6:
temp="Read1302"(DS1302_MONTH); //讀取月數
temp="temp-1"; //月數減1
down_flag=1;
if(temp==0)
temp="12";
break;
case 7:
temp="Read1302"(DS1302_YEAR); //讀取年數
temp="temp-1"; //年數減1
down_flag=1;
if(temp==-1)
temp="0x85";
break;
default:break;
}
while(Down==0);
while(wireless_3==1);
}
}
void Setkey()//模式選擇按鍵
{
Set=1;
if(Set==0||wireless_4==1)
{
mdelay(8);
count="count"+1; //Setkey按壹次,count就加1
done="1"; //進入調整模式
while(Set==0);
while(wireless_4==1);
}
}
void keydone()//按鍵功能執行
{ uchar Second;
if(flag==0) //關閉時鐘,停止計時
{ Write1302(0x8e,0x00); //寫入允許
temp="Read1302"(0x80);
Write1302(0x80,temp|0x80);
Write1302(0x8e,0x80); //禁止寫入
flag="1";
}
Setkey(); //掃描模式切換按鍵
switch(count)
{case 1:do //count=1,調整秒
{
outkey(); //掃描跳出按鈕
Upkey(); //掃描加按鈕
Downkey(); //掃描減按鈕
if(up_flag==1||down_flag==1) //數據更新,重新寫入新的數據
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x80,temp|0x80); //寫入新的秒數
Write1302(0x8e,0x80); //禁止寫入
up_flag=0;
down_flag=0;
}
hide_sec++; //位閃計數
if(hide_sec>3)
hide_sec=0;
show_time(); //液晶顯示數據
}while(count==2);break;
case 2:do //count=2,調整分
{
hide_sec=0;
outkey();
Upkey();
Downkey();
if(temp>0x60)
temp="0";
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x82,temp); //寫入新的分數
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,調整小時
{
hide_min=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x84,temp); //寫入新的小時數
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,調整星期
{
hide_hour=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x8a,temp); //寫入新的星期數
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,調整日
{
hide_week=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x86,temp); //寫入新的日數
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,調整月
{
hide_day=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x88,temp); //寫入新的月數
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,調整年
{
hide_month=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //寫入允許
Write1302(0x8c,temp); //寫入新的年數
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, 跳出調整模式,返回默認顯示狀態
Second="Read1302"(DS1302_SECOND);
Write1302(0x8e,0x00); //寫入允許
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止寫入
done="0";
break; //count=7,開啟中斷,標誌位置0並退出
default:break;
}
}