//************************************************
// 功能说明
//************************************************
/*
*主要功能:
*1.提供精确到1/4000秒的时间
*2.可以自己设定时间
*3.可以设定闹钟
*4.支持闹钟再响
*5.支持闹钟开启和关闭
*接口说明:
*1.p3.4接喇叭in接口
*2.p3.5接口接ls377芯片的时钟口
*3.p3.6和p3.7分别接两片ls377的锁存端
*4.p0.0-7和d0.0-7短路
*5.p2.0-7和s1-8短路
*p1.0和p1.2随意接任意led灯
*/
//************************************************
// 数据预定义区域
//************************************************
#include <reg52.h>
//数据别名
#define uchar unsigned char
#define uint unsigned int
//接口别名
#define p0 P0
#define p1 P1
#define p2 P2
#define p3 P3
//端口命名
sbit led1 = P1^0;
sbit led2 = P1^1;
sbit CS1 = P3^6;
sbit CS2 = P3^7;
sbit CLK = P3^5;
sbit Buzzer = P3^4;
//全局数据
uint num,temp;
//时钟变量
uchar second=0,
minute=0,
hour=0;
//闹钟变量
sbit Con=P1^3;
uchar Chour = 0;
uchar Cminute = 3;
//秒表变量
uint Ssecond=0;
uint Centisecond=0;
uint StopSecond=0;
//************************************************
// 定义1-16的字符码显示
//************************************************
uchar code table[] = {
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e,
0x7f,0xbf,0xff/*18*/,0xc8,/*n,19*/
0xf8,0xf1,0xf8/*秒表所用变量*/
};
//************************************************
// 选位
//************************************************
uchar code table2[] = {
0x7f,0xbf,0xdf,0xef,
0xf7,0xfb,0xfd,0xfe/*0-7*/
};
//************************************************
// 函数声明区,函数请在下面查看
//************************************************
void delay2();
void Setlocalandchar(uchar wei,uchar zi);
uchar CathKey();
void showTime();
void openINT();
void FlashTime(uchar i);
void SetTime();
void SetColock();
void ShowStopWatch(uchar IsStop);
void stopwatch();
void closeINT();
//************************************************
// 主函数区
//************************************************
void main()
{
Con=1;//闹钟默认开启
Buzzer=0;//响铃默认关闭
openINT();//开启中断
while (1)
{
if (CathKey()==1)//关闭闹钟
{
Buzzer=0;
while(CathKey()==1);
}
if (CathKey() == 4)//设定时间
{
while(CathKey() == 4);
SetTime();
}
if(CathKey() == 8)//设定闹钟
{
while (CathKey() == 8);
SetColock();
}
if (CathKey() == 6)//进入秒表模式
{
while(CathKey() == 6);
stopwatch();
}
else
{
showTime();//默认显示时间
}
}
}
//************************************************
// 延迟函数,视觉残留
//************************************************
void delay2()
{
uchar i,j;
for (i = 25;i>0;i--)
for (j = 15;j>0;j--);
}
//************************************************
// 在指定的位置上显示指定的字符
//************************************************
void Setlocalandchar(uchar wei,uchar zi)
{
//设定位置
P0 = table2[wei];//wei = 要放进去的为止0-7
CLK = 0;//时钟端电平拉低
CS2 = 0;//锁存端打开
// 默认这时候因为电器特性,p0的值会存进锁存端里面
CLK = 1;//时钟端电平拉低
CS2 = 1;//锁存端关闭
//给初值
P0 = table[zi];//zi = 要放进去的字
CLK = 0;//同理
CS1 = 0;
CLK = 1;
CS1 = 1;
delay2();//延迟函数,余辉效应,如不舒适,可以自行调教
}
//************************************************
// 获取键盘函数
//************************************************
uchar CathKey()
{
uchar i;
//软件去按键抖动
if(p2 != 0xff)
{
for (i=500;i>0;i++);
if (p2 != 0xff)
{
if (p2 == 0xfe)//对p2进行获取数字
{
return 1;
}
if (p2 == 0xfd)
{
return 2;
}
if (p2 == 0xfb)
{
return 3;
}
if (p2 == 0xf7)
{
return 4;
}
if (p2 == 0xef)
{
return 5;
}
if (p2 == 0xdf)
{
return 6;
}
if (p2 == 0xbf)
{
return 7;
}
if (p2 == 0x7f)
{
return 8;
}
}
}
return 0;//没有的话默认返回按键零
}
//************************************************
// 开启中断
//************************************************
void openINT()
{
TMOD=0x02;//定义为模式2
TH0=6;//装入初值
TL0=6;//装入初值
EA=1;//开总中断
ET0=1;//开定时器中断
TR0=1;//启动定时器0
}
//************************************************
// 关闭中断
//************************************************
void closeINT()
{
TMOD=0x02;//定义为模式2
TH0=0;//装入初值
TL0=0;//装入初值
EA=0;//开总中断
ET0=0;//开定时器中断
TR0=0;//启动定时器0
}
//************************************************
// 中断1所进行的动作,每个时钟周期都会中断一次
//************************************************
void T0_time() interrupt 1 //中断1
{
num++;
if (num >= 4000)//这时候的num会大于256,所以要用uint定义
{
num = 0;
led1 = ~led1;
second++;
Ssecond++;
}
//这里每个中断检查一次而不是一秒检查一次是因为
// 如果我们手动调节太快可能不会在秒过十的时候自动进1
//对秒表进行响应
if(Ssecond == 999)
{
Ssecond=0;
}
//对时钟进行响应
if (second == 60)
{
second = 0;
minute++;
}
if (minute == 60)
{
minute = 0;
hour++;
}
if (hour ==24)
{
hour=0;
}
if (Chour==24)
{
Chour=0;
}
if (Cminute==60)
{
Cminute=0;
}
//接下来对闹钟进行响应
if (Chour == hour)
{
if (Cminute == minute)
{
if(Con == 1)
{
//设时候闹钟响了;
Buzzer=1;
Con=0;//闹钟再响关闭
}
}
}
}
//************************************************
// 驱动显卡显示时钟
//************************************************
void showTime()
{
Setlocalandchar(7,second%10);
Setlocalandchar(6,second/10);
Setlocalandchar(5,17);
Setlocalandchar(4,minute%10);
Setlocalandchar(3,minute/10);
Setlocalandchar(2,17);
Setlocalandchar(1,hour%10);
Setlocalandchar(0,hour/10);
}
//************************************************
// 显示秒表时间 0表示动态,1表示静态
//************************************************
void ShowStopWatch(uchar IsStop)
{
Setlocalandchar(7,Centisecond%10);
Setlocalandchar(6,Centisecond/10);
Setlocalandchar(5,17);
if (IsStop == 1)
{
Setlocalandchar(4,StopSecond%10);
Setlocalandchar(3,(StopSecond/10)%10);
Setlocalandchar(2,StopSecond/100);
}
else
{
Setlocalandchar(4,Ssecond%10);
Setlocalandchar(3,(Ssecond/10)%10);
Setlocalandchar(2,Ssecond/100);
}
Setlocalandchar(0,18);
// 这里是在一秒内显示一个动态图像
// 分三个阶段进行,为节约资源,比较有进行划分
if (Centisecond<34)
{
Setlocalandchar(0,20);
}
if (Centisecond<70)
{
Setlocalandchar(0,21);
}
else
{
Setlocalandchar(0,22);
}
}
//************************************************
// 设定时间函数,需美化
//************************************************
void SetTime()
{
//当按键按下时候
// 首先应该进行的是01 34 67的位置的设定
while(1)
{
// 一秒显示,一秒隐藏
Sethour:// 首先,先隐藏位置01
while(1)//这时候会停留在设置时的位置上,下面同理
{
FlashTime(0);
//这时候选择按键,s5为向上,s6为向下
//s4为跳出这个循环
if (CathKey() == 5)//只能向上调
{
while (CathKey() == 5);
hour++;
}
if (CathKey() == 4)//跳到下一步
{
while(CathKey() == 4);
goto setMinute;
}
}
setMinute:// 再者,隐藏位置34
while(1)//这时候会停留在设置时的位置上,下面同理
{
FlashTime(1);
//这时候选择按键,s5为向上,s6为向下
//s4为跳出这个循环
if(CathKey() == 5)
{
while (CathKey() == 5);//只能向上调
minute++;
}
if (CathKey() == 4)// 跳出大循环
{
while(CathKey() == 4);
return ;
}
}
}
}
//************************************************
// 闪烁时间,函数对指定位置的数字进行闪烁
//************************************************
void FlashTime(uchar i)
{
switch (i)
{
case 0:// 当光标停留在设定小时
Setlocalandchar(7,second%10);
Setlocalandchar(6,second/10);
Setlocalandchar(5,17);
Setlocalandchar(4,minute%10);
Setlocalandchar(3,minute/10);
Setlocalandchar(2,17);
if (second%2 == 0)
{
Setlocalandchar(1,18);
Setlocalandchar(0,18);
}
else
{
Setlocalandchar(1,hour%10);
Setlocalandchar(0,hour/10);
}
break;
case 1:// 当光标停留在设定分钟时候
Setlocalandchar(7,second%10);
Setlocalandchar(6,second/10);
Setlocalandchar(5,17);
if (second%2 == 0)
{
Setlocalandchar(4,18);
Setlocalandchar(3,18);
}
else
{
Setlocalandchar(4,minute%10);
Setlocalandchar(3,minute/10);
}
Setlocalandchar(2,17);
Setlocalandchar(1,hour%10);
Setlocalandchar(0,hour/10);
break;
case 2: //当光标停留在on和no的时候
Setlocalandchar(7,Cminute%10);
Setlocalandchar(6,Cminute/10);
Setlocalandchar(5,17);
Setlocalandchar(4,Chour%10);
Setlocalandchar(3,Chour/10);
Setlocalandchar(2,17);
if (second%2 == 0)
{
Setlocalandchar(1,18);
Setlocalandchar(0,18);
}
else
{
if (Con == 0)//no
{
Setlocalandchar(1,0);
Setlocalandchar(0,19);
}
else
{
Setlocalandchar(1,19);
Setlocalandchar(0,0);
}
}
break;
case 3://当光标停留在设置闹钟小时
Setlocalandchar(7,Cminute%10);
Setlocalandchar(6,Cminute/10);
Setlocalandchar(5,17);
if (second%2 == 0)
{
Setlocalandchar(4,18);
Setlocalandchar(3,18);
}
else
{
Setlocalandchar(4,Chour%10);
Setlocalandchar(3,Chour/10);
}
Setlocalandchar(2,17);
if (Con == 0)//no
{
Setlocalandchar(1,0);
Setlocalandchar(0,19);
}
else
{
Setlocalandchar(1,19);
Setlocalandchar(0,0);
}
break;
case 4://当光标停留在设置闹钟分钟
if (second%2 == 0)
{
Setlocalandchar(7,18);
Setlocalandchar(6,18);
}
else
{
Setlocalandchar(7,Cminute%10);
Setlocalandchar(6,Cminute/10);
}
Setlocalandchar(5,17);
Setlocalandchar(4,Chour%10);
Setlocalandchar(3,Chour/10);
Setlocalandchar(2,17);
if (Con == 0)//no
{
Setlocalandchar(1,0);
Setlocalandchar(0,19);
}
else
{
Setlocalandchar(1,19);
Setlocalandchar(0,0);
}
break;
}
}
//************************************************
// 设置闹钟函数,no,on表示闹钟开启关闭状态
//************************************************
// 闹钟变量
// uchar Csecond=0;
// uchar Cminute=0;
// uchar Con=0;
void SetColock()
{
while(1)
{
//一开始要先显示前面两位
// 先调教两位
while (1)
{
FlashTime(2);
if (CathKey() == 5)// 设定闹钟开启和关闭
{
while(CathKey() == 5);
Con=~Con;
}
if (CathKey() == 4)
{
while(CathKey() == 4);//调到下一步
goto SetColockhour;
}
}
// 然后再调教小时
SetColockhour:
while (1)
{
FlashTime(3);
if (CathKey() == 5)
{
while(CathKey() == 5);// 小时++
Chour++;
}
if (CathKey() == 4)
{
while(CathKey() == 4);// 跳到下一步
goto SetColockminute;
}
}
// 最后再调教分钟
SetColockminute:
while (1)
{
FlashTime(4);
if (CathKey() == 5)// 分钟++
{
while(CathKey() == 5);
Cminute++;
}
if (CathKey() == 4)// 跳出该函数
{
while(CathKey() == 4);
return ;
}
}
}
}
//************************************************
// 秒表函数
//************************************************
void stopwatch()
{
//毫秒用100来显示
//每次慢100进1
int tempSscond;
StopWait:
while(1)//等待,并且数据清零
{
Ssecond=0;
Centisecond=0;
ShowStopWatch(0);
if (p2 == 0xbf)
{
goto StopStart;// 开始执行下一步
}
}
StopStart:
while(1)
{
Centisecond=num/40;// 显示精度为
ShowStopWatch(0);
if (p2 == 0xfb)
{
StopSecond = Ssecond;
goto Stopstop;
}
}
Stopstop:
while(1)
{
ShowStopWatch(1);//显示秒表
if(p2 == 0xef) // 复位
{
goto StopWait;
}
if (p2 == 0xfe) // 退出
{
goto Stopexit;
}
if(p2 == 0xbf) //继续
{
Ssecond=StopSecond;// 赋予静态函数
goto StopStart;
}
}
Stopexit:
return ;
}
//************************************************
// Last Version:2011年5月2日9:29:48
//************************************************
//************************************************
// Edit by HXH
//************************************************