admin管理员组文章数量:1532656
2024年5月7日发(作者:)
【单片机】c51数字时钟(带年月日显示)
显示当前时间:9点58分34秒 (第一个零表示闹钟未开启)
当前日期:10年4月六日
摘要:本设计以单片机为核心,LED数码管动态扫描显示。采用矩阵式键盘输
入能任意修改当前时间日期和设定闹钟时间。具有显示年月日(区分闰年和二
月),闹钟报警和整点报时功能
说明
系统的功能选择由7个按键完成。
其中P3.0,P3.1分别对应调整当前时间的时和分,
P3.2为外部中断0,控制闹钟功能的开启/关闭(开启时数码管第一位显示字母’
c’)
P3.3用作外部中断1,当前时间的显示与闹铃时间显示切换,闹钟显示时按
P3.0,P3.1可进行闹钟时分的设定,此时,led1灯灭。闹铃时间到切闹钟开关开
启时,闹铃响一分钟。
P3.5P3.6P3.7对年月日进行调整(第一次按P3.5,就进入了年月日的显示,现
在就可对日期进行调整)。按P3.1回到当前时间的显示状态。
整点到时:报警对应小时的次数。
程序如下:
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
uchar data keyvalue; //查到的键值
uchar data keys; //转换出的数字
uchar dis[8];
uchar code
seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x40,0x00,0x
39,0xf7};
// 0 1 2 3 4
5 6 7 8 9 - 灭灯 c n
sbit led_duan=P2^6; //段选通
sbit led_wei=P2^7; //位选通
sbit speaker=P2^3; //蜂鸣器
sbit minitek=P3^0; //分校正 按键
sbit hourk=P3^1; //小时校正 按键
sbit p3_4=P3^4; //
sbit yeark=P3^5; //年
sbit monthk=P3^6; //月
sbit dayk=P3^7; //日
uchar data wei,i;
bit leap_year; //闰年标志位
bit dis_nyr;
bit cal_year=1;
bit calculate=1; //显示 年月日 与 当前时间切换标志
uchar data c_min; //闹钟‘分寄存单元
uchar data c_hou; //闹钟、小时寄存单元
uchar data second; //秒
uchar data minite; //分变量
uchar data hour; //小时变量
uchar data year,month,day; //定义年月日变量
uchar data CNTA;
uchar data speaker_num; //蜂鸣次数
bit beep; //整点报时标志
bit run; //运行标志
bit flash; //灭灯标志
bit clarm_switch; //闹钟开关标志
bit baoshi; //报时开关标志
sbit led1=P1^6; // 按键标识指示灯
sbit led2=P1^7; // 运行标志指示灯
sbit P3_2=P3^2;
sbit P3_3=P3^3;
uint n,k;
/*10微秒级延时*/
void delay_10us(uchar n)
{ do
{ _nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
/***毫秒级延时 ***/
void delay_ms(uint n)
{ do delay_10us(131);
while(--n);
}
/****** 当前时间转换******/
clk_to_dis()
{
dis[0]=second%10;
dis[1]=second/10;
if(flash)dis[2]=10;
else dis[2]=11;
dis[3]=minite%10;
dis[4]=minite/10;
dis[5]=hour%10;
dis[6]=hour/10;
}
/*****定时闹钟显示译码(用于七段码显示)*****/
clarm_to_dis()
{
dis[0]=c_min%10;
dis[1]=c_min/10;
if(flash)dis[2]=10; //亮灯
else dis[2]=11; //灭灯
dis[3]=c_hou%10;
dis[4]=c_hou/10;
dis[5]=10;
dis[6]=13;
}
/***********年月日显示译码************/
nyr_to_dis()
{
dis[0]=day%10;
dis[1]=day/10;
dis[2]=10; //显示 '-'
dis[3]=month%10;
dis[4]=month/10;
dis[5]=10; // '-'
dis[6]=year%10;
dis[7]=year/10;
}
/*主函数*/
void main()
{
P2=0xff;
P1=0XFF;
p3_4=0;
run=1;
led2=0; //运行指示灯亮
led1=1;
flash=0x00;
dis[2]=10; //第三位显示“-”
wei=0x7f; //选通低位
i=0;
second=21;
minite=58;
hour=9;
CNTA=0x00;
year=10;
month=4;
day=5;
clk_to_dis();
TMOD=0x11;
TH0=15560/256;
TL0=15560%256;
TH1=0xfc;
TL1=0x18;
EA=1;
PT0=1;
EX0=1; //开中断;
EX1=1;
ET0=1;
ET1=1;
TR0=1;
TR1=1;
while(1)
{while(run==1)
{ clk_to_dis();
if(calculate)
{
if(month==1|month==3|month==5|month==7|month==8|month==10|mont
h==12)
{day++;
if(day>31){day=0x01;month++;
if(month==13){month=1;year++;cal_year=1;}}
led1=0; //指示灯亮
}
if(month==4|month==6|month==9|month==11)
{
day++;
if(day>30){day=0x01;month++;}
led1=0; //指示灯亮
}
if(month==2) { if(leap_year==1)
{day++;if(day==30)day=1;}
else {day++;if(day==29)day=1;}
}
while(cal_year)
{
if((year+2000)%400==0) leap_year=1; // 被400整除为闰年
else if((year+2000)%100==0) leap_year=0; // 不能
被400整除 能被100整除 不是闰年
else
if((year+2000)%4==0) leap_year=1; // 不能被400、100整除 能被4
整除 是闰年
else leap_year=0;
cal_year=0;
}
calculate=0;led1=1;
}
while(!minitek)
{
for(n=0;n<1000;n++);
if(!minitek==0)break; //延时防抖
minite++;
second=0x00;
led1=0;
for(n=0;n<20;n++)
{
speaker=!speaker;
delay_10us(50); //蜂鸣器响
}
if(minite==60)minite=0x00;
while(!minitek); //等待键松开
led1=1; //显示灯
}
while(!hourk)
{
for(n=0;n<1000;n++);
if(!hourk==0)break;
hour++;
second=0x00;
led1=0;
for(n=0;n<30;n++)
{
speaker=!speaker;
delay_10us(30); //蜂鸣器响
}
if(hour==24) hour=0x00;
while(!hourk);
led1=1;
}
while(!yeark) //yeark键复用 进入年月日调整
{
for(n=0;n<1000;n++);
if(!yeark==0)break;
dis_nyr=1;
while(!yeark);
while(dis_nyr)
{ nyr_to_dis();
while(!yeark)
{
for(n=0;n<1000;n++);
if(!yeark==0)break;
year++;
led1=0;
for(n=0;n<30;n++)
{
speaker=!speaker;
delay_10us(30); //蜂鸣器响
}
if((year+2000)%400==0) leap_year=1; // 被
400整除为闰年
else if((year+2000)%100==0) leap_year=0; // 不能
被400整除 能被100整除 不是闰年
else
if((year+2000)%4==0) leap_year=1; // 不能被400、100整除 能被4
整除 是闰年
else leap_year=0;
while(!yeark);
led1=1;
}
while(!monthk)
{
for(n=0;n<1000;n++);
if(!monthk==0)break;
month++;
if(month==13)month=1;
led1=0;
for(n=0;n<30;n++)
{
speaker=!speaker;
delay_10us(30); //蜂鸣器响
}
while(!monthk);
led1=1;
}
while(!dayk)
{
for(n=0;n<1000;n++);
if(!dayk==0)break;
if(month==1|month==3|month==5|month==7|month==8|month==
10|month==12)
{day++;
if(day>31)day=0x01;
led1=0; //指示灯亮
}
if(month==4|month==6|month==9|month==11)
{
day++;
if(day>30)day=0x01;
led1=0; //指示灯亮
}
if(month==2) { if(leap_year==1)
{day++;if(day==30)day=1;}
else {day++;if(day==29)day=1;}
}
led1=0;
for(n=0;n<30;n++)
{
speaker=!speaker;
delay_10us(30); //蜂鸣器响
}
while(!dayk);
led1=1;
}
while(!hourk)
{ for(n=0;n<1000;n++);
if(hourk) break;
dis_nyr=0;
while(!hourk);
if(clarm_switch)dis[7]=12; //开启显示 C
else dis[7]=11; //关闭 不显示
dis[6]=11;
clk_to_dis();
}
}
}
if(clarm_switch) //闹铃时间到,指示灯闪烁 蜂鸣器长响
{
if(c_min==minite&&c_hou==hour)
{speaker_num=60;
beep=1;
while(beep&& clarm_switch)
{
led1=!led1;
delay_ms(100);
clk_to_dis();
}
led1=1;
beep=0;
}
}
}
while(run==0) //闹钟时间设定
{ clarm_to_dis();
///////////////////////////////////////////////////////////
while(!minitek)
{
for(n=0;n<1000;n++);
if(!minitek==0)break; //延时防抖
c_min++;
led1=0;
for(n=0;n<20;n++)
{
speaker=!speaker;
delay_10us(50); //蜂鸣器响
}
if(c_min==60)c_min=0x00;
while(!minitek); //等待键松开
led1=1; //显示灯
}
while(!hourk)
{
for(n=0;n<1000;n++);
if(!hourk==0)break;
c_hou++;
led1=0;
for(n=0;n<30;n++)
{
speaker=!speaker;
delay_10us(30); //蜂鸣器响
}
if(c_hou==24) c_hou=0x00;
while(!hourk);
led1=1;
}
}
}
}
/***************定时器T0中断*****************/
timer0() interrupt 1 using 2 //定时器
0中断号为1号 使用第2组寄存器
{TR1=0;
TH0=15548/256;
TL0=15548%256;
CNTA++;
if(beep)
{
if(speaker_num%2)speaker=!speaker;
if(!speaker_num) beep=0;
}
if(CNTA==20)
{ if(speaker_num)speaker_num--; //每秒整点报时次数减一
flash=!flash;
CNTA=0;
second++; //秒加
if(second==60)
{second=0;
minite++;
if(minite==60)
{
minite=0;
hour++;
if(hour>7){speaker_num=2*hour; //整点到 设定报时次数 蜂
鸣标志 置1
beep=1;}
if(hour==24)
{
hour=0; calculate=1; //0点到,日期标志加一
}
}
}
}
TR1=1;
}
/*********定时器中断T1**********/
timer1() interrupt 3 using 3
{
TH1=0xfc;
TL1=0x18;
P0=0xff;
led_wei=1;
led_wei=0;
P0=seg[dis[i]];
led_duan=1;
led_duan=0;
P0=wei;
led_wei=1;
led_wei=0;
if(++i==8)i=0;
wei=_cror_(wei,1);
}
/**********************外中断0*******************/
int_0() interrupt 0
{
clarm_switch=!clarm_switch; // 闹钟开关
if(clarm_switch)dis[7]=12; // 开启显示 开启第一位显示C
else dis[7]=11; // 关闭 不显示
for(k=0;k<40;k++)
{speaker=!speaker;
led1=!led1;
delay_ms(5);
}
led1=1;
}
/********************外中断1********************/
int_1() interrupt 2 //闹钟时间设置/运行 转换开关
{
run=!run;
if(run)led2=0;
else led2=1;
for(k=0;k<90;k++)
{speaker=!speaker; // 蜂鸣器响
led1=!led1; // 指示灯闪烁
delay_10us(100);
}
led1=1;
}
版权声明:本文标题:【单片机】c51数字时钟(带年月日显示) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1715096375a434910.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论