/************************************************/
/******************* 数字时钟 *******************/
/************************************************/
#include <AT89X51.H>
#define MAIN_Fosc 11059200UL //定义主时钟
#define Timer0_Reload (MAIN_Fosc / 12000)
#define uchar unsigned char
#define uint unsigned int
sbit tiaomiao=P2^0; //调秒
sbit tiaofen=P2^1; //调分
sbit tiaoshi=P2^2; //调时
sbit date=P2^3; //日期
sbit qingling=P2^4; //清零
sbit buzzer=P2^5; //闹钟蜂鸣器
sbit dengguan=P2^6; //灯光
sbit DIO = P1^0; // 串行数据输入 595的14脚
sbit RCLK = P1^1; // 时钟脉冲信号——上升沿有效 即锁存 595的12脚
sbit SCLK = P1^2; // 打入信号————上升沿有效 即移位 595的11脚
uint a,b;
uchar hour,minu,sec, //时钟
hour0,minu0,sec0, //秒钟
hour1,minu1,sec1;
h1,h2,m1,m2,s1,s2,//显示位
k,s; //状态转换标志
uchar j,datah,datal;
uchar code segment[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//段码
uchar code segbit[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; //位码
/*****************函数声明***********************/
void key_pro(); //键盘扫描子程式
void init();
void delay(uchar z); //延时子程式
void LED_Display(uchar,uchar,uchar); // LED显示
void sounde(); //闹钟程式
void LED_OUT(); //LED单字节串行移位函数
/*****************主函数*************************/
void main()
{
init();
while(1)
{
while(TR1)
{
key_pro(); //扫描函数
while(s==1) //s是状态标志,当s=0时,闹钟取消。s=1时,设定闹钟时间
{ //s=2时,闹钟工作,时间与设定时刻一致时,闹钟响
key_pro(); //s状态切换(0-》1-》2-》0)通过外部中断1实现
LED_Display(hour1,minu1,sec1); //闹钟时刻显示
}
LED_Display(hour0,minu0,sec0);//时钟显示
while(k) /*k是秒表状态(0-》1-》2-》0)通过外部中断0实现 */
{
LED_Display(hour,minu,sec); //秒表显示
}
}
}
}
/*****************初始化函数***********************/
void init()
{
a=0;
b=0;
k=0;
s=0;
hour0=12; //预设定时间小时
minu0=00; //预设定时间分钟
sec0=00; //预设定时间秒
hour=0;
minu=0;
sec=0;
hour1=0; // 预设 闹钟时刻显示
minu1=0; // 预设 闹钟时刻显示
sec1=0; // 预设 闹钟时刻显示
TMOD=0x11; //定时器0,1工作于方式1;赋初值
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
EA=1;
EX0=1; //秒表中断
EX1=1; //闹钟设定中断
ET0=1;
ET1=1;
IT0=1; //边沿触发方式
IT1=1;
PX0=1;
PX1=1;
TR0=0; //初值,秒表不工作
TR1=1; //时钟一开始工作
buzzer=1;
}
/*****************定时器0中断*************/
void timer0_int() interrupt 1 //秒表
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
a++;
if(a==2)
{
a=0;
sec++;
if(sec==100)
{
sec=0; //毫秒级
minu++;
if(minu==60)
{
minu=0; //秒
hour++;
if(hour==60) //分
{
hour=0;
}
}
}
}
}
/*************外部中断0中断函数************/
void ex0_int() interrupt 0
{
k++;
if(k==4)
k=0;
if(k==2)
{
TR0=~TR0;
if(TR0==1)
{
hour=0;
minu=0;
sec=0;
}
}
if(k==3)
{
TR0=~TR0;
}
}
/*************外部中断1中断函数************/
void ex1_int() interrupt 2
{
s++;
if(s==3)
s=0;
}
/*************定时器1中断****************/
void timer1_int() interrupt 3 //控制时钟工作
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
if(s==2)
{
if(hour1==hour0 && minu1==minu0 &&sec1==sec0)
sounde();
}
b++;
if(b==20)
{
b=0;
sec0++;
if(sec0==60)
{
sec0=0;
minu0++;
if(minu0==60)
{
minu0=0;
hour0++;
if(hour0==24)
hour0=0;
}
}
}
}
/*************键盘扫描****************/
void key_pro()
{
if(s==1)
{
if(qingling==0)
{
delay(30);
if(qingling==0)
{
sec1=0;
minu1=0;
hour1=0;
}
}
if(tiaomiao==0)
{
delay(30);
if(tiaomiao==0)
{
sec1++;
if(sec1==60)
{
sec1=0;
}
while(!tiaomiao);
}
}
if(tiaofen==0)
{
delay(30);
if(tiaofen==0)
{
minu1++;
if(minu1==60)
{
minu1=0;
}
while(!tiaofen);
}
}
if(tiaoshi==0)
{
hour1++;
delay(30);
if(hour1==24)
{
hour1=0;
}
while(!tiaoshi);
}
}
else //调整时钟时间
{
if(qingling==0)
{
delay(30);
if(qingling==0)
{
sec0=0;
minu0=0;
hour0=0;
}
}
if(tiaomiao==0)
{
delay(30);
if(tiaomiao==0)
{
sec0++;
if(sec0==60)
{
sec0=0;
}
while(!tiaomiao);
}
}
if(tiaofen==0)
{
delay(30);
if(tiaofen==0)
{
minu0++;
if(minu0==60)
{
minu0=0;
}
while(!tiaofen);
}
}
if(tiaoshi==0)
{
hour0++;
delay(30);
if(hour0==24)
{
hour0=0;
}
while(!tiaoshi);
}
}
}
/*************显示函数****************/
void LED_Display(uchar hour,uchar minu,uchar sec)
{
datal=segment[hour/10];
datah=segbit[0];
LED_OUT();
delay(2); //这里的延时时间可以更改
datal=segment[hour%10];
datah=segbit[1];
LED_OUT();
delay(2);
datal=0xbf;
datah=segbit[2];
LED_OUT();
delay(2);
datal=segment[minu/10];
datah=segbit[3];
LED_OUT();
delay(2);
datal=segment[minu%10];
datah=segbit[4];
LED_OUT();
delay(2);
datal=0xbf;
datah=segbit[5];
LED_OUT();
delay(2);
datal=segment[sec/10];
datah=segbit[6];
LED_OUT();
delay(2);
datal=segment[sec%10];
datah=segbit[7];
LED_OUT();
delay(2);
}
/*************disp595()函数****************/
void LED_OUT()
{
for(j=0;j<8;j++)
{
SCLK=0;
datal<<=1;
DIO=CY;
SCLK=1;//sh_cp上升沿 移位
}
for(j=0;j<8;j++)
{
SCLK=0;
datah<<=1;
DIO=CY;
SCLK=1;//sh_cp上升沿 移位
}
RCLK=0;
RCLK=1;//st_cp上升沿 存储
}
/*************闹钟函数****************/
void sounde()
{
buzzer=~buzzer;
}
/*************延时函数****************/
void delay(uchar z)
{
int x,y;
for(x=z;x>0;x--)
for(y=125;y>0;y--);
}