下面是电子钟的主要程序:
void fz(void)
{ int i;
if(alarm_on==1)
{
if(strncmp(CurrentTime.TimeString,stralarm,7)==0)
{
for(i=0;i<20;i++)
{ bz( 100,1,1);
mdelay(200);
bz(100,1,1);
mdelay(200);
mdelay(1000);
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
GotoXY(0, 0);
Print("..Alarm.........");
GotoXY(0, 1);
Print(stralarm);
stopwatch_flag=1;
if(out==0)
{ while(out==0);
alarm_on=0;
break;
}
gettime();
}
}
}
if((CurrentTime.TimeString[6]=='5')&&(CurrentTime.TimeString[7]=='9'))
alarm_on=alarm_flag_sto[0];
}
void disp_strstowatch(void)
{ LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
GotoXY(0, 0);
Print("---Stopwatch----");
GotoXY(1, 1);
Print(stop_watch_value);
stopwatch_flag=1;
Delay1ms(200);
}
void outkey() //跳出调整模式,返回默认显示
{ uchar Second;
if(out==0)
{ mdelay(8);
count=0;
hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;
Second=Read1302(DS1302_SECOND);
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止写入
done=0;
while(out==0);
settime_flag=0;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Upkey()//升序按键
{
Up=1;
if(Up==0)
{
mdelay(8);
switch(count)
{case 1:
temp=Read1302(DS1302_SECOND); //读取秒数
temp=temp+1; //秒数加1
up_flag=1; //数据调整后更新标志
if((temp&0x7f)>0x59) //超过59秒,清零
temp=0;
break;
case 2:
temp=Read1302(DS1302_MINUTE); //读取分数
temp=temp+1; //分数加1
up_flag=1;
if(temp>0x59) //超过59分,清零
temp=0;
break;
case 3:
temp=Read1302(DS1302_HOUR); //读取小时数
temp=temp+1; //小时数加1
up_flag=1;
if(temp>0x23) //超过23小时,清零
temp=0;
break;
case 4:
temp=Read1302(DS1302_WEEK); //读取星期数
temp=temp+1; //星期数加1
up_flag=1;
if(temp>0x7)
temp=1;
break;
case 5:
temp=Read1302(DS1302_DAY); //读取日数
temp=temp+1; //日数加1
up_flag=1;
if(temp>0x31)
temp=1;
break;
case 6:
temp=Read1302(DS1302_MONTH); //读取月数
temp=temp+1; //月数加1
up_flag=1;
if(temp>0x12)
temp=1;
break;
case 7:
temp=Read1302(DS1302_YEAR); //读取年数
temp=temp+1; //年数加1
up_flag=1;
if(temp>0x85)
temp=0;
break;
default:break;
}
while(Up==0);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Downkey()//降序按键
{
Down=1;
if(Down==0)
{
mdelay(8);
switch(count)
{case 1:
temp=Read1302(DS1302_SECOND); //读取秒数
temp=temp-1; //秒数减1
down_flag=1; //数据调整后更新标志
if(temp==0x7f) //小于0秒,返回59秒
temp=0x59;
break;
case 2:
temp=Read1302(DS1302_MINUTE); //读取分数
temp=temp-1; //分数减1
down_flag=1;
if(temp==-1)
temp=0x59; //小于0秒,返回59秒
break;
case 3:
temp=Read1302(DS1302_HOUR); //读取小时数
temp=temp-1; //小时数减1
down_flag=1;
if(temp==-1)
temp=0x23;
break;
case 4:
temp=Read1302(DS1302_WEEK); //读取星期数
temp=temp-1; //星期数减1
down_flag=1;
if(temp==0)
temp=0x7;;
break;
case 5:
temp=Read1302(DS1302_DAY); //读取日数
temp=temp-1; //日数减1
down_flag=1;
if(temp==0)
temp=31;
break;
case 6:
temp=Read1302(DS1302_MONTH); //读取月数
temp=temp-1; //月数减1
down_flag=1;
if(temp==0)
temp=12;
break;
case 7:
temp=Read1302(DS1302_YEAR); //读取年数
temp=temp-1; //年数减1
down_flag=1;
if(temp==-1)
temp=0x85;
break;
default:break;
}
while(Down==0);
}
}
void Setkey()//模式选择按键
{
Set=1;
out=1;
stop_watch=1;
if(Set==0)
{
mdelay(2);
count=count+1; //Setkey按一次,count就加1
done=1; //进入调整模式
while(Set==0);
}
if(stop_watch==0)
{
mdelay(8);
done=1;
stopwatch_flag=1;
while(stop_watch==0);
while(stopwatch_flag){
if(Set==0)
{ while(Set==0);
TR0=1;
}
if(Up==0){
while(Up==0);
TR0=0;}
if(Down==0)
{ while(Down==0);
minite=0;
second=0;
count_stop=0;
trasfer();
}
if(out==0)
{ while(out==0);
stopwatch_flag=0;
done=0;
goto kip;
}
trasfer();
disp_strstowatch();
}
}
kip: LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
}
void alarm(void)
{ uchar alarm_tmph,alarm_tmpm,alarm_tmps;
while(1){
if(Set==0)
{ while(Set==0);
alarm_tmph++;
if(alarm_tmph>=24)
alarm_tmph=0;
stralarm[0]=alarm_tmph/10+0x30;
stralarm[1]=alarm_tmph%10+0x30;
}
if(Up==0){
while(Up==0);
alarm_tmpm++;
if(alarm_tmpm>=60)
alarm_tmpm=0;
stralarm[3]=alarm_tmpm/10+0x30;
stralarm[4]=alarm_tmpm%10+0x30;
}
if(Down==0)
{ while(Down==0);
alarm_tmps++;
if(alarm_tmps>=60)
alarm_tmps=0;
stralarm[6]=alarm_tmps/10+0x30;
stralarm[7]=alarm_tmps%10+0x30;
}
if(out==0)
{ while(out==0);
stopwatch_flag=0;
done=0;
stop_watch=1;
goto kip2;
}
disp_alarm();
}
kip2: LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
stralarm[2]=':';
stralarm[5]=':';
Write1302(0x8e,0x00); //写入允许
WriteRAM(0,stralarm,9);
Write1302(0x8e,0x80); //禁止写入 */
}
void keydone()//按键功能执行
{ uchar Second;
if(flag==0) //关闭时钟,停止计时
{ Write1302(0x8e,0x00); //写入允许
temp=Read1302(0x80);
Write1302(0x80,temp|0x80);
Write1302(0x8e,0x80); //禁止写入
flag=1;
}
Setkey(); //扫描模式切换按键
switch(count)
{case 1:do //count=1,调整秒
{
outkey(); //扫描跳出按钮
Upkey(); //扫描加按钮
Downkey(); //扫描减按钮
if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,temp|0x80); //写入新的秒数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_sec++; //位闪计数
if(hide_sec>3)
hide_sec=0;
show_time(); //液晶显示数据
}while(count==2);
break;
case 2:do //count=2,调整分
{
hide_sec=0;
outkey();
Upkey();
Downkey();
if(temp>0x60)
temp=0;
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x82,temp); //写入新的分数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_min++;
if(hide_min>3)
hide_min=0;
show_time();
}while(count==3);break;
case 3:do //count=3,调整小时
{
hide_min=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x84,temp); //写入新的小时数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_hour++;
if(hide_hour>3)
hide_hour=0;
show_time();
}while(count==4);break;
case 4:do //count=4,调整星期
{
hide_hour=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8a,temp); //写入新的星期数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_week++;
if(hide_week>3)
hide_week=0;
show_time();
}while(count==5);break;
case 5:do //count=5,调整日
{
hide_week=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x86,temp); //写入新的日数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_day++;
if(hide_day>3)
hide_day=0;
show_time();
}while(count==6);break;
case 6:do //count=6,调整月
{
hide_day=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x88,temp); //写入新的月数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_month++;
if(hide_month>3)
hide_month=0;
show_time();
}while(count==7);break;
case 7:do //count=7,调整年
{
hide_month=0;
outkey();
Upkey();
Downkey();
if(up_flag==1||down_flag==1)
{
Write1302(0x8e,0x00); //写入允许
Write1302(0x8c,temp); //写入新的年数
Write1302(0x8e,0x80); //禁止写入
up_flag=0;
down_flag=0;
}
hide_year++;
if(hide_year>3)
hide_year=0;
show_time();
}while(count==8);break;
case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态
Second=Read1302(DS1302_SECOND);
Write1302(0x8e,0x00); //写入允许
Write1302(0x80,Second&0x7f);
Write1302(0x8E,0x80); //禁止写入
done=0;
case 9:alarm(); break;
break; //count=7,开启中断,标志位置0并退出
default:break;
}
}
void gettime(void)
{ DS1302_GetTime(&CurrentTime); //获取时钟芯片的时钟数据到自定义的结构型数组
DateToStr(&CurrentTime); //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
TimeToStr(&CurrentTime); //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
if(hide_day<2)
{ DateStr[0]=(CurrentTime.Day)/10+0x30;
DateStr[1]=(CurrentTime.Day)%10+0x30;
}
else
{
DateStr[0] = ' ';
DateStr[1] = ' ';
}
}
void show_time() //液晶显示程序
{
gettime();
GotoXY(0,1);
Print(CurrentTime.TimeString); //显示时间
if(!settime_flag) //显示乱码,可能需要去掉
{
GotoXY(0,0);
Print(CurrentTime.DateString); //显示日期
GotoXY(8,0);
Print(DateStr); //显示日
GotoXY(15,0);
Print(week_value); //显示星期
GotoXY(11,0);
Print("Week"); //在液晶上显示 字母 week
}
if(alarm_on==1)
{ GotoXY(11,1);
Print("alarm");
}
Delay1ms(300); //扫描延时
}
void time_init(void)
{ IE=0x82;
TCON=0x00;
EA=1;
TMOD=0X01;
TH0=(56636-1500)/256;
TL0=(56636-1500)%256;
TR0=0;
}
void alarm_chage(void)
{
if(Down==0)
{
while(Down==0);
iii++;
if(iii==1)
{ alarm_on=1;
alarm_flag[0]='*';
}
if(iii==2)
{
alarm_flag[0]='.';
alarm_on=0;
}
if(iii==3)
iii=0;
alarm_flag_sto[0]=alarm_on;
Write1302(0x8e,0x00); //写入允许
WriteRAM(12,alarm_flag_sto,1);
Write1302(0x8e,0x80); //禁止写入 */
}
}
main()
{
flag=1; //时钟停止标志
LCD_Initial(); //液晶初始化
Initial_DS1302(); //时钟芯片初始化
up_flag=0;
down_flag=0;
done=0; //进入默认液晶显示
b=1;
P3=0xff;
time_init();
ReadRAM(0,stralarm,9);
ReadRAM(12,alarm_flag_sto,1);
alarm_on=alarm_flag_sto[0];
while(1)
{
while(done==1)
{ keydone(); //进入调整模式
fz();
}
while(done==0)
{
show_time(); //液晶显示数据
flag=0;
Setkey(); //扫描各功能键
fz();
alarm_chage();
}
}
}
void clok(void) interrupt 1
{ TH0=(56636-1500)/256;
TL0=(56636-1500)%256;
while(++count_stop==100)
{ count_stop=0;
second++;
if(second>=60)
{ second=0;
minite++;
if(minite>=60)
{ minite=0;
}
}
}
}