/****************************************************************
作用:基于时钟芯片DS1302的定时闹钟并利用74HC595芯片驱动数码管显示。
日期:2019年11月20日
作者:周桦
****************************************************************/
#include "main.h"
unsigned int m,s,f;
unsigned int N_f,N_s; //闹钟设置函数
unsigned int sum=1;
code char Ztun[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
code char Wei[8]={0x08,0x04,0x02,0x01,0x80,0x40,0x20,0x10};
code char Ztun1[25]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x18,};//带点显示
bit biao=0; //闹钟设置标志
void yanshi(void)
{
int i,j;
for(i=0;i<1;i++)
for(j=0;j<125;j++);
}
void T_yanshi(unsigned int j)
{
while(j--)
{
_nop_();
}
}
unsigned char Z10BCD( uchar date) //十进制转BCD码
{
uchar i,j;
i=date/10;
j=date-(i*10);
i=(i<<4)|j;
return (i);
}
unsigned char BCDTO10( uchar date ) //BCD码转10进制
{
uchar i,j;
i=(date & 0xf0)>>4 ;
j=date & 0x0f ;
i=i*10+j;
return i;
}
unsigned char Tiao()//调时间
{
unsigned int S_min,G_min,S_hor,G_hor,week;
bit k=0;
S_min=BCDTO10( RE1302(0x83) )/10; //分十位
G_min=BCDTO10( RE1302(0x83) )%10; //分个位
S_hor= BCDTO10( RE1302(0x85) )/10; //时十位
G_hor= BCDTO10( RE1302(0x85) )%10; //时个位
week= BCDTO10( RE1302(0x8B) ); // 星期
P2=0xfd;
while(sum==2)
{
OUT_output(~Ztun[BCDTO10( RE1302(0x81) )%10], ~Wei[7]);
OUT_output(~Ztun[BCDTO10( RE1302(0x81) )/10], ~Wei[6]);
OUT_output(~Ztun1[G_min], ~Wei[5]);
OUT_output(~Ztun[S_min], ~Wei[4]);
OUT_output(~Ztun1[G_hor], ~Wei[3]);
OUT_output(~Ztun[S_hor], ~Wei[2]);
OUT_output(0x09, ~Wei[1]);
OUT_output(~Ztun[week], ~Wei[0]);
switch(P3)
{
case 0xFE:
week++;if(week==8)week=0;
while(!S0); k=1;
break;
case 0xFD:
S_hor++;if(S_hor==3)S_hor=0;
while(!S1); k=1;
break;
case 0xFB:
G_hor++;if(G_hor==10)G_hor=0;
while(!S2); k=1;
break;
case 0xF7:
S_min++; if(S_min==6)S_min=0;
while(!S3); k=1;
break;
case 0xEF:
G_min++;if(G_min==10)G_min=0;
while(!S4); k=1;
break;
}
}
if(k)
{
f=(S_min*10)+G_min;
s=(S_hor*10)+G_hor;
WR1302(0x8E,0X00);
Initime(0,f,s,18,6,week,10);
}
if(sum==3) Nao(&N_f,&N_s); //进入调闹钟
P2=0xff;
}
unsigned int Nao( unsigned int *o,unsigned int *p)
{
unsigned int q,w,e,r,x;
unsigned int l,k;
l=*o; k=*p;
r=l%10; e=l/10;
w=k%10; q=k/10;
P2=0xfb;
while(sum==3)
{
OUT_output(~Ztun[0], ~Wei[7]);
OUT_output(~Ztun[0], ~Wei[6]);
OUT_output(~Ztun1[r], ~Wei[5]);
OUT_output(~Ztun[e], ~Wei[4]);
OUT_output(~Ztun1[w], ~Wei[3]);
OUT_output(~Ztun[q], ~Wei[2]);
OUT_output(0x40, ~Wei[1]);
OUT_output(~Ztun[x], ~Wei[0]); //显示
switch(P3)
{
case 0xFD:
q=q+1;if(q==3)q=0;
while(!S1); biao=1;
break;
case 0xFB:
w=w+1;if(w==10)w=0;
while(!S2); biao=1;
break;
case 0xF7:
e=e+1; if(e==6)e=0;
while(!S3); biao=1;
break;
case 0xEF:
r=r+1;if(r==10)r=0;
while(!S4); biao=1;
break;
}
}
l=(e*10)+r;
k=(q*10)+w;
*o=l;
*p=k;
P2=0xff;
}
void Nnao()
{
unsigned int i;
i=100;
while(i--)
{
D1=0;
T_yanshi(2);
D1=1;
T_yanshi(8);
}
i=50;
while(i--)
{
D1=0;
T_yanshi(2);
D1=1;
T_yanshi(1);
}
}
void main()
{
unsigned int Min,Hor;
AUXR = 0x40; //工作在1T模式
TMOD = 0x60; //T1为计数器模式2(8位自动重装)
TL1 = TH1 = 0xff; //填充0xff 计数一次
TR1 = 1; //定时器一开关
ET1 = 1; //T1开关
EA = 1;
if(pan()) //因为DS1302掉电过后时间会变成0不会走这里判断它如果是0时0分星期一就给它赋初值
{
WR1302(0x8E,0X00);
Initime(56,34,12,20,11,3,19); //给时钟芯片赋初值
}
WR1302(0x8E,0Xf0); // 0X8E是WP写保护地址,最高位赋0表示可以写操作
while(1)
{
/*
Sec = BCDTO10( RE1302(0x81) ); //0x81读秒数据,读出来的是BCD码,还要转换成十进制数
Min = BCDTO10( RE1302(0x83) ); //0x83读分数据
Hor = BCDTO10( RE1302(0x85) ); //0x85读时数据
Day = BCDTO10( RE1302(0x87) ); //0x87读日数据
Yue = BCDTO10( RE1302(0x89) ); //0x89读月数据
Week = BCDTO10( RE1302(0x8B) ); //0x8b读星期数据
Year = BCDTO10( RE1302(0x8D) ); //0x8d读年数据
*/
if(sum==2) Tiao(); //进入调时间函数
if(sum==3) Nao(&N_f,&N_s); //进入调闹钟
if(biao) //设置过闹钟才会响
if(BCDTO10( RE1302(0x83) )==N_f && BCDTO10( RE1302(0x85) )==N_s) {Nnao();} //判断是否到设定的闹钟值
if(BCDTO10( RE1302(0x81) )>60) //如果秒超60(DS1302出错)则时间归零
{
WR1302(0x8E,0X00);
Initime(00,00,00,20,11,7,19);
}
OUT_output(~Ztun[BCDTO10( RE1302(0x81) )%10], ~Wei[7]);
OUT_output(~Ztun[BCDTO10( RE1302(0x81) )/10], ~Wei[6]);
OUT_output(~Ztun1[BCDTO10( RE1302(0x83) )%10], ~Wei[5]);
OUT_output(~Ztun[BCDTO10( RE1302(0x83) )/10], ~Wei[4]);
OUT_output(~Ztun1[BCDTO10( RE1302(0x85) )%10], ~Wei[3]);
OUT_output(~Ztun[BCDTO10( RE1302(0x85) )/10], ~Wei[2]);
OUT_output(~Ztun[BCDTO10( RE1302(0x8B) )], ~Wei[0]);
if (BCDTO10( RE1302(0x81) )%2==0)
{
OUT_output(0x09,~Wei[1]);
}
}
}
void t1int() interrupt 3 //T1中断程序
{
T_yanshi(20);
sum++;
while(!S5);
if(sum==4) {sum=1;}
}