单片机控制多位数码管的电子时钟程序
1、软件编程:
keil工程C语言代码:
2、/***************************************
项目名称:数码管电子时钟
实现功能:数码管显示时间、日期,时间、日
期可调,可设置闹钟,闹铃响一分钟。
****************************************/
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uint numwe,tt,t,numdu,set,aclock,rili;
unsigned long int time,time1=0;
unsigned long int second,minute,hour,year=2012,month=12,day=31;
uchar code du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar code we[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar Mth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};//每月对应的天数
uchar YMth[13]={0,2,9,2,1,2,1,2,2,1,2,1,2};
sbit dula=P2^0;
sbit wela=P2^1;
sbit KEY0=P3^2;//选位
sbit KEY1=P3^1;//加一
sbit KEY2=P3^0;//设闹铃
sbit KEY3=P3^3;
sbit beep=P2^2;//响铃
void Delay(uint del);//延时程序
void Display(uint sd,uint mm,uint hy);//显示程序
void add();//加一
void alarmclock();//闹钟
void init();//初始化
int clock();//计算时间
void Calender();//计算日期
void main()
{
P2=0xff;
init();
while(1){
add();
if(rili==1)//分日历和时间显示
Display(day,month,year);
else
Display(second,minute,hour);
alarmclock();
}
}
void Display(uint sd,uint mm,uint hy)
{ int y0,y1,y2;
if(rili==1)
{
y0=hy/1000,y1=hy%1000;y2=hy%100;
}
for(numwe=0;numwe<8;numwe++)
{
P0=0xff;
wela=1;
P0=we[numwe];
wela=0;
P0=0xff;
dula=1;
switch(numwe)
{
case 0:
P0=(tt==1&set==1)?0x00:(rili==1)?du[y0]:du[hy/10];break;
case 1:
P0=(tt==1&set==2)?0x00:(rili==1)?du[y1/100]:du[hy%10];break;
case 2:
P0=(rili!=1)?0x40:(tt==1&set==3)?0x00:du[y2/10];break;
case 3:
P0=(tt==1&set==4)?0x00:(rili==1)?du[hy%10]+0x80:du[mm/10];break;
case 4:
P0=(tt==1&set==5)?0x00:(rili==1)?du[mm/10]:du[mm%10];break;
case 5:
P0=(rili!=1)?0x40:(tt==1&set==6)?0x00:du[mm%10]+0x80;break;
case 6:
P0=(tt==1&set==7)?0x00:du[sd/10];break;
case 7:
P0=(tt==1&set==8)?0x00:du[sd%10];break;
}
dula=0;
Delay(5);
}
}
void init()//初始化
{
wela=0;
dula=0;
TMOD=0x01;//设置定时器0为工作方式1
TH0=(65536-50000)/256;//定时器高八位//定时5ms
TL0=(65536-50000)%256;//定时器低八位
IE=0x8f;//开启中断
TCON=0x15;//启动定时器及工作方式
}
int clock()//计算时间
{
if(t==10|t==20) tt=!tt;//闪烁标志位
if(t==20)
{
t=0;
if(!(set!=0&aclock==0))
time++;
if(time>=time1&time<time1+60)
beep=0;
else
beep=1;
Calender();
if(aclock==0)
{
second=time%60;
minute=(time%3600)/60;
hour=time/3600;
if(hour==24)
{
time=0;
hour=0;
}
}
else
{
second=time1%60;
minute=(time1%3600)/60;
hour=time1/3600;
if(hour==24)
{
time=0;
hour=0;
}
}
}
}
void Delay(uint del)
{
uint i,j;
for(i=0; i<del; i++)
for(j=0; j<100; j++);
}
void timer0() interrupt 1//定时器0中断
{
TH0=(65536-50000)/256;//定时器高八位//定时5ms
TL0=(65536-50000)%256;//定时器低八位
t++;
clock();
}
void settime() interrupt 0//it0
{
if(KEY0==0)
{
Delay(2);
if(KEY0==0)
{ if(rili!=1)
{if(set==2|set==5) set=set+2; else set++;}
else
set++;
if(set==9)
{set=0;t=0;}
//while(!KEY0);
}
}
}
void calendar() interrupt 2//日历
{
if(KEY3==0)
{
Delay(2);
if(KEY3==0)
rili=!rili;
set=0;aclock=0;
}
}
void Calender()//计算日历
{
if(time==86400)
{
day++;
if((year%4==0&year%100!=0)|(year%400==0))
Mth[2]=29;
else
Mth[2]=28;
if(day>Mth[month])
{
day=1;
month++;
if(month>12)
{month=1;
year++;}
}
}
}
void add()//自加一
{
int ge,ge1,ge2,shi,shi1,shi2,bai2,qian2;
if(rili==1)
{
ge=day%10;ge1=month%10;ge2=year%10;
shi=day/10;shi1=month/10;shi2=year%100/10;
bai2=year%1000/100;qian2=year/1000;
}else
{
ge=second%10;ge1=minute%10;ge2=hour%10;
shi=second/10;shi1=minute/10;shi2=hour/10;
}
if(KEY1==0)
{
Delay(2);
if(KEY1==0)
{
if(rili==1)
{
if((year%4==0&year%100!=0)|(year%400==0))
YMth[2]=10;
else
YMth[2]=9;
switch(set)
{
case 1:qian2=(qian2+1)%10;break;
case 2:bai2=(bai2+1)%10;break;
case 3:shi2=(shi2+1)%10;break;
case 4:ge2=(ge2+1)%10;break;
case 5:shi1=(shi1+1)%2;break;
case 6:ge1=(shi1==1)?(ge1+1)%3:(ge1+1)%10;break;
case 7:shi=(month==2)?(shi+1)%3:(shi+1)%4;break;
case 8:ge=(shi==3)?(ge+1)%YMth[month]:(month==2)?(ge+1)%YMth[2]:(ge+1)%10;break;
}
year=qian2*1000+bai2*100+shi2*10+ge2;
month=shi1*10+ge1;
day=shi*10+ge;
}else
{
switch(set)
{
case 1: shi2=(shi2+1)%3;break;
case 2: ge2=(ge2+1)%4;break;
case 4: shi1=(shi1+1)%6;break;
case 5: ge1=(ge1+1)%10;break;
case 7: shi=(shi+1)%6;break;
case 8: ge=(ge+1)%10;break;
}
second=shi*10+ge; minute=shi1*10+ge1;hour=shi2*10+ge2;
if(aclock==0)
time=hour*3600+minute*60+second;
else
time1=hour*3600+minute*60+second;
}
while(!KEY1);
}
}
}
void alarmclock()//设置闹铃
{
if(KEY2==0)
{
Delay(2);
if(KEY2==0)
{
while(!KEY2);
aclock=1;
rili=0;
set=0;
while(1)
{
if(rili==1)
Display(day,month,year);
else
Display(second,minute,hour);
add();
if(KEY2==0)
{
while(!KEY2);
aclock=0;
set=0;
break;
}
}
}
}
}
3、引脚连接说明:
1、PO口接8为共阴数码管;
2、P2^0与P2^1分别为数码管的段锁存与位锁存;
3、P3^0为闹钟显示功能按键
P3^1为设置时钟时的数字调整,单向增大
P3^2为设置键,可对闹钟,日期,时间选择进行设置
P3^3为日立与时间的转换查看键
4、闹钟可选用led灯或者蜂鸣器,默认提醒时长为1分钟
4、软件仿真与实验效果:

