基于单片机的多功能时钟设计
程序员文章站
2022-06-08 20:49:14
...
基于单片机的多功能时钟设计
目的
设计一款可显示时间、日历和闹钟的多功能数字时钟
元器件
- AT89C51单片机
- 数码管
- 74HC138译码器、74HC573锁存器、74HC02或非门
- 按键若干、电阻若干、电源若干
- 蜂鸣器等
电路原理图
功能
初始化:默认为时钟状态为00—00—00,日历为20—07—02,闹钟为00—00—00。
按键功能
- 按键s1定义为状态切换键,可以按顺序切换时钟界面,日历界面,闹钟界面;
- 在设置状态下,按键s1定义为确认功能,完成设置;
- 按键s2定义为设置键,在时钟界面下 通过该键可以进入时钟设置界面,通过该键可以切换新选择待调>整的时、分、秒,当前选择的显示单元以0.5s为间隔亮灭。在日历界面下同样做此功能 。在闹钟设置>界面下,在上述功能外增加调节闹钟持续时长功能;
- 按键s3定义为“加”按键;
- 按键s4定义为“减”按键;
- 特殊说明:
按键s3,s4只在时钟设置,日历设置或者闹钟设置状态下有效。- 闹钟提示功能
- 用1KHZ的方波驱动蜂鸣器,初始持续时间为10s,可通过按键s2进行设置;
- 闹钟提示状态下,按任意键可关闭蜂鸣器。
代码:
#include <reg51.h>
#include <absacc.h>
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
sbit s4=P3^3;
sbit buzzer=P1^0;
unsigned char code SMG_duanma[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共阳极数码管
unsigned char code SMG_position[9]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位选
unsigned char yi,er,san,si,wu,liu,qi,ba;
unsigned char SMGflag=1,s1_flag=1,s2_flag=1;
unsigned char cnt,state=1,alarm1=0;//state:0.5s闪烁标志,alarm1:闹钟状态标志
signed char Timer[3]={0,0,0},Timer_set[3]={0,0,0};Alarm[3]={0,0,0},Calendar[3]={20,7,2},time=10;//time为闹钟时长
void Time_set();
void Rili_set();
void Alarm_set();
void delay_ms(unsigned int n)
{
unsigned int i=0,j=0;
for(i=0;i<n;i++)
for(j=0;j<123;j++);
}
void SMG_select(unsigned char pos,unsigned char dat)
{
XBYTE[0Xc000]=SMG_position[pos];
XBYTE[0Xe000]=SMG_duanma[dat];
}
void SMG_control() //数码管控制
{
if(SMGflag==1) Time_set();
else if(SMGflag==2) Rili_set();
else if(SMGflag==3) Alarm_set();
}
void SMG_Display()
{
SMG_control();
SMG_select(1,yi) ;delay_ms(2);
SMG_select(2,er) ;delay_ms(2);
SMG_select(3,san);delay_ms(2);
SMG_select(4,si) ;delay_ms(2);
SMG_select(5,wu) ;delay_ms(2);
SMG_select(6,liu);delay_ms(2);
SMG_select(7,qi) ;delay_ms(2);
SMG_select(8,ba) ;delay_ms(2);
}
void InitTimer()//初始化定时器
{
TMOD=0X11; //定时器0,工作方式1
TH0=(65536-50000)/256;//定时50ms
TL0=(65536-50000)%256;
TH1=(65536-500)/256;//定时0.5ms产生1KHZ方波
TL1=(65536-500)%256;
ET0=1;
TR0=1;
ET1=1;
EA=1;
PT0=1;//定时器0优先级高
}
void Timer0() interrupt 1 //定时器0中断
{
TH0=(65536-50000)/256;//定时50ms,装载初值
TL0=(65536-50000)%256;
cnt++;
if(cnt%10==0) state=!state;//0.5s闪烁一次
if(cnt==20)
{
cnt1=0;
Timer[2]++; //秒++
if(Timer[2]==60)//60s时间到
{
Timer[2]=0;//秒清零
Timer[1]++;//分++
if(Timer[1]==60)//60min时间到
{
Timer[1]=0;//分清零
Timer[0]++;//时++
if(Timer[0]==24)//24小时时间到
{
Timer[0]=0;//时清零
Calendar[2]++; //日++
if(Calendar[1]==1||Calendar[1]==3||Calendar[1]==5||Calendar[1]==7||Calendar[1]==8||Calendar[1]==10||Calendar[1]==12)
{//大月
if(Calendar[2]==32)
{
Calendar[2]=1;
Calendar[1]++;//月++
if(Calendar[1]==13)
{
Calendar[1]=1;
Calendar[0]++;//年清0
if(Calendar[0]==100)Calendar[0]=0;
}
}
}
else if((Calendar[1]==4)||(Calendar[1]==6)||(Calendar[1]==9)||(Calendar[1]==11)&&(Calendar[2]==31))
{//小月
Calendar[2]=1;
Calendar[1]++;
if(Calendar[1]==13)
{
Calendar[1]=1;
Calendar[0]++;
if(Calendar[0]==100)Calendar[0]=0;
}
}
else if(Calendar[0]%4==0&Calendar[0]%100!=0||Calendar[0]%400==0&Calendar[1]==2&Calendar[2]==30)
{//闰二月
Calendar[2]=1;
Calendar[1]++;
if(Calendar[1]==13)
{
Calendar[1]=1;
Calendar[0]++;
if(Calendar[0]==100)Calendar[0]=0;
}
}
else if(Calendar[1]==2&Calendar[2]==29)
{//非闰二月
Calendar[2]=1;
Calendar[1]++;
if(Calendar[1]==13)
{
Calendar[1]=1;
Calendar[0]++;
if(Calendar[0]==100)Calendar[0]=0;
}
}
}
}
}
}
}
void Timer1() interrupt 3
{
TH1=(65536-500)/256;
TL1=(65536-500)%256;
buzzer=!buzzer;//buzzer=0,蜂鸣器打开;buzzer=1,蜂鸣器关闭。
if((Timer[2]-Alarm[2])>time)//闹钟持续时长为time
{
alarm1=0;
TR1=0;
buzzer=1;
}
}
void Time_set() //时间设置
{
if(s1_flag==1)//时间设置界面
{
if(s2_flag==1) //时钟开启
{ //时钟状态‘-’字符1s闪烁一次
if(Timer[2]%2==0){yi=Timer[0]/10;er=Timer[0]%10;san=liu=10;si=Timer[1]/10;wu=Timer[1]%10;qi=Timer[2]/10;ba=Timer[2]%10;}
else {yi=Timer[0]/10;er=Timer[0]%10;san=liu=11;si=Timer[1]/10;wu=Timer[1]%10;qi=Timer[2]/10;ba=Timer[2]%10;}
}
else if (s2_flag==2)//时设置,时0.5s闪烁一次
{
san=liu=10;si=Timer_set[1]/10;wu=Timer_set[1]%10;qi=Timer_set[2]/10;ba=Timer_set[2]%10;
if(state==1){yi=Timer_set[0]/10;er=Timer_set[0]%10;}
else if(state==0) {yi=11;er=11;} //熄灭
}
else if(s2_flag==3)//分设置,分0.5s闪烁一次
{
yi=Timer_set[0]/10;er=Timer_set[0]%10;san=liu=10;qi=Timer_set[2]/10;ba=Timer_set[2]%10;
if(state==1){si=Timer_set[1]/10;wu=Timer_set[1]%10;}
else if(state==0) {si=11;wu=11;}
}
else if(s2_flag==4)//秒设置,秒0.5s闪烁一次
{
yi=Timer_set[0]/10;er=Timer_set[0]%10;san=liu=10;si=Timer_set[1]/10;wu=Timer_set[1]%10;
if(state==1){qi=Timer_set[2]/10;ba=Timer_set[2]%10;}
else if(state==0) {qi=11;ba=11;}
}
}
}
void Rili_set() //日历设置
{
if(s1_flag==2)//日历设置界面
{
if(s2_flag==1) {yi=Calendar[0]/10;er=Calendar[0]%10;san=liu=10;si=Calendar[1]/10;wu=Calendar[1]%10;qi=Calendar[2]/10;ba=Calendar[2]%10;}
else if(s2_flag==2) //年设置
{
san=liu=10;si=Calendar[1]/10;wu=Calendar[1]%10;qi=Calendar[2]/10;ba=Calendar[2]%10;
if(state==1) {yi=Calendar[0]/10;er=Calendar[0]%10;}
else {yi=11;er=11;}
}
else if(s2_flag==3) //月设置
{
yi=Calendar[0]/10;er=Calendar[0]%10;san=liu=10;qi=Calendar[2]/10;ba=Calendar[2]%10;
if(state==1) {si=Calendar[1]/10;wu=Calendar[1]%10;}
else {si=11;wu=11;}
}
else if(s2_flag==4) //日设置
{
yi=Calendar[0]/10;er=Calendar[0]%10;san=liu=10;si=Calendar[1]/10;wu=Calendar[1]%10;
if(state==1) {qi=Calendar[2]/10;ba=Calendar[2]%10;}
else {qi=11;ba=11;}
}
}
}
void Alarm_set() //闹钟设置
{
if(s1_flag==3)//闹钟设置界面
{
if(s2_flag==1) {yi=Alarm[0]/10;er=Alarm[0]%10;san=liu=10;si=Alarm[1]/10;wu=Alarm[1]%10;qi=Alarm[2]/10;ba=Alarm[2]%10;}
else if (s2_flag==2)//时设置,时单元0.5s闪烁一次
{
san=liu=10;si=Alarm[1]/10;wu=Alarm[1]%10;qi=Alarm[2]/10;ba=Alarm[2]%10;
if(state==1){yi=Alarm[0]/10;er=Alarm[0]%10;}
else if(state==0) {yi=11;er=11;} //熄灭
}
else if(s2_flag==3)//分设置,分单元0.5s闪烁一次
{
yi=Alarm[0]/10;er=Alarm[0]%10;san=liu=10;qi=Alarm[2]/10;ba=Alarm[2]%10;
if(state==1){si=Alarm[1]/10;wu=Alarm[1]%10;}
else if(state==0) {si=11;wu=11;}
}
else if(s2_flag==4)//秒设置,秒单元0.5s闪烁一次
{
yi=Alarm[0]/10;er=Alarm[0]%10;san=liu=10;si=Alarm[1]/10;wu=Alarm[1]%10;
if(state==1){qi=Alarm[2]/10;ba=Alarm[2]%10;}
else if(state==0) {qi=11;ba=11;}
}
else if(s2_flag==5)//闹钟时长设置界面
{
yi=er=san=si=wu=liu=11;qi=time/10;ba=time%10;
}
}
}
void Alarming() //闹钟提醒模式
{
if(Timer[0]==Alarm[0]&Timer[1]==Alarm[1]&Timer[2]==Alarm[2])
{
alarm1=1; //闹钟标志位置1
TR1=1; //开启定时器T1
}
}
void keyscan()//按键扫描函数
{
if(s1==0) //时钟、日历、闹钟切换
{
delay_ms(10);//按键消抖
if(s1==0)
{
if(alarm1==0) //非闹钟提醒状态
{
if(s2_flag==1)//非设置状态下,s1切换界面
{
switch(s1_flag)
{
case 1:s1_flag=2;SMGflag=2;break;//日历界面
case 2:s1_flag=3;SMGflag=3;break;//闹钟界面
case 3:s1_flag=1;SMGflag=1;break;//时间界面
}
}
else if(s2_flag!=1)//设置状态下,s1为确认键
{
s2_flag=1;
if(s1_flag==1) {Timer[0]=Timer_set[0];Timer[1]=Timer_set[1];Timer[2]=Timer_set[2];}
}
}
else {alarm1=0;buzzer=1;TR1=0;} //任意键关闭闹钟
}
while(s1==0) SMG_Display(); //松手检测
}
if(s2==0) //设置位置切换
{
delay_ms(10);//按键消抖
if(s2==0)
{
if(alarm1==0)//非闹钟提醒状态
{
if(s1_flag==1)//时间界面下
{
switch(s2_flag)
{
case 1:s2_flag=2;break;//设置时
case 2:s2_flag=3;break;//设置分
case 3:s2_flag=4;break;//设置秒
case 4:s2_flag=2;break;//循环设置
}
}
else if(s1_flag==2)//日历界面下
{
switch(s2_flag)
{
case 1:s2_flag=2;break;//设置年
case 2:s2_flag=3;break;//设置月
case 3:s2_flag=4;break;//设置日
case 4:s2_flag=2;break;//循环设置
}
}
else if(s1_flag==3)//闹钟界面下
{
switch(s2_flag)
{
case 1:s2_flag=2;break;//设置时
case 2:s2_flag=3;break;//设置分
case 3:s2_flag=4;break;//设置秒
case 4:s2_flag=5;break;//设置闹钟持续时长
case 5:s2_flag=2;break;//循环设置
}
}
}
else if(alarm1==1)
{alarm1=0;buzzer=1;TR1=0;}//任意键关闭闹钟
}
while(s2==0)SMG_Display();//松手检测
}
if(s3==0) // s3 +
{
delay_ms(10);//按键消抖
if(s3==0)
{
if(alarm1==0) //非闹铃提醒状态
{
if(s1_flag==1)//时间界面
{
switch(s2_flag)
{
case 2:Timer_set[0]++;if(Timer_set[0]==24) Timer_set[0]=0;break;//时+
case 3:Timer_set[1]++;if(Timer_set[1]==60) Timer_set[1]=0;break;//分+
case 4:Timer_set[2]++;if(Timer_set[2]==60) Timer_set[2]=0;break;//秒+
}
}
else if(s1_flag==2)//日历界面
{
switch(s2_flag)
{
case 2:Calendar[0]++;if(Calendar[0]==100) Calendar[0]=0; break;//年+
case 3:Calendar[1]++;if(Calendar[1]==13 ) Calendar[1]=1; break;//月+
case 4:Calendar[2]++;if(Calendar[2]==31 ) Calendar[2]=0; break;//日+
}
}
else if(s1_flag==3)//闹钟界面
{
switch(s2_flag)
{
case 2:Alarm[0]++;if(Alarm[0]==24) Alarm[0]=0;break;//时+
case 3:Alarm[1]++;if(Alarm[1]==60) Alarm[1]=0;break;//分+
case 4:Alarm[2]++;if(Alarm[2]==60) Alarm[2]=0;break;//秒+
case 5:time++ ;if(time==61) time=0; break;//设置闹钟时长,最长为60s
}
}
}
else if(alarm1==1)
{alarm1=0;buzzer=1;TR1=0;}//任意按键关闭闹钟
}
while(s3==0)SMG_Display();//松手检测
}
if(s4==0) // s4 -
{
delay_ms(10);//按键消抖
if(s4==0)
{
if(alarm1==0)//非闹铃提醒状态
{
if(s1_flag==1)//时间界面
{
switch(s2_flag)
{
case 2:Timer_set[0]--;if(Timer_set[0]==-1) Timer_set[0]=23;break;//时-
case 3:Timer_set[1]--;if(Timer_set[1]==-1) Timer_set[1]=59;break;//分-
case 4:Timer_set[2]--;if(Timer_set[2]==-1) Timer_set[2]=59;break;//秒-
}
}
else if(s1_flag==2)//日历界面
{
switch(s2_flag)
{
case 2:Calendar[0]--;if(Calendar[0]==0) Calendar[0]=99; break;//年-
case 3:Calendar[1]--;if(Calendar[1]==0) Calendar[1]=12; break;//月-
case 4:Calendar[2]--;if(Calendar[2]==0) Calendar[2]=31; break;//日-
}
}
else if(s1_flag==3)//闹钟界面
{
switch(s2_flag)
{
case 2:Alarm[0]--;if(Alarm[0]==-1) Alarm[0]=23;break;//时-
case 3:Alarm[1]--;if(Alarm[1]==-1) Alarm[1]=59;break;//分-
case 4:Alarm[2]--;if(Alarm[2]==-1) Alarm[2]=59;break;//秒-
case 5:time-- ;if(time==-1) time=60; break;//设置闹钟时长-
}
}
}
else if(alarm1==1)
{alarm1=0;buzzer=1;TR1=0;}//闹钟状态下,任意键可以关闭闹钟
}
while(s4==0)SMG_Display();//松手检测
}
}
void main()
{
InitTimer();
while(1)
{
SMG_Display();
keyscan();
Alarming();
}
}