电子时钟源代码及注释
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include "reg52.h"
#define TIMER0_COUNT 0xEC78 /*10000h-(12,000,000/(12*200))*/
#define uchar unsigned char
#define uint unsigned int
uchar led_mod[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳数码管0~9
uchar led_ctl[]={0xfe,0xfd,0xfb,0xf7}; //位选码
uchar buffer[]={0,0,0,0}; //码管数值
char i=0;
sbit mode=P1^4; //选择模式 引脚
sbit add=P1^5; //加
sbit dec=P1^6; //减
sbit alarm=P3^2; //闹钟
sbit sec_led=P1^1; //秒驱动LED闪烁
sbit alarm_warn=P1^0;//闹钟提醒引脚
int time=0;
char status=0; //模式值
sbit sTime=P1^2; //设置时间提示
sbit sClock=P3^3; //设置闹钟提示
uint hour=19,min=5,sec=0; //初始时分秒
uint alarmhour=19,alarmmin=0,flag=1; //初始闹钟时分
bit ringoff=1;//闹铃停止
unsigned char msecond=0; //毫秒计数变量
unsigned char second2; //秒计数变量
uchar code freqh[]={0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC, //低音1~7 第一个八度
0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,//中音 1~7 第二个八度
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF};//高音 1~7 第三个八度
uchar code freql[]={0x21,0xE1,0x8C,0xD8,0x68,0xE9,0x5B, //低音1234567
0x8F,0xEE,0x44,0x6B,0xB4,0xF4,0x2D, //中音 1234567
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16}; //高音 1234567
uchar code song[]={5,3,2,3,3,1,4,3,1,5,3,2,3,3,1,4,3,1,5,3,1,5,2,1,6,2,1,7,2,1,1,3,1,2,3,1,3,3,1,4,3,1,3,3,2,1,3,1,2,3,1,3,3,2,
3,2,1,4,2,1,5,2,1,6,2,1,5,2,1,4,2,1,5,2,1,3,2,1,4,2,1,5,2,1,4,2,2,6,2,1,5,2,1,4,2,2,3,2,1,2,2,1,3,2,1,2,2,1,1,2,1,2,2,1,
3,2,1,4,2,1,5,2,1,6,2,1,4,2,2,6,2,1,5,2,1,6,2,2,7,2,1,1,3,1,5,2,1,6,2,1,7,2,1,1,3,1,2,3,1,3,3,1,4,3,1,5,3,1,3,3,2,1,3,1,2,3,1,
3,3,2,2,3,1,1,3,1,2,3,1,7,2,1,1,3,1,2,3,1,3,3,1,2,3,1,1,3,1,7,2,1,1,3,2,6,2,1,7,2,1,1,3,2,1,2,1,2,2,1,
3,2,1,4,2,1,3,2,1,2,2,1,3,2,1,1,3,1,7,2,1,1,3,1,6,2,2,1,3,2,7,2,1,6,2,2,5,2,1,4,2,1,5,2,1,4,2,1,3,2,1,4,2,1,5,2,1,6,2,1,7,2,1,1,2,1,
6,2,2,1,3,1,7,2,1,1,3,2,7,2,1,6,2,1,7,2,1,1,3,1,2,3,1,1,3,1,7,2,1,1,3,1,6,2,1,7,2,1,0,0,0}; //卡农
//一个音符有三个数字。前为音节、中为第几个八度、后为时长(以半拍为单位)。
uchar timer1h,timer1l,time1; //time1为节拍(延迟时间),timer1l、timer1h为计数器1初值
void delay(unsigned int time){
unsigned int j=0;
for(;time>0;time--)
for(j=0;j<125;j++);
}
/******************正常走时时数码管显示程序*************/
void display()
{
if(status==3||status==4) //闹铃时间
{
buffer[0]=alarmhour/10;
buffer[1]=alarmhour%10;
buffer[2]=alarmmin/10;
buffer[3]=alarmmin%10;
}
else if(status==1||status==2||status==0) //正常时间
{
buffer[0]=hour/10;
buffer[1]=hour%10;
buffer[2]=min/10;
buffer[3]=min%10;
}
}
void delay2(void) //延时函数
{
unsigned char j;
for(j=0;j<180;j++);
}
/********函数功能:显示秒表秒数的子程
序 *******************/
void DisplaySecond2(unsigned char m) //毫秒表的显示
{
P2=led_ctl[0];
P0=led_mod[m/10]; //显示十位
delay2();
delay2();
P2=led_ctl[1];
P0=led_mod[m%10]&0x7f;//led_mod[] led_ctl[] 显示个位
delay2();
delay2();
P2=0xff; //关闭所有数码管
P0=0xff;
delay2();
delay2();
}
/*******************函数功能:显示秒表毫秒的子程序*********/
void DisplayMsecond(unsigned char s)
{
P2=led_ctl[2];
P0= led_mod[s/10];//显示十位 led_mod[] led_ctl[]
delay2();
delay2();
delay2();
P2=led_ctl[3];
P0=led_mod[s%10];//显示个位
delay2();
delay2();
delay2();
P2=0xff; //关闭所有数码管
P0=0xff;
delay2();
delay2();
delay2();
}
void press()
{
if(mode==0) //模式按钮被按下
{
status++;
if(status>5)
{
status=0;
}
if(status!=5)
{
second2=0;
msecond=0;
TR2=0;
}
display(); //显示
while(mode==0);
}
if(add==0) //加按钮被按下
{
switch(status) //判断模式
{
case 1:if(hour<23) hour++; else hour=0; display();break;//模式1小时+1,到24变成0
case 2:if(min<59) min++; else min=0; display();break; //模式2分钟+1
case 3:if(alarmhour<23) alarmhour++; else alarmhour=0; display();break;//模式3闹铃小时+1
case 4:if(alarmmin<59) alarmmin++; else alarmmin=0; display();break;//模式4闹铃分钟+1
case 5: TR2=1; break;
default:break;
}
while(add==0);
}
if(dec==0) //减按钮被按下
{
switch(status)
{
case 1:if(hour>0) hour--; else hour=23; display();break;
case 2:if(min>0) min--; else min=59; display();break;
case 3:if(alarmhour>0) alarmhour--; else alarmhour=23; display();break;
case 4:if(alarmmin>0) alarmmin--; else alarmmin=59; display();break;
case 5:TR2=0; break;
default:break;
}
while(dec==0);
}
if(alarm==0) //闹铃按钮被按下
{
if(status==5) {//秒表清零
second2=0;
msecond=0;
TR2=0;
}
else
ringoff=~ringoff; //开始/停止闹铃
while(alarm==0);
}
}
/********** 定时器 0 方式 1 中断处理程序**********/
void t0() interrupt 1
{
TL0=(TIMER0_COUNT & 0x00FF);
TH0=(TIMER0_COUNT >> 8);
time++;
if(time==200) //计时1秒时
{
time=0;
sec_led=~sec_led;
sec++;
if(sec==60) //计时1分钟
{
sec=0;
min++;
display();
if(min==60) //计时1小时
{
min=0;
hour++;
if(hour==24)
{
hour=0;
}
display();
}
}
}
if(status==1 || status==3) //调整时分闪动
{
if(time<100)
{
P2=led_ctl[i]|0x03; //位选控制
P0=led_mod[buffer[i]]; //码管显示
}
else
{
P2=led_ctl[i]; //位选控制
P0=led_mod[buffer[i]]; //码管显示
}
}
else if(status==2 || status==4){ //调整时间或闹钟时 分钟部分闪动
if(time<100)
{
P2=l
ed_ctl[i]|0x0c; //位选控制
P0=led_mod[buffer[i]]; //码管显示
}
else
{
P2=led_ctl[i]; //位选控制
P0=led_mod[buffer[i]]; //码管显示
}
}
else if(status==5);
else
{
P2=led_ctl[i]; //位选控制
P0=led_mod[buffer[i]]; //码管显示
}
i++; //i为全局变量 动态刷新显示
i=i%4;
}
/**********定时器T1中断。用来产生不同频率方波********/
void t1() interrupt 3
{
TR1=0; //先关中断
alarm_warn=~alarm_warn; //产生方波
TH1=timer1h;
TL1=timer1l; //重新装入初值
TR1=1; //在开始计数
}
/*********************延迟半节拍数*******************/
void delay1(uchar t)
{
uchar t1;
unsigned long t2;
for(t1=0;t1<13*t;t1++)
{
display(); //防止响音乐时数码管无显示
press();
for(t2=0;t2<220;t2++) ;
}
TR1=0; //一个音符发送完后关计数
}
/********************产生音乐程序***************/
void send()
{
TH1=timer1h;
TL1=timer1l;
TR1=1;
delay1(time1); //根据节拍数调用延迟
}
void main()
{
uint j,k;
TMOD=0x11; //定时器0方式1
TL0=(TIMER0_COUNT & 0x00FF);
TH0=(TIMER0_COUNT >> 8);
ET0=1;
TR0=1;
ET1=1;
EA=1;
/*********定时器2************/
RCAP2L=(TIMER0_COUNT & 0x00FF);;
RCAP2H=(TIMER0_COUNT >> 8);
ET2=1;
display(); //处理显示值
while(1)
{
press(); //检测按钮
if(status==1 || status==2) //显示设置时间提示灯
{
sTime=0;
}
else
sTime=1;
if(status==3 || status==4) //显示设置闹钟提示灯
{
sClock=0;
}
else
sClock=1;
if(status==5) //秒表计时,设置秒表提示灯
{
sTime=0;
sClock=0;
DisplaySecond2(second2); //调用秒显示子程序
delay2();
DisplayMsecond(msecond); //调用毫秒显示子程序
delay2();
}
else
{
sTime=1;
sClock=1;
}
if(hour==alarmhour && min==alarmmin&&ringoff)//闹铃时间到
{
j=0;
time1=1;
while(ringoff)
{
k=song[j]+7*song[j+1]-8;//找到相应音符的计数初值
timer1h=freqh[k];
timer1l=freql[k]; //装入计数初值
time1=song[j+2];
j=j+3;
if(time1!=0) send(); //播放音符
else j=0; //循环播放
}
}
else
alarm_warn=1;
}
}
void Timer2_Server(void) interrupt 5 using 3
{
static unsigned int Timer2_Server_Count;// 定义静态变量,用来计数T2 定时器的溢出次数(进入本函数的次数)
TF2=0; // T2 定时器发生溢出中断时,需要用户自己清除溢出标记,而51的其他定时器是自动清除
Timer2_Server_Count++;
if(Timer2_Server_Count==2)
{
Timer2_Server_Count=0; //中断计数变量清0
msecond++; //毫秒计数变量加1
}
if(msecond==100)
{
msecond=0; //如果毫秒满100,将毫秒计数
变量清0
second2++; //秒计数变量加1
}
if(second2==100)
second2=0;
}