基于51单片机的数字电子钟C程序设计.doc
基于51单片机的数字电子钟C程序设计&仿真图/*lns主程序snl*/#include <absacc.h> /包含头文件#include <reg52.h> /包含头文件/*数据类型定义*/#define uchar unsigned char /数据类型定义/*定义变量并初始化*/uchar n=31; /定义月份天数变量并初始化uchar ms=0; /定义毫秒变量并初始化uchar h1=0,m1=0,s1=0; /定义计时时、分、秒变量并初始化uchar h2=0,m2=1,s2=1; /定义定时时、分、秒变量并初始化 uchar year=7,month=9,day=8; /定义年、月、日变量并初始化uchar wday=6; /定义星期变量并初始化uchar *h=&h1,*m=&m1,*s=&s1; /定义显视位变量并初始化uchar *p; /定义调节指针uchar k1=0,k2=0,k3=0,k4=0,k5=0; /定义控制变量并初始化uchar counter=0; /定义铃声节拍变量并初始化uchar count=0; /定义铃声音符变量并初始化sbit sound=P10; /定义铃声输出位uchar a8=1,2,3,4,5,6,7; /定义显视输出位数组并初始化uchar code tt12= 0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7d,0x07,0x7f,0x6f,0x40,0x00 ; /数码管显视代码uchar code array= 0x18, 0x30, 0x1C, 0x10, 0x20, 0x40, 0x1C, 0x10, 0x18, 0x10, 0x20, 0x10, 0x1C, 0x10, 0x18, 0x40, 0x1C, 0x20, 0x20, 0x20, 0x1C, 0x20, 0x18, 0x20, 0x20, 0x80, 0xFF, 0x00, 0x20, 0x30, 0x1C, 0x10, 0x18, 0x20, 0x15, 0x20, 0x1C, 0x20, 0x20, 0x20, 0x26, 0x40, 0x20, 0x20, 0x2B, 0x20, 0x26, 0x20, 0x20, 0x20, 0x30, 0x80, 0xFF, 0x00, 0x20, 0x20, 0x1C, 0x10, 0x18, 0x10, 0x20, 0x20, 0x26, 0x20, 0x2B, 0x20, 0x30, 0x20, 0x2B, 0x40, 0x20, 0x20, 0x1C, 0x10, 0x18, 0x10, 0x20, 0x20, 0x26, 0x20, 0x2B, 0x20, 0x30, 0x20, 0x2B, 0x40, 0x20, 0x30, 0x1C, 0x10, 0x18, 0x20, 0x15, 0x20, 0x1C, 0x20, 0x20, 0x20, 0x26, 0x40, 0x20, 0x20, 0x2B, 0x20, 0x26, 0x20, 0x20, 0x20, 0x30, 0x80, 0x20, 0x30, 0x1C, 0x10, 0x20, 0x10, 0x1C, 0x10, 0x20, 0x20, 0x26, 0x20, 0x2B, 0x20, 0x30, 0x20, 0x2B, 0x40, 0x20, 0x15, 0x1F, 0x05, 0x20, 0x10, 0x1C, 0x10, 0x20, 0x20, 0x26, 0x20, 0x2B, 0x20, 0x30, 0x20, 0x2B, 0x40, 0x20, 0x30, 0x1C, 0x10, 0x18, 0x20, 0x15, 0x20, 0x1C, 0x20, 0x20, 0x20, 0x26, 0x40, 0x20, 0x20, 0x2B, 0x20, 0x26, 0x20, 0x20, 0x20, 0x30, 0x30, 0x20, 0x30, 0x1C, 0x10, 0x18, 0x40, 0x1C, 0x20, 0x20, 0x20, 0x26, 0x40, 0x13, 0x60, 0x18, 0x20, 0x15, 0x40, 0x13, 0x40, 0x18, 0x80, 0x00, 0x00 ; /arrayi=0x00 代表歌曲演唱完毕 /arrayi=0xff 代表是休止符/* 函数名称:leap()* 功 能:计算二月份天数* 入口参数:year* 出口参数:无*/ uchar leap(uchar year) /判断是否闰年并返回二月份的天数 /闰年返回29,平年返回28 year+=2000; if(year%4=0) if(year%100=0) if(year%400=0) return 29; else return 28; else return 29; else return 28; /* 函数名称:mon()* 功 能:计算并返回每个月的天数* 入口参数:month* 出口参数:无*/ uchar mon(uchar month) /计算并返回每个月的天数 switch(month) case 1: case 3: case 5: case 7: case 8: case 10: case 12:return 31;break; /1,3,5,7,8,10,12月每月31天 case 4: case 6: case 9: case 11:return 30;break; /4,6,9,11月每月30天 case 2: return leap(year);break;/返回二月份的天数 default:break; /* 函数名称:music()* 功 能:音乐节拍控制* 入口参数:无* 出口参数:无*/ void music(void) /铃声音乐 counter+; /节拍次数计数 if(counter>=arraycount+1) /节拍次数判断 count+=2; /音符变换 counter=0; /清0节拍数 if(count>=192) /判断是否唱完一曲 count=0; /返回第一个音符 /* 函数名称:timer1()* 功 能:音乐频率设置* 入口参数:无* 出口参数:无*/ void timer1(void)interrupt 1 using 1 /音调设置 sound=sound; /铃声输出 TH0=(0xffff-30*arraycount)>>8; /音频设置 TL0=(0xffff-30*arraycount)&0xff; /* 函数名称:timer3()* 功 能:中断计时* 入口参数:无* 出口参数:无*/ void timer3(void) interrupt 3 using 3 /计时中断 TH1=0xd8; /计数器初值重载 TL1=0xef; /定义单位节拍的延时大小为10ms if(k5)music(); /调用闹铃音乐lns else TR0=0; /达到所设闹铃时间长度关铃声 if(+ms=100) /计时一秒钟 ms=0; if(+s1=60) /计时一分钟 s1=0; if(+m1=60) /计时一小时 m1=0; if(+h1=24) /计时一天 h1=0; n=mon(month); /取每月的天数 if(+day>n) /计时一个月 day=1; if(+month>12) /计时一年 month=1; year+; if(+wday>6) /星期计数 wday=0; k5-; /闹铃时间长度倒记时 if(h1=h2&&m1=m2) /判断是否到定时时刻 TR0=1; /开铃声中断lns k5=s2; /设置闹铃时间长度 /* 函数名称:d3()* 功 能:数码管输出显示* 入口参数:无* 出口参数:无*/ void d3(void) /显示输出uchar sel=0x80,i ; /定义sel为位选通变量并初使化if(k2) /判断是否处于调时状态 if(k2=4)a0=a1=a4=a6=a7=10; /星期显示设置 if(k1&&(k3-=0) k3=255; /设置位调节闪烁初值 for(i=0;i<=8;i+) /循环显示八个数码管 P2=0xff; /清屏 P0=ttai; /输出显示数值 if(k1&&(k3>200) /判断是否闪烁 if (k1=1&&(i=6|i=7)P2=0xff; /时位闪烁 else if(k1=2&&(i=3|i=4)P2=0xff; /分位闪烁 else if(k1=3&&(i=0|i=1)P2=0xff; /秒位闪烁 else P2=sel; /非闪烁状态 else P2=sel; /非闪烁状态 sel=sel>>1; /显示位移位 /* 函数名称:d2()* 功 能:循环调用* 入口参数:无* 出口参数:无*/ void d2(void) while(1) a0=*s%10; /给显示数组赋值 a1=*s/10; a2=10; a3=*m%10; a4=*m/10; a5=10; a6=*h%10; a7=*h/10; d3(); /调用显示输出函数 /* 函数名称:d1()* 功 能:中断设置* 入口参数:无* 出口参数:无*/ void d1(void) TMOD=0x11; TH1=0xff; TH0=0xff; TL1=0xff; TL0=0xff; IE=0x8f; TR1=1; IT0=1; IT1=1; IP=0x02;/* 函数名称:main()* 功 能:程序入口,调用功能子函数* 入口参数:无* 出口参数:无*/ void main(void) d1(); /调用中断位设置函数 d2(); /* 函数名称:d5()* 功 能:切换显示菜单* 入口参数:无* 出口参数:无*/void d5(void) /显示菜单调节函数 switch(k2) case 1:h=&h1; m=&m1; s=&s1; break; /菜单1:显示时钟时间 case 2:h=&h2; m=&m2; s=&s2; break; /菜单2:显示定时时刻 case 3:h=&year;m=&month;s=&day; break; /菜单3:显示日历年月日 case 4:h=&wday;m=&wday; s=&wday;break; /菜单4:显示星期0-6 default:k2=0;h=&h1;m=&m1;s=&s1; break; /复位显示 /* 函数名称:d7()* 功 能:调节限制,防止数值调节超出值域* 入口参数:无* 出口参数:无*/ void d7(void) /调节限制函数 if(k2=1|k2=2) /计时与定时限制 if (k1=1&&*p>=24) *p=0; /小时限制 else if(*p>=60) *p=0; /分、秒限制 if(k2=3) /日历限制 if (k1=1&&*p>=100)*p=0; /年限制 else if(k1=2&&*p>12) *p=1; /月限制 else if(k1=3&&*p>n) *p=1; /日限制 if(k2=4) if (k1=2&&*p>6) *p=0; /星期限制 /* 函数名称:timer0()* 功 能:菜单切换及位加数调节* 入口参数:无* 出口参数:无*/ /*外部中断1调节函数*/ void timer0(void)interrupt 0 using 0 /外部中断0调节 if(k1) /判断是位调节还是菜单调节 (*p)+; /位加数调节 d7(); /调用调节限制函数 else k2+; /菜单加数调节 d5(); /调用调节菜单 /* 函数名称:timer2()* 功 能:调节位选择及关铃声* 入口参数:无* 出口参数:无*/ void timer2(void)interrupt 2 using 2 /外部中断1调节 TR0=0;k5=0; /手动关铃声 if(k2) /断是否处于调节状态 if (k2=4)k1+; /期调节位选择 if (+k1=1) p=h; /选择时位 else if(k1=2) p=m; /选择分位 else if(k1=3) p=s; /选择秒位 else k1=0; /复位 /*lns主程序snl*/