注意:本程序仅供参考交流,切莫抄袭!
实验芯片:STC89C52
实验电路板:铁牛单片机电路板
如图:
实现功能:
1、时钟功能,可调整时间,调整位闪烁,到点蜂鸣器发出一声。
2、秒表功能,可开始,暂停,继续,清零。
3、闹钟功能,可调整,到时间蜂鸣器持续发声
代码如下:
/*************************************************************************************/
/********************程序名称:时钟芯片***********************************************/
/********************作者:pchospitalcjk*****************************************************/
/********************完成时间:2012年6月6日*******************************************/
/*************************************************************************************/
/*电子时钟程序,以HH-MM-SS的格式显示时间,并带有时间调校功能,调教时被调校位会闪烁,
带有秒表功能,可以开始,暂停,清零,带有闹钟功能,闹钟可设定,用蜂鸣器进行提醒。*/
#include
#define uchar unsigned char
#define uint unsigned int
char code duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00};
char code wei[]={0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7};
uchar j,i,n,ge,shi,bai,qian,wang,shiwang;
uint number; //时钟中断计数标志位
char h_num,m_num,s_num,Nh_num,Nm_num,Ns_num;
char h_shi,h_ge,m_shi,m_ge,s_shi,s_ge;
uchar mode; //mode为时间选位,mode1为闹钟时间选位
bit fan,mb,nz,sy; //fan标志当前闪烁数码管显示状态,mb标志当前是否是秒表状态,clm标志按钮一再秒表状态按下,nz为闹钟打开标志位,nz1为界面标志位。
sbit fm=P3^4;
sbit key1 = P3^2; //调校按钮
sbit key2 = P3^3; //调校选位按钮
sbit key3 = P1^0; //进入秒表模式
sbit key4 = P1^1; //打开或关闭闹钟
void delay(uchar);
void disp(char,char,char,char,char,char);
void init0();
void init1();
void time_out();
void scankey();
void click1();
void clock();
void stopwatch();
/************主函数***************/
void main()
{
mb=0; //将秒表状态为0
nz=0; //闹钟状态为0
init0(); //初始化时钟中断0寄存器变量
init1(); //初始化时钟中断1寄存器变量
mode = 0; //将调校模式置为0
s_num = 55; //初始化时钟显示时间
m_num = 59;
h_num = 10;
Ns_num = 5; //初始化闹钟显示时间
Nm_num = 0;
Nh_num = 11;
TR1 = 0;
while(1)
{
TR0 = 1; //开启定时器0
if(sy==1) //检测声音标志位是否为1
{
fm=0; //响蜂鸣器
delay(10);
fm=1;
}
scankey(); //键盘扫描 //定时中断0关闭
stopwatch(); //秒表状态函数
time_out(); //时钟状态函数
clock(); //闹钟扫描函数
}
}
/************************显示函数****************************/
void disp(char h_shi,char h_ge,char m_shi,char m_ge,char s_shi,char s_ge)
{
P2 = duan[h_shi];
P1 = wei[0];
delay(5);
P2 = duan[h_ge];
P1 = wei[1];
delay(5);
P2 = duan[10];
P1 = wei[2];
delay(5);
P2=duan[m_shi];
P1=wei[3];
delay(5);
P2=duan[m_ge];
P1=wei[4];
delay(5);
P2=duan[10];
P1=wei[5];
delay(5);
P2=duan[s_shi];
P1=wei[6];
delay(5);
P2=duan[s_ge];
P1=wei[7];
delay(5);
}
/*******************模糊延时函数***********************/
void delay(uchar x)
{
char a,b;
for(a=x;a>0;a--)
for(b=110;b>0;b--);
}
/********************定时器中断0*************************/
void init0()
{
EA=1;
ET0=1;
TMOD=0x11;
TH0=0x4c;
TL0=0x00;
}
/***********************定时中断1****************************/
void init1()
{
ET1=1;
TH0=0x4c;
TL0=0x00;
}
/************************时钟调用函数*******************************/
void time_out()
{
if(j>=20) //如果到1S
{
fan = ~fan; //数码管亮暗交叉显示标志位
j=0; //时钟中断0技术标志位清零
if(s_num>58) //如果秒显示到59
{
s_num = -1;
if(m_num>58) //如果分显示到59
{
m_num = -1;
if(h_num>23) //如果小时显示到23
{
h_num = -1;
}
h_num++;
fm=0; //到整点后蜂鸣器会响一下
delay(50);
fm=1;
}
m_num++;
}
s_num++;
if(h_num>23) //小时手工调校到23时
h_num = 0;
if(m_num>59) //分钟手工调校到59
m_num = 0;
if(nz == 1) //如果在闹钟显示模式下
{
h_shi=Nh_num/10;
h_ge =Nh_num%10;
m_shi=Nm_num/10;
m_ge =Nm_num%10;
s_shi=Ns_num/10;
s_ge =Ns_num%10;
}
if(nz == 0) //如果在秒表显示模式下
{
h_shi=h_num/10;
h_ge =h_num%10;
m_shi=m_num/10;
m_ge =m_num%10;
s_shi=s_num/10;
s_ge =s_num%10;
}
if(mode==1) //如果选中个位
{
if(fan==1) //如果闪烁标志1位为1
{
s_shi = 11; //让个位数码管不亮
s_ge = 11;
}
s_shi = s_shi; //让数码管显示数字
s_ge = s_ge;
}
if(mode==2) //如果选中十位
{
if(fan==1)
{
m_shi = 11; //让十位数码管不亮
m_ge = 11;
}
m_shi = m_shi;
m_ge = m_ge;
}
if(mode==3)
{
if(fan==1)
{
h_shi = 11; //让百位数码管不亮
h_ge = 11;
}
h_shi = h_shi;
h_ge = h_ge;
}
}
if (mb == 0)
disp(h_shi,h_ge,m_shi,m_ge,s_shi,s_ge);
}
/**********************秒表状态函数*******************************/
void stopwatch() //秒表调用函数
{
if(i>=2) //如果到0.1秒
{
i=0;
if(number==999999) //如果计数到最大,就清0。
number=0;
number++;
}
shiwang=number%100000/10000;
wang=number%10000/1000; //求千位的值。这个不难理解吧。不会的翻C语言的书
qian=number%1000/100; //求百位的值。
bai=number%1000%100/10; //求十位的值。
shi=number%10;
ge=0; //求个位的值
if(mb == 1) //如果当前为秒表模式,则在数码管显示秒表计数
disp(shiwang,wang,qian,bai,shi,ge);
}
/*********************键盘扫描函数***********************/
void scankey()
{
if(key2 == 0) //按键二按下
{
delay(10);
if(key2 == 0)
{
if(mb ==0) //如果不在秒表模式下
{
mode++; //数码管选择位增加
if(mode>3) //数码管选择位超过最大值,就返回数码管未选位模式
mode = 0;
}
if(mb == 1){ //如果在秒表模式下
number=0; //计数清零
}
while(!key2);
}
}
if(key1 == 0)
{
delay(10);
//将声音关闭
if(key1 == 0)
{
sy = 0;
if(mb==1) //秒表状态
TR1 = ~TR1; //打开或关闭计数器1
if(mb==0) //时钟状态
click1(); //时间选位调整
while(!key1);
}
}
if(key3 == 0)
{
delay(10);
if(key3 == 0)
{
mb = ~mb; //将秒表标志位取
while(!key3);
}
}
if(key4 == 0)
{
delay(10);
if(key4 == 0)
{
nz = ~nz; //闹钟模式转换
while(!key4); //闹钟界面标志位置反向结果
}
}
}
/*******************数码管选位函数**********************/
void click1(){
switch(mode)
{
case 1:
if(nz==0)
s_num++;
if(nz==1)
Ns_num++;
break;
case 2:
if(nz==0)
m_num++;
if(nz==1)
Nm_num++;
break;
case 3:
if(nz==0)
h_num++;
if(nz==1)
Nh_num++;
break;
}
}
/******************闹钟计算函数*********************/
void clock()
{
if(h_num-Nh_num==0&m_num-Nm_num==0&s_num-Ns_num==0)
sy = 1;
}
/*******************定时中断1(控制时钟)********************/
void time()interrupt 1
{
TH0=0x4c; //因为晶振用的是11.0592MHZ,定义初值15ms.
TL0=0x00;
j++;
}
/****************定时中断1(控制秒表)******************/
void time1()interrupt 3
{
TH0=0x4c; //因为晶振用的是11.0592MHZ。在取初值时,大概定义为一个中断为50MS
TL0=0x00;
i++;
n++;
}