51单片机电子时钟设计及说明.docx
- 文档编号:23649809
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:19
- 大小:19.32KB
51单片机电子时钟设计及说明.docx
《51单片机电子时钟设计及说明.docx》由会员分享,可在线阅读,更多相关《51单片机电子时钟设计及说明.docx(19页珍藏版)》请在冰豆网上搜索。
51单片机电子时钟设计及说明
51单片机电子时钟程序
#include
#include
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitmode=P2^0;//设定修改位数k0
sbitplus=P2^2;//加键k2
sbitdec=P2^3;//减键k3
sbitnz=P2^1;//闹钟设置k1
sbitnzz=P2^4;//闹钟总开关k4
sbitnzf=P2^5;//闹钟分开关k5
sbitfm=P2^6;
uchara=0,b=0;
ucharDateTime[7];
ucharweek,mode_num,mod_num;
uchartab1[]={"D**/**/**"};
uchartab2[]={"T**:
**:
**"};
charcodeweekday[8][4]={"***","MON","TUS","WEN","THU","FRI","SAT","SUN"};
charcodedayofmonth[]={31,28,31,30,31,30,31,31,30,31,30,31};
sbitrs=P1^0;//寄存器选择信号
sbitrw=P1^1;//读写控制信号线
sbiten=P1^2;//使能信号线
charcodeint_to_char[]="0123456789";
voiddelay(uintx)//延时程序
{uinta,b;
for(a=x;a>0;a--)
for(b=10;b>0;b--);
}
voidwrite_com(ucharcom)//写命令
{rs=0;
rw=0;
P0=com;
en=0;
delay(10);
en=1;
delay(10);
en=0;
}
voidwrite_date(uchardate)//写数据
{
rs=1;//写数据时,rs要为高电平
rw=0;
P0=date;//将数据送到P0口准备传送出
en=0;
delay(10);
en=1;
delay(10);
en=0;
}
voidinit_lcd(void)//初始化lcd1602
{
delay(15);
write_com(0x38);//模式设置
delay(20);
write_com(0x0c);//显示无光标
delay(20);
write_com(0x06);//光标移动
delay(20);
write_com(0x01);//清屏
delay(20);
}
voiddisplay_string(char*p)//写字符串
{
while(*p)
{write_date(*p);
delay(20);
p++;}
}
voidgotoxy(ucharx,uchary)//设置移动坐标
{delay(10);
if(x==1)write_com(0x80+y);
elsewrite_com(0xc0+y);
}
voiddisplay_data(charnumber)//显示数据
{
ucharx,y;
x=number/10;//将取得的数据转换成十进制
y=number%10;
write_date(int_to_char[x]);
write_date(int_to_char[y]);
}
sbitDS1302_CLK=P1^6;
sbitDS1302_IO=P1^7;
sbitDS1302_RST=P1^5;
sbitACC0=ACC^0;
sbitACC7=ACC^7;
charhour,minute,second,day;
uintyear;
ucharmonth;
charshour,sminute;
voidDS1302InputByte(uchard)//实时时钟写入一字节(内部函数)
{
uchari;
ACC=d;
for(i=8;i>0;i--)
{
DS1302_IO=ACC0;//将IO线上的数据存放在ACC中
DS1302_CLK=1;//特别注意,DS1302写一数据时,CLK要产生一负脉冲
DS1302_CLK=0;
ACC=ACC>>1;//每次移位一位
}
}
voidWrite1302(unsignedcharucAddr,unsignedcharucDa)//其中Addr为DS1302地址,ucData为要写的数据
{
DS1302_RST=0;//写数据时,要注意RST产生一上升沿,CLK为低电平
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr);//地址,命令
DS1302InputByte(ucDa);//写1字节数据
DS1302_CLK=1;
DS1302_RST=0;
}
voidWriteDS1302(ucharx)//写1302
{uchari;
for(i=0;i<8;i++)
{DS1302_IO=x&0x01;DS1302_CLK=1;DS1302_CLK=0;x>>=1;}
}
ucharReadDS1302()//读1302
{uchari,b=0x00;
for(i=0;i<8;i++)
{b|=_crol_((uchar)DS1302_IO,i);
DS1302_CLK=1;
DS1302_CLK=0;
}returnb/16*10+b%16;
}
ucharRead_Data(ucharaddr)
{
uchardat;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
WriteDS1302(addr);
dat=ReadDS1302();
DS1302_CLK=1;
DS1302_RST=0;
returndat;
}
ucharmonthday(ucharyear,ucharmonth)
{
if(month==2&&year%4==0)return(29);//用以判定是否为润年,其2月有29天
elsereturn(dayofmonth[month-1]);//非闰年时的该月份天数减1
}
voidGetTime()
{
uchari,addr=0x81;
for(i=0;i<7;i++)
{DateTime[i]=Read_Data(addr);
addr+=2;
}
}
voiddisplay_week(ucharw)
{
display_string(&weekday[w][0]);
}
voidkeyscan()//按键校时程序
{if(a==0)
{if(mode==0)//"修改位"的选择
{delay(5);//延时
if(mode==0)//当外部按键mode每按下一次时,都使mode_num自加,即mode_num表示为按键mode按下的次数
{mode_num++;
while(!
mode);
write_com(0x0f);
}
if(mode_num==1){gotoxy(1,3);b=1;}
if(mode_num==2)gotoxy(1,6);
if(mode_num==3)gotoxy(1,9);
if(mode_num==4)gotoxy(1,13);
if(mode_num==5)gotoxy(2,3);
if(mode_num==6)gotoxy(2,6);
if(mode_num==7)gotoxy(2,9);
if(mode_num==8)
{mode_num=0;b=0;//非修改模式时,将mode_num置零,有助于判断是否为修改模式
write_com(0x0c);
}
}
if(mode_num!
=0)//为修改模式时,加减键的处理子程序
{
if(plus==0)//当加键为零,即外部触发一次时,进行以下处理
{
delay(5);//延时
if(plus==0)//延时再次判断加键,防止抖动
{
while(!
plus);
if(mode_num==1)//当为年份改变时,年份自加1,并且显示修改后的日期
{
year++;
Write1302(0x8c,year/10*16+year%10);//因为年份主要是最后两位在改变,所以除以100来计算年份值,除以100求得的商值为十位
gotoxy(1,2);display_data(year);write_com(0x0f);gotoxy(1,3);
}
if(mode_num==2)
{
month++;
if(month==13)month=1;//特别注意,月份不能超过12,当为13时,要将月份置1
Write1302(0x88,month/10*16+month%10);
gotoxy(1,5);display_data(month);write_com(0x0f);gotoxy(1,6);
}
if(mode_num==3)
{
day++;
if(day>monthday(year,month))
day=1;
Write1302(0x86,day/10*16+day%10);
gotoxy(1,8);display_data(day);write_com(0x0f);gotoxy(1,9);
}
if(mode_num==4)
{
week++;
if(week==8)
week=1;week=week+1;Write1302(0x8a,week/10*16+week%10);week=week-1;
gotoxy(1,11);display_week(week);write_com(0x0f);gotoxy(1,13);
}
if(mode_num==5)
{
hour++;
if(hour==24)hour=0;//小时不能超过24
Write1302(0x84,hour/10*16+hour%10);
gotoxy(2,2);display_data(hour);write_com(0x0f);gotoxy(2,3);
}
if(mode_num==6)
{
minute++;
if(minute==60)minute=0;
Write1302(0x82,minute/10*16+minute%10);
gotoxy(2,5);display_data(minute);write_com(0x0f);gotoxy(2,6);
}
if(mode_num==7)
{
second++;
if(second==60)second=0;
Write1302(0x80,second/10*16+second%10);
gotoxy(2,8);display_data(second);write_com(0x0f);gotoxy(2,9);
}
}
}
if(dec==0)
{
delay(5);
if(dec==0)
{
while(!
dec);
if(mode_num==1)
{
year--;
Write1302(0x8c,year/10*16+year%10);
gotoxy(1,2);display_data(year);write_com(0x0f);gotoxy(1,3);
}
if(mode_num==2)
{
month--;
if(month==0)month=12;
Write1302(0x88,month/10*16+month%10);
gotoxy(1,5);display_data(month);write_com(0x0f);gotoxy(1,6);
}
if(mode_num==3)
{day--;
if(day==0)
day=monthday(year,month);
Write1302(0x86,day/10*16+day%10);
gotoxy(1,8);display_data(day);write_com(0x0f);gotoxy(1,9);
}
if(mode_num==4)
{
week--;
if(week==0)week=7;
week=week+1;
Write1302(0x8a,week/10*16+week%10);
week=week-1;
gotoxy(1,11);display_week(week);write_com(0x0f);gotoxy(1,13);
}
if(mode_num==5)
{
hour--;
if(hour<0)hour=23;
Write1302(0x84,hour/10*16+hour%10);
gotoxy(2,2);display_data(hour);write_com(0x0f);gotoxy(2,3);
}
if(mode_num==6)
{
minute--;
if(minute<0)minute=59;
Write1302(0x82,minute/10*16+minute%10);
gotoxy(2,5);display_data(minute);write_com(0x0f);gotoxy(2,6);
}
if(mode_num==7)
{
second--;
if(second<0)second=59;
Write1302(0x80,second/10*16+second%10);
gotoxy(2,8);display_data(second);write_com(0x0f);gotoxy(2,9);
}
}
}
}
}}
voidnaozhong()//按键校时程序
{if(b==0)
{if(nz==0)//"修改位"的选择
{
delay(5);//延时
if(nz==0)//当外部按键mode每按下一次时,都使mode_num自加,即mode_num表示为按键mode按下的次数
{
mod_num++;
while(!
nz);
write_com(0x0f);
}
if(mod_num==1){gotoxy(2,12);a=1;}
if(mod_num==2)gotoxy(2,15);
if(mod_num==3)
{mod_num=0;a=0;//非修改模式时,将mode_num置零,有助于判断是否为修改模式
write_com(0x0c);
}
}
if(mod_num!
=0)
{if(plus==0)
{delay(5);
if(plus==0)
{
while(!
plus);
if(mod_num==1)
{
shour++;
if(shour==24)shour=0;
gotoxy(2,11);display_data(shour);write_com(0x0f);gotoxy(2,12);}
if(mod_num==2)
{
sminute++;
if(sminute==60)sminute=0;
gotoxy(2,14);display_data(sminute);write_com(0x0f);gotoxy(2,15);
}
}
}
if(dec==0)
{
delay(5);
if(dec==0)
{
while(!
dec);
if(mod_num==1)
{
shour--;
if(shour<0)shour=23;
gotoxy(2,11);display_data(shour);write_com(0x0f);gotoxy(2,12);
}
if(mod_num==2)
{
sminute--;
if(sminute<0)sminute=59;
gotoxy(2,14);display_data(sminute);write_com(0x0f);gotoxy(2,15);
}
}
}
}
}}
voidfmq(void)
{
if(minute==0)
{if(second==0|second==2|second==4|second==6|second==8)
fm=~fm;}
}
ucharn=0,d=0;
voidnzsz(void)
{if(nzf==0)
{delay(5);
if(nzf==0)
while(nzf==0);
n++;if(n==2)
n=0;
}
if(n==0)
{if(shour==hour)
{if(sminute==minute)
{if(second<30)
{fm=~fm;d=1;
}
}
if(d==1)
{if(sminute+1==minute|sminute+2==minute)
{if(second<30)
fm=~fm;
}
}}
}
if(n==1)
{if(second>30)
{n=0;d=0;}
}
}
ucharm=0;
voidnzzkg(void)
{
if(nzz==0)
{delay(5);
if(nzz==0)
m++;
if(m==2)
m=0;
while(nzz==0);
}
if(m==0&week<=5)nzsz();
}
voidFormat_DateTime(uchard,uchar*a)//显示格式
{
a[0]=d/10+'0';
a[1]=d%10+'0';
}
voidxs(void)
{
ucharq;
write_com(0xc0);
write_com(0x80);
for(q=0;q<16;q++)
{
write_date(tab1[q]);
delay
(1);
}
write_com(0xc0);
for(q=0;q<16;q++)
{
write_date(tab2[q]);
delay
(1);
}
GetTime();
Format_DateTime(DateTime[6],tab1+2);//年
Format_DateTime(DateTime[4],tab1+5);//月
Format_DateTime(DateTime[3],tab1+8);//日
strcpy(tab1+11,weekday[DateTime[5]-1]);
Format_DateTime(DateTime[2],tab2+2);//时
Format_DateTime(DateTime[1],tab2+5);//分
Format_DateTime(DateTime[0],tab2+8);//秒
}
voidmain()
{
init_lcd();//初始化lcd
while
(1)
{fmq();
keyscan();
naozhong();
nzzkg();
if(mode_num==0)
if(mod_num==0)
{xs();
year=DateTime[6];month=DateTime[4];day=DateTime[3];
week=DateTime[5]-1;
hour=DateTime[2];minute=DateTime[1];second=DateTime[0];
}
}
}
电子时钟的功能介绍
1、基本功能显示时间:
年、月、日、时、分、秒、星期。
2、基本校时功能:
a、按下K0进入时间校时,每按一次光标向后移动一位,到秒时退出校时功能。
在进行校时时,不可对闹钟进行调整;
b、进入校时,按下K2对每位进行加一,按下K3对每位进行减一;
3、报时:
整点报时,10秒过后自动关闭报时。
4、闹钟:
a、到设定的时间,闹钟报时,30自动关闭,若不关5分钟后再次报时,还是30秒后关闭,在过5分钟后,再次报时;
b、按下K1进入闹钟调时,每按一次光标向后移动一位,到设置分时再按一次K1,退出闹钟调时。
在进行闹钟调时时,不可对时间进行设置;
c、K4为闹钟总开关,初始闹钟打开,只有在工作日闹钟工作,关闭总开关,闹钟一直不工作,只有再次打开才可工作;
c、K5为闹钟分开关,只能关闭当日的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 51 单片机 电子 时钟 设计 说明