📄 main.c
字号:
if(tmp<0) min=59; else min=tmp; }
break;
case 0xf3: if(show_status==0) //闹钟设置的"分钟"减1
{ tmp=alarm[cur_alarm_set].m-1;
if(tmp<0) alarm[cur_alarm_set].m=59;
else alarm[cur_alarm_set].m=tmp;
}
else if(show_status==3)
{ day--; //当前日期的"日"减1
if(day==0) day=31; }
else if(show_status==4)
{ tmp=sec-1; //当前时间的"秒"减1
count_down=8000;
if(tmp<0) sec=59; else sec=tmp; }
break;
case 0xfd: if(show_status==0) //切换周末标志
alarm_wk^=0x1<<cur_alarm_set;
break;
case 0xfe: if(show_status==0) //切换启用标志
alarm_en^=0x1<<cur_alarm_set;
} //end of switch(attr)
return;
}
////////////////////////////////////////////////////////////////////////
void SetAlarm() //第一个按钮
{
//如果闹钟正响,按此键停止
if(sound)
{
alarm_stop=1;
sound=0;
}
//正显示日期或时间 进入闹钟设置
else if((show_status==1 || show_status==2) && led_on)
{
show_status=0;
cur_alarm_set=0;
attr=0x3f;
}
//如正在设置闹钟时间项 返回当前时间显示
else if(show_status==0)
{
show_status=2;
new_alarm_info=1;
attr=0xff;
}
}
////////////////////////////////////////////////////////////////////////
void Timer0ISR(void) interrupt 1 using 3 //定时器0中断程序,用于走时,1/8000秒一次
{
unsigned char tmp,tmp_days;
count_down--;
if(count_down==1 || count_down==2001 || count_down==4001 || count_down==6001)
{ flash=~flash; //数码管闪烁的开关量
if(sound && flash) sound_output=0; //驱动蜂鸣器
else sound_output=1; //关闭蜂鸣器
return;
}
/*** 计算当前日期为星期几***/
if(count_down==3000)
{ if(year==0) weekday=5; //2000年1月1日为星期六
else { tmp=(year-1)/4+1; tmp=(year-tmp)+tmp*2;
weekday=(tmp+5)%7; //计算出当前年的1月1日为星期几
}
tmp_days=0;
for(tmp=1;tmp<month;tmp++)
if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)
tmp_days=tmp_days+31;
else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)
tmp_days=tmp_days+30;
else if(tmp==2)
{ if(year%4==0) tmp_days=tmp_days+29;
else tmp_days=tmp_days+28;
}
tmp_days=tmp_days+day-1; weekday=(weekday+tmp_days%7)%7+1;
return;
}
/*** 查询是否有闹钟时间项符合触发条件 ***/
if(count_down==5000)
{ if((alarm_stop || sound) && alarm[cur_alarm_active].m!=min) //触发后1分钟
{ alarm_stop=0; sound=0; } //自动关蜂鸣器
if(sound==0 && alarm_stop==0) //没有已触发的闹钟项
for(tmp=0;tmp<8;tmp++) //则查询8个闹钟项内是否有符合条件的
{ if(((alarm_en>>tmp)&1)==0) continue; //该闹钟项不启用
if(((alarm_wk>>tmp)&1)==1) //该闹钟项周末有效
{ if(weekday!=6 && weekday!=7) continue; } //当前不是星期六或星期天
else
{ if(weekday==6 || weekday==7) continue; }
if(alarm[tmp].h==hour && alarm[tmp].m==min) //比较当前时间与该
{ sound=1; cur_alarm_active=tmp; break; } //闹钟项的时间
}
return;
}
if(count_down==0) //过了一秒钟
{ count_down=8000;
sec++;
if(sec==60)
{ sec=0;
min++;
if(min==60)
{ min=0;
hour++;
if(hour==24)
{ hour=0; day++;
switch(day)
{ case 29: if(month==2 && year%4) { day=1; month=3; }
break;
case 30: if(month==2 && year%4==0) { day=1; month=3; }
break;
case 31: if(month==4 || month==6 || month==9 || month==11)
{ day=1; month++; }
break;
case 32: day=1; month++;
if(month==13) { month=1; year++; }
}
}
}
}
}
}
///////////////////////////////////////////////////////
//定时器2中断,用于按键扫描
//////////////////////////////////////////////////////
void Timer1ISR(void) interrupt 3 using 2
{
unsigned char keytmp;
TH1=0x15;
TL1=0xa0; // 每30ms中断一次
if(show_status==0) //当前正在设置闹钟项
{
display[0]=dis_code[ cur_alarm_set ];
display[1]=0xff;
display[2]=dis_code[ alarm[cur_alarm_set].h/10 ];
display[3]=dis_code[ alarm[cur_alarm_set].h%10 ];
display[4]=dis_code[ alarm[cur_alarm_set].m/10 ];
display[5]=dis_code[ alarm[cur_alarm_set].m%10 ];
display[6]=dis_code[ (alarm_wk>>cur_alarm_set)&1 ];
display[7]=dis_code[ (alarm_en>>cur_alarm_set)&1 ];
}
if(show_status==1 || show_status==3) //当前显示或设置日期
{
display[0]=dis_code[ year/10 ];
display[1]=dis_code[ year%10 ];
display[2]=dis_code[ month/10 ];
display[3]=dis_code[ month%10 ];
display[4]=dis_code[ day/10 ];
display[5]=dis_code[ day%10 ];
display[6]=0xff;
display[7]=dis_code[ weekday ];
}
if(show_status==2 || show_status==4) //当前显示或设置时间
{
display[0]=dis_code[ hour/10 ];
display[1]=dis_code[ hour%10 ];
display[2]=dis_code[ min/10 ];
display[3]=dis_code[ min%10 ];
display[4]=dis_code[ sec/10 ];
display[5]=dis_code[ sec%10 ];
display[6]=0xff;
display[7]=0xff;
}
/*** 按键扫描及处理 ***/
keytmp=P3;
keytmp=keytmp>>2;
keytmp=~(keytmp) & 0x0f;
if(keytmp==0) {km=0;kp=0;}
else
{ if(km==0) km=1;
else
{ if(kp==0)
{ kp=1;
if(keytmp==1) SetAlarm(); //第一个按钮闹钟设置
if(keytmp==2 && led_on) SetInc(); //第二个按钮,仅当数码管打开时有效
if(keytmp==4) SetReduce(); //第三个按钮
if(keytmp==8 & led_on) SetNext(); //第四个按钮,仅当数码管打开时有效
} // end of if(kp==0)
} // end of if(km==0)
} // end of if(keytmp!=0)
}
//////////////////////////////////////////////////////////
//主函数入口
/////////////////////////////////////////////////////////
void main(void)
{
unsigned char i;
hour=12; min=00; sec=00;
year=8; month=8; day=8;
count_down=8000;
flash=0; attr=0xff;
led_on=1; //点亮数码管标志
km=0;kp=0;
show_status=2; //加电后显示当前时间
new_alarm_info=0;
sound=0;
alarm_stop=0;
for(i=0;i<8;i++) //从EEPROM中读入8个闹钟设置
{
alarm[i].h=myread(i*2);
alarm[i].m=myread(i*2+1);
}
alarm_en=myread(i*2);
alarm_wk=myread(i*2+1);
IE=0;
IP=0; //disable all interrupt and lower priority
TMOD=0x12; //timer 0 is set to mode 2,auto_reloading,timer1,mode 1
TH0=0x8d;
TL0=0x8d; //timer0 parameters for 0.125ms
TH1=0x94;
TL1=0x00; //timer1 parameters for 30ms
TR0=1;
TR1=1; //timer0 interrupt most important
ET0=1;
ET1=1;
EA=1; //enable interrupt function
while(1)
{
///////////////////////////////////
if(led_on)
for(i=0;i<8;i++)
{
P2=0xff;
if( flash || attr&(0x80>>i) )
{
P0=display[i];
P2=0xff-(0x80>>i);
DelayX1ms(1);
}
}
else P2=0xff;
///////////////////////////////////
if(new_alarm_info)
{
P2=0xff; //暂时关闭数码管
new_alarm_info=0; //写入EEPROM
for(i=0;i<8;i++)
{
mywrite(i*2,alarm[i].h);
mywrite(i*2+1,alarm[i].m);
}
mywrite(i*2,alarm_en);
mywrite(i*2+1,alarm_wk);
}
}
}
///////////////////////////////////////////////
//程序结束
///////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -