|
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uchar unsigned char
#define uint unsigned int
sbit DS1302_CLK=P3^2;
sbit DS1302_IO=P3^3;
sbit DS1302_RST=P3^4;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit Tiaoshi=P3^7; //調試按鍵
sbit Inck=P3^6; //升序按鍵
uchar count=0; //記錄按鍵次數
uchar temp;
sfr Wei=0xa0;
sfr Duan=0x90;
bit Inck_flag=0x20; //升序調試標志
bit flag=0x21;
char hide_sec;
char hide_min;
char hide_hour;
char hide_day;
char hide_month;
char hide_year;
typedef struct _SYSTEMTIME_
{
uchar Second;
uchar Minute;
uchar Hour;
uchar Day;
uchar Month;
uchar Year;
uchar TimeStr[12];
}SYSTEMTIME; //定義的時間類型
SYSTEMTIME CurrentTime; //結構體名稱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_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8c
void mdelay(unsigned int count) //延時函數
{
uchar i,j;
for(i=0;i<count;i++)
{
for(j=0;j<120;j++)
;
}
}
void DS1302InputByte(uchar d) //向1302中通過ACC輸入數值d
{
uchar i;
ACC=d;
for(i=8;i>0;i--)
{
DS1302_IO=ACC0;
DS1302_CLK=1; //一個時鐘的上升沿輸出
DS1302_CLK=0;
ACC=ACC>>1;
}
}
uchar DS1302OutputByte(void) //ds1302向單片機發送數據返回值為ACC
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=DS1302_IO;
DS1302_CLK=1;
DS1302_CLK=0;
}
return(ACC);
}
void Write1302(uchar ucAddr,uchar ucDa) //向ds1302中寫入數據地址為Addar,數據為ucDa
{
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr); //先發送地址,命令
DS1302InputByte(ucDa); //然后寫1Byte數據
DS1302_CLK=1;
DS1302_RST=0;
}
uchar Read1302(uchar ucAddr) //讀取DS1302某地址的數據
{
uchar 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_SetProtect(bit flag1) // 是否寫保護
{
if(flag1)
Write1302(0x8E,0x10);
else
Write1302(0x8E,0x00);
}
void DS1302_SetTime(uchar Address,uchar Value) //設置時間函數
{
DS1302_SetProtect(0);
Write1302(Address,((Value/10)<<4|(Value%10)));
}
void DS1302_GetTime(SYSTEMTIME *Time) //將ds1302中讀取的數據存入結構體
{
uchar ReadValue;
ReadValue=Read1302(DS1302_SECOND); //將秒位的數據賦值給ReadValue變量
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); //將的數據賦值給ReadValue變量
Time->Day=((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 TimeToStr(SYSTEMTIME *Time) //數據緩存區
{
Time->TimeStr[0]=Time->Hour/10; //將小時的十位存入TimeStr[0]
Time->TimeStr[1]=Time->Hour%10;
Time->TimeStr[2]=Time->Minute/10;
Time->TimeStr[3]=Time->Minute%10;
Time->TimeStr[4]=Time->Second/10;
Time->TimeStr[5]=Time->Second%10;
Time->TimeStr[6]=Time->Year/10; //將小時的十位存入TimeStr[0]
Time->TimeStr[7]=Time->Year%10;
Time->TimeStr[8]=Time->Month/10;
Time->TimeStr[9]=Time->Month%10;
Time->TimeStr[10]=Time->Day/10;
Time->TimeStr[11]=Time->Day%10;
}
void Delay1ms(uint count1) //延時函數
{
uint i,j;
for(i=0;i<count1;i++)
for(j=0;j<120;j++);
}
void Dis(SYSTEMTIME *Time) //顯示函數
{
uchar disbit,shitfb;
DS1302_GetTime(Time); //從1302中獲取時間并存入結構體Time中
TimeToStr(Time); //將結構體中數據緩存至TimeStr[0]
disbit=1; //0xfe; 最后一位打開
for(shitfb=0;shitfb<6;shitfb++)
{_nop_(); _nop_(); //延時
Duan=Time->TimeStr[shitfb]; //段選依次輸入 TimeStr[0]到TimeStr[5];
Wei=_crol_(disbit,shitfb); //位選依次亮起
Delay1ms(2);
Wei=0;
}
}
void Dis2(SYSTEMTIME *Time) //顯示函數
{
uchar disbit,shitfb;
DS1302_GetTime(Time); //從1302中獲取時間并存入結構體Time中
TimeToStr(Time); //將結構體中數據緩存至TimeStr[0]
disbit=1; //0xfe; 最后一位打開
for(shitfb=6;shitfb<12;shitfb++)
{_nop_(); _nop_(); //延時
Duan=Time->TimeStr[shitfb]; //段選依次輸入 TimeStr[6]到TimeStr[11];
Wei=_crol_(disbit,shitfb-6); //位選依次亮起
Delay1ms(2);
Wei=0;
}
}
void Setkey() //模式選擇按鍵
{
Tiaoshi=1;
if(Tiaoshi==0) //調試按鍵按下
{
mdelay(8);
count=count+1; //count從0開始計數
if(count==7)count=0;
while(Tiaoshi==0); //按鍵松開跳出循環
}
}
void Inckey() //升序按鍵
{
Inck=1;
if(Inck==0) //升序按鍵按下
{ mdelay(8);
switch(count) //選擇調時模式
{case 1: //調整小時
temp=Read1302(DS1302_HOUR); //讀取小時數 將返回的ACC存入temp
temp=((temp&0x70)>>4)*10+(temp&0x0f); //將ACC化為十進制數
temp=temp+1; //小時數加1
if(temp>=24)temp=0;
Inck_flag=1;
break;
case 2:
temp=Read1302(DS1302_MINUTE); //讀取分數
temp=((temp&0x70)>>4)*10+(temp&0x0f);
temp=temp+1; //分數加1
Inck_flag=1;
if(temp>=60)temp=0;
break;
case 3:
temp=Read1302(DS1302_SECOND); //讀取秒數
temp=((temp&0x70)>>4)*10+(temp&0x0f);
temp=temp+1; //秒數加1
Inck_flag=1; //數據調整后更新標志
if(temp>=60)temp=0;
break;
case 4: //調整年
temp=Read1302(DS1302_YEAR); //讀取年 將返回的ACC存入temp
temp=((temp&0x70)>>4)*10+(temp&0x0f); //將ACC化為十進制數
temp=temp+1; //小時數加1
if(temp>=99)temp=0;
Inck_flag=1;
break;
case 5:
temp=Read1302(DS1302_MONTH); //讀取
temp=((temp&0x70)>>4)*10+(temp&0x0f);
temp=temp+1; //
Inck_flag=1;
if(temp>=12)temp=0;
break;
case 6:
temp=Read1302(DS1302_DAY); //讀取秒數
temp=((temp&0x70)>>4)*10+(temp&0x0f);
temp=temp+1; //秒數加1
Inck_flag=1; //數據調整后更新標志
if(temp>=32)temp=0;
break;
default: Inck_flag=0;
break;
}
while(Inck==0); //檢測松開按鍵
}
}
void Keydone() //按鍵功能執行
{
Setkey(); //掃描模式切換按鍵
switch(count)
{case 1:do //count=1,調整時
{ Inckey();
if(Inck_flag==1)
{ temp=(temp/10)<<4|temp%10;
Write1302(0x8e,0x00); //寫入允許
Write1302(0x84,temp); //寫入新的小時數temp
Write1302(0x8e,0x80); //禁止寫入
Inck_flag=0;
}
hide_hour++;
if(hide_hour>3)
hide_hour=0;
Dis(&CurrentTime) ;
}while(count==2);
break;
case 2:do //count=2,調整分
{ hide_hour=0;
Inckey();
if(Inck_flag==1)
{ temp=(temp/10)<<4|temp%10;
Write1302(0x8e,0x00); //寫入允許
Write1302(0x82,temp); //寫入新的分數
Write1302(0x8e,0x80); //禁止寫入
Inck_flag=0;
}
hide_min++;
if(hide_min>3)
hide_min=0;
Dis(&CurrentTime); //程序每循環三次顯示一下
}while(count==3);
break;
case 3:do //調整秒
{ hide_min=0;
Inckey(); //掃描加按鈕
if(Inck_flag==1) //數據更新,重新寫入新的數據
{ temp=(temp/10)<<4|temp%10;
Write1302(0x8e,0x00); //寫入允許
Write1302(0x80,temp&0x7f); //寫入新的秒數
Write1302(0x8e,0x80); //禁止寫入
Inck_flag=0;
}
hide_sec++; //位閃計時
if(hide_sec>3)
hide_sec=0;
Dis(&CurrentTime);
}while(count==4);
break;
case 4:do //count=1,調整
{ Inckey();
if(Inck_flag==1)
{ temp=(temp/10)<<4|temp%10;
Write1302(0x8e,0x00); //寫入允許
Write1302(0x8c,temp); //寫入新的
Write1302(0x8e,0x80); //禁止寫入
Inck_flag=0;
}
hide_year++;
if(hide_year>3)
hide_year=0;
Dis2(&CurrentTime) ;
}while(count==5);
break;
case 5:do //count=5
{ hide_year=0;
Inckey();
if(Inck_flag==1)
{ temp=(temp/10)<<4|temp%10;
Write1302(0x8e,0x00); //寫入允許
Write1302(0x88,temp); //寫入新的
Write1302(0x8e,0x80); //禁止寫入
Inck_flag=0;
}
hide_month++;
if(hide_month>3)
hide_month=0;
Dis2(&CurrentTime); //程序每循環三次顯示一下
}while(count==6);
break;
case 6:do //調整
{ hide_month=0;
Inckey(); //掃描加按鈕
if(Inck_flag==1) //數據更新,重新寫入新的數據
{ temp=(temp/10)<<4|temp%10;
Write1302(0x8e,0x00); //寫入允許
Write1302(0x86,temp); //寫入新的
Write1302(0x8e,0x80); //禁止寫入
Inck_flag=0;
}
hide_day++; //位閃計時
if(hide_day>3)
hide_day=0;
Dis2(&CurrentTime);
}while(count==7);
break;
case 7:
count=0;hide_sec=0;hide_day=0;
break;
default:
break;
}
}
main()
{ Inck_flag=0;
while(1)
{
if(count<4)
{
Dis(&CurrentTime);
Setkey();
if(count!=0)//(F0==1)
Keydone();
} //進入調整模式
if(count>=4)
{
Dis2(&CurrentTime);
Setkey();
if(count!=0)//(F0==1)
Keydone();
} //進入調整模式
}
}
|
|