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;

}

本文标签: 显示闹钟时间开启