//预置时间初值的时钟(24h制) WJ SD
//+键盘服务(K1返回时钟界面,K2光标右移,K3数值加1)
//+日历(K4循环显示3遍,K5调整日期)
//+闹铃(K6设定) 非音乐
//+定时器(K7设定)
//+秒表(K8运行/暂停)
//第二代键盘,用的下面2排键盘!!
//更新了显示服务
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit P36=P3^6;
sbit P37=P3^7;
sbit P16=P1^6;
sbit P00=P0^0;
sbit P01=P0^1;
sbit P02=P0^2;
sbit P03=P0^3;
bit KEY_ON=0;
bit FLS_FLG=0;
bit RUN_FLG=1;
bit BACKRING_ON=0; //倒计时时间到
bit BACKRING_START=0; //倒计时启动标志
bit MSEC=0; //使用秒表标志
bit RING_ON=0; //使用闹铃标志
bit LINE1=1; //LINE1=1上一排按键有效LINE1=0则下一排有效
uchar tem; //键盘用临时参量1
uchar tem2; //键盘用临时参量2
uint year;
uchar keydelay=8; //键盘防抖动参数(ms)
uchar keyvalue=0; //键值
bit ms_stay=1; //秒表后台运行开关
uchar ring[]={0,8,12,2,7,10,13,13};
uchar rili[]={2,0,1,2,11,0,2,11,2,8,10,10,0,9,0,5,2,0,4,0,10}; //,0,9,0,5,2,0,4,0
uchar riqi[]={2,0,1,2,0,2,2,8};
char backring[]={0,0,12,0,0,12,0,8}; //预置定时器初值 需与backclk关联
uchar flash_allow[]={0,0,0,0,0,0,0,0};
uchar code seg[]={ //七段数码表
0x3f,0x06,0x5b,0x4f,0x66, //0~4
0x6d,0x7d,0x07,0x7f,0x6f, //5~9
0x00,0x08,0x40,0x00}; //全灭,日历分隔_ ,时钟分隔-,闹铃符号E
void delay_10us(uchar n) //10us级延时
{do
{_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
void delay_ms(uchar n) //ms级延时
{do
{delay_10us(131);
}while(--n);
}
void delay_3ms() //解决显示拖影
{ delay_ms(2);
delay_10us(110);
}
//------------------Music------------------
struct music_type
{uchar tone;
uchar delay;
};
uchar tl1,th1;
uint code tonetab_E[]={ //E调7声音阶的定时器定时参数
64138,64291,64426,64489,64603,64704,64795, //低音1~7
64837,64913,64981,65012,65070,65120,65166, //中音1~7
65186,65225,65259,65274,65303,65328,65351, //高音1~7
};
struct music_type code notetab[]={ //两只老虎曲谱
1+7,0x02,2+7,0x02,3+7,0x02,1+7,0x02,
1+7,0x02,2+7,0x02,3+7,0x02,1+7,0x02,
3+7,0x02,4+7,0x01,5+7,0x04,
3+7,0x02,4+7,0x01,5+7,0x04,
//
5+7,0x01,6+7,0x01,5+7,0x01,4+7,0x01,3+7,0x02,1+7,0x02,
5+7,0x01,6+7,0x01,5+7,0x01,4+7,0x01,3+7,0x02,1+7,0x02,
2+7,0x02,5+0,0x02,1+7,0x04,
2+7,0x02,5+0,0x02,1+7,0x04,
//------------
0,0x00
};
//-----------------------秒表用:-----------------------
struct clkms_type
{uchar s;
uchar ms;
}clkms={0,0};
uchar disbufms[4]={0,0,0,0};
uchar countms=2;
void inc_clkms() //秒表加10ms处理
{clkms.ms++;
if(clkms.ms==100)
{clkms.ms=0;
clkms.s++;
if(clkms.s==60)
{clkms.s=0;}
}
}
void clkms_to_disbuf() //时钟单元数据送显示缓
冲区
{disbufms[0]=clkms.s/10;
disbufms[1]=clkms.s%10;
disbufms[2]=clkms.ms/10;
disbufms[3]=clkms.ms%10;
}
void T1_serv() interrupt 3 //----------T1中断服务,秒表/音乐---------------
{
if(RING_ON)
{TL1=tl1;
TH1=th1;
P16=!P16;
}
//
if(MSEC)
{TH1=60928/256;
TL1=60928%256;
countms--;
if(countms==0)
{countms=2;
inc_clkms();
if(ms_stay)
clkms_to_disbuf();
}
}
}
//--------------------定时器用:---------------------
struct backclk_type
{char h;
char m;
char s;
}backclk={0,0,5};
void back_clk() //时钟-1s处理
{backclk.s--;
if(backclk.s==-1&&backclk.m)
{backclk.s=59;
backclk.m--;
if(backclk.m==-1&&backclk.h)
{backclk.m=59;
backclk.h--;
}
else if(backclk.m==-1&&backclk.h==0) BACKRING_ON=1;
}
else if(backclk.s==-1&&backclk.m==0&&backclk.h)
{backclk.s=59;backclk.m=59;backclk.h--;}
}
void backclk_to_disbuf() //时钟单元数据送显示缓冲区
{backring[0]=backclk.h/10;
backring[1]=backclk.h%10;
backring[3]=backclk.m/10;
backring[4]=backclk.m%10;
backring[6]=backclk.s/10;
backring[7]=backclk.s%10;
}
void disbuf_to_backclk() //显示缓冲区数据送时钟单元
{backclk.h=backring[0]*10+backring[1];
backclk.m=backring[3]*10+backring[4];
backclk.s=backring[6]*10+backring[7];
}
//-----------------------日历用:(日期进位)--------------------
void riqiadd()
{ year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];
{if( ((0==year%4)&&(0!=year%100))||(0==year%400))
{if(riqi[4]==0&&riqi[5]==2&&riqi[2]==2&&riqi[6]>9) //闰2月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}}
else {if(riqi[4]==0&&riqi[5]==2&&riqi[2]==2&&riqi[6]>8) //平2月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}}}
{if(riqi[4]==0&&(riqi[5]==1||riqi[5]==3||riqi[5]==5||riqi[5]==7||riqi[5]==8)&&riqi[6]==3&&riqi[7]>1) //大月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
if(riqi[4]==1&&riqi[5]==0&&riqi[2]==3&&riqi[6]>1)
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
if(riqi[4]==1&&riqi[5]==2&&riqi[6]==3&&riqi[7]>1) //大月
{riqi[4]=0;riqi[5]=1;riqi[6]=0;riqi[7]=1;riqi[3]++;}
if(riqi[4]==0&&(riqi[5]==4||riqi[5]==6||riqi[5]==9)&&riqi[6]==3&&riqi[7]>0) //小月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
if(riqi[4]==1&&riqi[5]==1&&riqi[2]==3&&riqi[6]>0) //小月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
}
}
//-----------------------日历用:(保证日期有效)--------------------
void riqi_to_rili()
{ year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];
{if( ((0==year%4)&&(0!=year%100))||(0==year%400))
{if(riqi[4]==0&&riqi[5]==2&&riqi[6]==2&&riqi[7]>9) {riqi[5]++;riqi[6]=0;riqi[7]=1;}} //2月
else {if(riqi[4]==0&&riqi[5]==2&&riqi[6]==2&&riqi[7]>8) {riqi[5]++;riqi[6]=0;riqi[7]=1;}}}
{ if(riqi[4]==0&&riqi[5]>9) {riqi[4]=1;riqi[5]=0;}; //month
if(riqi[4]==1&&riqi[5]>2) {riqi[4]=0;riqi[5]=1;};
if(riqi[7]>9) {riqi[6]++;riqi[7]=0;};
if(riqi[6]>3) {riqi[6]=0;riqi[7]=1;};
if(riqi[4]==0&&(riqi[5]==1||riqi[
5]==3||riqi[5]==5||riqi[5]==7||riqi[5]==8)&&riqi[6]==3&&riqi[7]>1) {riqi[5]++;riqi[6]=0;riqi[7]=1;}; //大月
if(riqi[4]==1&&(riqi[5]==0||riqi[5]==2)&&riqi[6]==3&&riqi[7]>1) {riqi[5]++;riqi[6]=0;riqi[7]=1;} //大月
if(riqi[4]==0&&(riqi[5]==4||riqi[5]==6||riqi[5]==9)&&riqi[6]==3&&riqi[7]>0) {riqi[5]++;riqi[6]=0;riqi[7]=1;} //小月
if(riqi[4]==1&&riqi[5]==1&&riqi[6]==3&&riqi[7]>0) {riqi[5]++;riqi[6]=0;riqi[7]=1;} //小月
}
rili[2]=riqi[2];rili[3]=riqi[3];
rili[5]=riqi[4];rili[6]=riqi[5]; //month
rili[8]=riqi[6];rili[9]=riqi[7]; //day
}
//--------------------------时钟用:---------------------------
uint p=1; //数码管闪烁位初值
struct clk_type
{uchar h;
uchar m;
uchar s;
}clk={0,0,0};
uchar disbuf[8]={0,0,12,0,0,12,0,0};
uchar count=200;
void inc_clk() //时钟加1s处理
{clk.s++;
if(clk.s==60)
{clk.s=0;
clk.m++;
if(clk.m==60)
{clk.m=0;
clk.h++;
if(clk.h==24) {clk.h=0;riqi[7]++;riqiadd();riqi_to_rili();}
}
}
}
void clk_to_disbuf() //时钟单元数据送显示缓冲区
{disbuf[0]=clk.h/10;
disbuf[1]=clk.h%10;
disbuf[3]=clk.m/10;
disbuf[4]=clk.m%10;
disbuf[6]=clk.s/10;
disbuf[7]=clk.s%10;
}
void disbuf_to_clk() //显示缓冲区数据送时钟单元
{clk.h=disbuf[0]*10+disbuf[1];
clk.m=disbuf[3]*10+disbuf[4];
clk.s=disbuf[6]*10+disbuf[7];
}
void t0_serv() interrupt 1 //T0中断服务
{TH0=19453/256;
TL0=19453%256;
count--;
if(count%5==0)
{FLS_FLG=!FLS_FLG;}
if(count==0)
{count=20;
if(RUN_FLG)
{inc_clk();
clk_to_disbuf();
if(BACKRING_START)
{back_clk();
backclk_to_disbuf();
}
}
}
}
uint key_rd() //按键控制子服务
{if(P00) return 1;
if(P01) return 2;
if(P02) return 3;
if(P03) return 4;
else return 0;
}
void key_ctrl() //按键控制服务 2行键盘
{
if(LINE1)
{
P36=0; //P36=0,WR有效
P37=1; //P37=0,RD有效
P2=0x8f; //段选使能
P0=0x04; //段选key2
P36=1;
P37=0;
tem=key_rd();
if(tem&&!KEY_ON)
{delay_ms(keydelay);
if(tem==key_rd())
{KEY_ON=1;tem2=tem;LINE1=1; }
else {KEY_ON=0;LINE1=0; }
}
if(tem==0&&!KEY_ON) {LINE1=0;}
if(KEY_ON) //
{
if(!(key_rd()))
{ delay_ms(keydelay);
if(!(key_rd()))
{keyvalue=tem2;KEY_ON=0;tem2=0;LINE1=1;}
}
}
}
//---------------------第一行无按键时读第二行按键
if(!LINE1)
{ P36=0; //P36=0,WR有效
P37=1; //P37=0,RD有效
P2=0x8f; //段选使能
P0=0x08; //段选key3
P36=1;
P37=0;
tem=key_rd();
if(tem&&!KEY_ON)
{delay_ms(keydelay);
if(tem==key_rd())
{KEY_ON=1;tem2=tem;LINE1=0; }
else { KEY_ON=0;LINE1=1; }
}
if(tem==0&&!KEY_ON) {LINE1=1;}
if(KEY_ON) //
{
if(!(key_rd()))
{ delay_ms(keydelay);
if(!(key_rd()))
{keyvalue=tem2+4;KEY_ON=0;tem2=0;LINE1=1;}
}
}
}
P37=1;
}
//------------------------显示服务(逐位)--------------------------
void LED_Display_pa
rt(uchar address,uchar LED_data)
{
uchar xdata *p;
p=0x8fff;
*p=address;
p=0x9fff;
*p=seg[LED_data];
delay_3ms();
}
//------------------------显示服务(全屏)--------------------------
void LED_Display(uchar LED_data[])
{
uchar xdata *p; //外部指针p
p=0x8fff; //AJ00=0,段选使能有效
*p=0x80; //段选数码管1
p=0x9fff; //AJ01=0,位选使能有效
if(FLS_FLG&&flash_allow[0])
*p=seg[10];
else
*p=seg[LED_data[0]]; //LED数字
delay_3ms();
p=0x8fff;
*p=0x40;
p=0x9fff;
if(FLS_FLG&&flash_allow[1])
*p=seg[10];
else
*p=seg[LED_data[1]];
delay_3ms();
p=0x8fff;
*p=0x20;
p=0x9fff;
if(FLS_FLG&&flash_allow[2])
*p=seg[10];
else
*p=seg[LED_data[2]];
delay_3ms();
p=0x8fff;
*p=0x10;
p=0x9fff;
if(FLS_FLG&&flash_allow[3])
*p=seg[10];
else
*p=seg[LED_data[3]];
delay_3ms();
p=0x8fff;
*p=0x08;
p=0x9fff;
if(FLS_FLG&&flash_allow[4])
*p=seg[10];
else
*p=seg[LED_data[4]];
delay_3ms();
p=0x8fff;
*p=0x04;
p=0x9fff;
if(FLS_FLG&&flash_allow[5])
*p=seg[10];
else
*p=seg[LED_data[5]];
delay_3ms();
p=0x8fff;
*p=0x02;
p=0x9fff;
if(FLS_FLG&&flash_allow[6])
*p=seg[10];
else
*p=seg[LED_data[6]];
delay_3ms();
p=0x8fff;
*p=0x01;
p=0x9fff;
if(FLS_FLG&&flash_allow[7])
*p=seg[10];
else
*p=seg[LED_data[7]];
delay_3ms();
}
//-----------------主函数----------------------------
void main()
{
uchar i=120;
uchar j=0;
uint k=0;
uint n=24;
TMOD=0x11;
TH0=19453/256;
TL0=19453%256;
count=20;
IE=0x8A; //开中断
TR0=1; //启动定时器T0
TR1=0; //不启动定时器T1
clk.h=23; //---------------------预置时间初值---------------
clk.m=59;
clk.s=30;
START:
while(1)
{ P16=1; //关蜂鸣器
TR1=0; //关TI计数器
keyvalue=0; //键盘初始化
key_ctrl(); //调用键盘服务
if(keyvalue)
{
if(keyvalue==1) //K1被按下 设定当前时间
{
//if(RUN_FLG)
{flash_allow[p]=!flash_allow[p];flash_allow[p-1]=!flash_allow[p-1];}
RUN_FLG=!RUN_FLG;
if(RUN_FLG)
{TH0=19453/256;
TL0=19453%256;
count=20;}
}
else if(keyvalue==2) //K2被按下 光标右移
{if(!RUN_FLG)
{ flash_allow[p]=0;flash_allow[p-1]=0;
if(p==1) p=4;
else p=1;
flash_allow[p]=1; flash_allow[p-1]=1;
}
}
else if(keyvalue==3) //K3被按下 数值加1
{if(!RUN_FLG)
{ if(p==1) disbuf[1]++;
if(p==4) disbuf[4]++;
if(p==1&&disbuf[0]
if(p==1&&disbuf[0]==2&&disbuf[1]==4) {disbuf[1]=0;disbuf[0]=0;}
if(p==4&&disbuf[4]>9) {disbuf[4]=0; disbuf[3]++;}
if(disbuf[3]>5) {disbuf[3]
=0;disbuf[4]=0;}
disbuf_to_clk();
}
}
else if(keyvalue==4) //-----K4循环显示3遍日历----
{ i=0;
do
{
do
{
keyvalue=0;
key_ctrl();
if(keyvalue==1) {i=27;break;}
LED_Display_part(0x80,rili[i%12]);
LED_Display_part(0x40,rili[(i+1)%12]);
LED_Display_part(0x20,rili[(i+2)%12]);
LED_Display_part(0x10,rili[(i+3)%12]);
LED_Display_part(0x08,rili[(i+4)%12]);
LED_Display_part(0x04,rili[(i+5)%12]);
LED_Display_part(0x02,rili[(i+6)%12]);
LED_Display_part(0x01,rili[(i+7)%12]);
}while(n--);n=24;
i++;
}
while(i
}
/*
else if(keyvalue==4) //-----K4循环显示3遍日历----加学号版
{ i=0;
do
{
do
{
keyvalue=0;
key_ctrl();
if(keyvalue==1) {i=55;break;}
LED_Display_part(0x80,rili[i%12]);
LED_Display_part(0x40,rili[(i+1)%21]);
LED_Display_part(0x20,rili[(i+2)%21]);
LED_Display_part(0x10,rili[(i+3)%21]);
LED_Display_part(0x08,rili[(i+4)%21]);
LED_Display_part(0x04,rili[(i+5)%21]);
LED_Display_part(0x02,rili[(i+6)%21]);
LED_Display_part(0x01,rili[(i+7)%21]);
}while(n--);n=24;
i++;
}
while(i
}
*/
else if(keyvalue==5) //------------------------K5调整日期----------------------
{
p=3;
flash_allow[p]=1;flash_allow[p-1]=1;// flash_allow[p-2]=1;flash_allow[p-3]=1;
while(1)
{
keyvalue=0;
key_ctrl();
if(keyvalue==2) //K2被按下
{
{ flash_allow[p]=0;flash_allow[p-1]=0;
switch(p)
{case 3:p=5;break;
case 5:p=7;break;
case 7:p=3;break;}
flash_allow[p]=1;flash_allow[p-1]=1;
}
}
if(keyvalue==3) //K3被按下
{ keyvalue=0;
if(p==3) riqi[3]++;
if(p==5) riqi[5]++;
if(p==7) riqi[7]++;
riqi_to_rili();
}
if(keyvalue==4) //K4被按下
{ keyvalue=0;
if(p==3) riqi[3]--;
if(p==5) riqi[5]--;
if(p==7) riqi[7]--;
riqi_to_rili();
}
if(keyvalue==1) {
// for(p=0;p++;p
{flash_allow[0]=0;flash_allow[1]=0;flash_allow[2]=0;flash_allow[3]=0;
flash_allow[4]=0;flash_allow[5]=0;flash_allow[6]=0;flash_allow[7]=0;
}
p=1;goto NOW;}
LED_Display(riqi);
}
}
else if(keyvalue==6) //----------------------K6调节闹铃 -------------------
{ p=1;
flash_allow[p]=1;flash_allow[p-1]=1;
while(1)
{
keyvalue=0;
key_ctrl();
if(keyvalue==2) //K2被按下
{
{ flash_allow[p]=0;flash_allow[p-1]=0;
if(p==1) p=4;
else p=1;
flash_allow[p]=1;flash_allow[p-1]=1;
}
}
if(keyvalue==3) //K3被按下
{
if(p==1) ring[1]++;
if(p==4) ring[4]++;
if(ring[0]9) {ring[0]++;ring[1]=0;}
if(ring[0]==2&&ring[1]>3) {ring[0]=0;ring[1]=0;}
if(ring[3]9) {ring[3]++;ring[4]=0;}
if(ring[3]==5&&ring[4]>9) {ring[3]=0;ring[4]=0;}
}
if(keyvalue==1) {flash_allow[0]=flash_allow[1]=flash_allow[3]=flash_allow[4]=0;p=1;break; }
LED_Display(ring);
}
}
else if(keyvalue==7) //----------------------K7定时器 -------------------
{ BACKRING_START=0;
BACKRING_ON=0;
p=1;
flash_allow[p]=1;flash_allow[p-1]=1;
while(1)
{
keyvalue=0;
key_ctrl();
if(keyvalue==2) //K2被按下
{
flash_allow[p]=flash_allow[p-1]=0;
switch(p)
{ case 1: p=4;break;
case 4: p=7;break;
case 7: p=1;break;
}
flash_allow[p]=flash_allow[p-1]=1;
}
if(keyvalue==3) //K3被按下
{
if(p==1) backring[1]++;
if(p==4) backring[4]++;
if(p==7) backring[7]++;
if(backring[0]9) {backring[0]++;backring[1]=0;}
if(backring[0]==9&&backring[1]>9) {backring[0]=0;backring[1]=0;}
if(backring[3]9) {backring[3]++;backring[4]=0;}
if(backring[3]==5&&backring[4]>9) {backring[3]=0;backring[4]=0;}
if(backring[6]9) {backring[6]++;backring[7]=0;}
if(backring[6]==5&&backring[7]>9) {backring[6]=0;backring[7]=0;}
disbuf_to_backclk();
}
if(keyvalue==1)
{ for(i=0;i
flash_allow[i]=0;P16=1;p=1;break;}
if(keyvalue==7) {for(i=0;i
if(backring[0]==0&&backring[1]==0&&backring[3]==0&&backring[4]==0&&backring[6]==0&&backring[7]==0&&BACKRING_ON)
{ BACKRING_START=0; //----响铃条件
//music
i=0;RING_ON=1;
while(notetab[i].delay)
{if(!notetab[i].tone) TR1=0;
else
{th1=TH1=tonetab_E[notetab[i].tone-1]>>8;
tl1=TL1=tonetab_E[notetab[i].tone-1]&0xff;
TR1=1;
}
for(j=0;j
{
for(k=0;k
{
keyvalue=0; //键盘初始化
key_ctrl(); //调用键盘服务
if(keyvalue==1) {RING_ON=0;goto START;}
LED_Display_part(0x01,0);
LED_Display_part(0x02,0);
LED_Display_part(0x04,12);
LED_Display_part(0x08,0);
LED_Display_part(0x10,0);
LED_Display_part(0x20,12);
LED_Display_part(0x40,0);
LED_Display_part(0x80,0);
}
}//delay_ms(150)延时用于显示;
i++;
}
RING_ON=0;
goto START;
}
LED_Display(backring);
}
}
else if(keyvalue==8) // ----------------K8秒表-------------------
{ MSEC=1;
TR1=1;
clkms.ms=0;
clkms.s=0;
clkms_to_disbuf();
while(1)
{ keyvalue=0;
key_ctrl();
if(keyvalue==8) TR1=!TR1;
if(keyvalue==1) {MSEC=0;ms_stay=0;break;}
if(keyvalue==4) ms_stay=!ms_stay;
LED_Display_part(0x20,disbufms[0]);
LED_Display_part(0x10,disbufms[1]);
LED_Display_pa
rt(0x08,12);
LED_Display_part(0x04,12);
LED_Display_part(0x02,disbufms[2]);
LED_Display_part(0x01,disbufms[3]);
}
}
//----------------------------可在此添加新键盘服务 ------------------------
}
//------------当前时钟显示-----------
NOW:
LED_Display(disbuf);
// -------------------------------------闹钟---------------------
if(disbuf[0]==ring[0]&&disbuf[1]==ring[1]&&disbuf[3]==ring[3]&&disbuf[4]==ring[4]&&disbuf[6]
{ i=0;RING_ON=1;
while(notetab[i].delay)
{if(!notetab[i].tone) TR1=0;
else
{th1=TH1=tonetab_E[notetab[i].tone-1]>>8;
tl1=TL1=tonetab_E[notetab[i].tone-1]&0xff;
TR1=1;
}
for(j=0;j
{
for(k=0;k
{
keyvalue=0; //键盘初始化
key_ctrl(); //调用键盘服务
if(keyvalue==1) {RING_ON=0;goto START;}
//
LED_Display(disbuf);
}
}//delay_ms(150)延时用于显示;
i++;
}
RING_ON=0;
goto START;
}
}
}
//预置时间初值的时钟(24h制) WJ SD
//+键盘服务(K1返回时钟界面,K2光标右移,K3数值加1)
//+日历(K4循环显示3遍,K5调整日期)
//+闹铃(K6设定) 非音乐
//+定时器(K7设定)
//+秒表(K8运行/暂停)
//第二代键盘,用的下面2排键盘!!
//更新了显示服务
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit P36=P3^6;
sbit P37=P3^7;
sbit P16=P1^6;
sbit P00=P0^0;
sbit P01=P0^1;
sbit P02=P0^2;
sbit P03=P0^3;
bit KEY_ON=0;
bit FLS_FLG=0;
bit RUN_FLG=1;
bit BACKRING_ON=0; //倒计时时间到
bit BACKRING_START=0; //倒计时启动标志
bit MSEC=0; //使用秒表标志
bit RING_ON=0; //使用闹铃标志
bit LINE1=1; //LINE1=1上一排按键有效LINE1=0则下一排有效
uchar tem; //键盘用临时参量1
uchar tem2; //键盘用临时参量2
uint year;
uchar keydelay=8; //键盘防抖动参数(ms)
uchar keyvalue=0; //键值
bit ms_stay=1; //秒表后台运行开关
uchar ring[]={0,8,12,2,7,10,13,13};
uchar rili[]={2,0,1,2,11,0,2,11,2,8,10,10,0,9,0,5,2,0,4,0,10}; //,0,9,0,5,2,0,4,0
uchar riqi[]={2,0,1,2,0,2,2,8};
char backring[]={0,0,12,0,0,12,0,8}; //预置定时器初值 需与backclk关联
uchar flash_allow[]={0,0,0,0,0,0,0,0};
uchar code seg[]={ //七段数码表
0x3f,0x06,0x5b,0x4f,0x66, //0~4
0x6d,0x7d,0x07,0x7f,0x6f, //5~9
0x00,0x08,0x40,0x00}; //全灭,日历分隔_ ,时钟分隔-,闹铃符号E
void delay_10us(uchar n) //10us级延时
{do
{_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
void delay_ms(uchar n) //ms级延时
{do
{delay_10us(131);
}while(--n);
}
void delay_3ms() //解决显示拖影
{ delay_ms(2);
delay_10us(110);
}
//------------------Music------------------
struct music_type
{uchar tone;
uchar delay;
};
uchar tl1,th1;
uint code tonetab_E[]={ //E调7声音阶的定时器定时参数
64138,64291,64426,64489,64603,64704,64795, //低音1~7
64837,64913,64981,65012,65070,65120,65166, //中音1~7
65186,65225,65259,65274,65303,65328,65351, //高音1~7
};
struct music_type code notetab[]={ //两只老虎曲谱
1+7,0x02,2+7,0x02,3+7,0x02,1+7,0x02,
1+7,0x02,2+7,0x02,3+7,0x02,1+7,0x02,
3+7,0x02,4+7,0x01,5+7,0x04,
3+7,0x02,4+7,0x01,5+7,0x04,
//
5+7,0x01,6+7,0x01,5+7,0x01,4+7,0x01,3+7,0x02,1+7,0x02,
5+7,0x01,6+7,0x01,5+7,0x01,4+7,0x01,3+7,0x02,1+7,0x02,
2+7,0x02,5+0,0x02,1+7,0x04,
2+7,0x02,5+0,0x02,1+7,0x04,
//------------
0,0x00
};
//-----------------------秒表用:-----------------------
struct clkms_type
{uchar s;
uchar ms;
}clkms={0,0};
uchar disbufms[4]={0,0,0,0};
uchar countms=2;
void inc_clkms() //秒表加10ms处理
{clkms.ms++;
if(clkms.ms==100)
{clkms.ms=0;
clkms.s++;
if(clkms.s==60)
{clkms.s=0;}
}
}
void clkms_to_disbuf() //时钟单元数据送显示缓
冲区
{disbufms[0]=clkms.s/10;
disbufms[1]=clkms.s%10;
disbufms[2]=clkms.ms/10;
disbufms[3]=clkms.ms%10;
}
void T1_serv() interrupt 3 //----------T1中断服务,秒表/音乐---------------
{
if(RING_ON)
{TL1=tl1;
TH1=th1;
P16=!P16;
}
//
if(MSEC)
{TH1=60928/256;
TL1=60928%256;
countms--;
if(countms==0)
{countms=2;
inc_clkms();
if(ms_stay)
clkms_to_disbuf();
}
}
}
//--------------------定时器用:---------------------
struct backclk_type
{char h;
char m;
char s;
}backclk={0,0,5};
void back_clk() //时钟-1s处理
{backclk.s--;
if(backclk.s==-1&&backclk.m)
{backclk.s=59;
backclk.m--;
if(backclk.m==-1&&backclk.h)
{backclk.m=59;
backclk.h--;
}
else if(backclk.m==-1&&backclk.h==0) BACKRING_ON=1;
}
else if(backclk.s==-1&&backclk.m==0&&backclk.h)
{backclk.s=59;backclk.m=59;backclk.h--;}
}
void backclk_to_disbuf() //时钟单元数据送显示缓冲区
{backring[0]=backclk.h/10;
backring[1]=backclk.h%10;
backring[3]=backclk.m/10;
backring[4]=backclk.m%10;
backring[6]=backclk.s/10;
backring[7]=backclk.s%10;
}
void disbuf_to_backclk() //显示缓冲区数据送时钟单元
{backclk.h=backring[0]*10+backring[1];
backclk.m=backring[3]*10+backring[4];
backclk.s=backring[6]*10+backring[7];
}
//-----------------------日历用:(日期进位)--------------------
void riqiadd()
{ year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];
{if( ((0==year%4)&&(0!=year%100))||(0==year%400))
{if(riqi[4]==0&&riqi[5]==2&&riqi[2]==2&&riqi[6]>9) //闰2月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}}
else {if(riqi[4]==0&&riqi[5]==2&&riqi[2]==2&&riqi[6]>8) //平2月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}}}
{if(riqi[4]==0&&(riqi[5]==1||riqi[5]==3||riqi[5]==5||riqi[5]==7||riqi[5]==8)&&riqi[6]==3&&riqi[7]>1) //大月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
if(riqi[4]==1&&riqi[5]==0&&riqi[2]==3&&riqi[6]>1)
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
if(riqi[4]==1&&riqi[5]==2&&riqi[6]==3&&riqi[7]>1) //大月
{riqi[4]=0;riqi[5]=1;riqi[6]=0;riqi[7]=1;riqi[3]++;}
if(riqi[4]==0&&(riqi[5]==4||riqi[5]==6||riqi[5]==9)&&riqi[6]==3&&riqi[7]>0) //小月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
if(riqi[4]==1&&riqi[5]==1&&riqi[2]==3&&riqi[6]>0) //小月
{riqi[5]++;riqi[6]=0;riqi[7]=1;}
}
}
//-----------------------日历用:(保证日期有效)--------------------
void riqi_to_rili()
{ year=riqi[0]*1000+riqi[1]*100+riqi[2]*10+riqi[3];
{if( ((0==year%4)&&(0!=year%100))||(0==year%400))
{if(riqi[4]==0&&riqi[5]==2&&riqi[6]==2&&riqi[7]>9) {riqi[5]++;riqi[6]=0;riqi[7]=1;}} //2月
else {if(riqi[4]==0&&riqi[5]==2&&riqi[6]==2&&riqi[7]>8) {riqi[5]++;riqi[6]=0;riqi[7]=1;}}}
{ if(riqi[4]==0&&riqi[5]>9) {riqi[4]=1;riqi[5]=0;}; //month
if(riqi[4]==1&&riqi[5]>2) {riqi[4]=0;riqi[5]=1;};
if(riqi[7]>9) {riqi[6]++;riqi[7]=0;};
if(riqi[6]>3) {riqi[6]=0;riqi[7]=1;};
if(riqi[4]==0&&(riqi[5]==1||riqi[
5]==3||riqi[5]==5||riqi[5]==7||riqi[5]==8)&&riqi[6]==3&&riqi[7]>1) {riqi[5]++;riqi[6]=0;riqi[7]=1;}; //大月
if(riqi[4]==1&&(riqi[5]==0||riqi[5]==2)&&riqi[6]==3&&riqi[7]>1) {riqi[5]++;riqi[6]=0;riqi[7]=1;} //大月
if(riqi[4]==0&&(riqi[5]==4||riqi[5]==6||riqi[5]==9)&&riqi[6]==3&&riqi[7]>0) {riqi[5]++;riqi[6]=0;riqi[7]=1;} //小月
if(riqi[4]==1&&riqi[5]==1&&riqi[6]==3&&riqi[7]>0) {riqi[5]++;riqi[6]=0;riqi[7]=1;} //小月
}
rili[2]=riqi[2];rili[3]=riqi[3];
rili[5]=riqi[4];rili[6]=riqi[5]; //month
rili[8]=riqi[6];rili[9]=riqi[7]; //day
}
//--------------------------时钟用:---------------------------
uint p=1; //数码管闪烁位初值
struct clk_type
{uchar h;
uchar m;
uchar s;
}clk={0,0,0};
uchar disbuf[8]={0,0,12,0,0,12,0,0};
uchar count=200;
void inc_clk() //时钟加1s处理
{clk.s++;
if(clk.s==60)
{clk.s=0;
clk.m++;
if(clk.m==60)
{clk.m=0;
clk.h++;
if(clk.h==24) {clk.h=0;riqi[7]++;riqiadd();riqi_to_rili();}
}
}
}
void clk_to_disbuf() //时钟单元数据送显示缓冲区
{disbuf[0]=clk.h/10;
disbuf[1]=clk.h%10;
disbuf[3]=clk.m/10;
disbuf[4]=clk.m%10;
disbuf[6]=clk.s/10;
disbuf[7]=clk.s%10;
}
void disbuf_to_clk() //显示缓冲区数据送时钟单元
{clk.h=disbuf[0]*10+disbuf[1];
clk.m=disbuf[3]*10+disbuf[4];
clk.s=disbuf[6]*10+disbuf[7];
}
void t0_serv() interrupt 1 //T0中断服务
{TH0=19453/256;
TL0=19453%256;
count--;
if(count%5==0)
{FLS_FLG=!FLS_FLG;}
if(count==0)
{count=20;
if(RUN_FLG)
{inc_clk();
clk_to_disbuf();
if(BACKRING_START)
{back_clk();
backclk_to_disbuf();
}
}
}
}
uint key_rd() //按键控制子服务
{if(P00) return 1;
if(P01) return 2;
if(P02) return 3;
if(P03) return 4;
else return 0;
}
void key_ctrl() //按键控制服务 2行键盘
{
if(LINE1)
{
P36=0; //P36=0,WR有效
P37=1; //P37=0,RD有效
P2=0x8f; //段选使能
P0=0x04; //段选key2
P36=1;
P37=0;
tem=key_rd();
if(tem&&!KEY_ON)
{delay_ms(keydelay);
if(tem==key_rd())
{KEY_ON=1;tem2=tem;LINE1=1; }
else {KEY_ON=0;LINE1=0; }
}
if(tem==0&&!KEY_ON) {LINE1=0;}
if(KEY_ON) //
{
if(!(key_rd()))
{ delay_ms(keydelay);
if(!(key_rd()))
{keyvalue=tem2;KEY_ON=0;tem2=0;LINE1=1;}
}
}
}
//---------------------第一行无按键时读第二行按键
if(!LINE1)
{ P36=0; //P36=0,WR有效
P37=1; //P37=0,RD有效
P2=0x8f; //段选使能
P0=0x08; //段选key3
P36=1;
P37=0;
tem=key_rd();
if(tem&&!KEY_ON)
{delay_ms(keydelay);
if(tem==key_rd())
{KEY_ON=1;tem2=tem;LINE1=0; }
else { KEY_ON=0;LINE1=1; }
}
if(tem==0&&!KEY_ON) {LINE1=1;}
if(KEY_ON) //
{
if(!(key_rd()))
{ delay_ms(keydelay);
if(!(key_rd()))
{keyvalue=tem2+4;KEY_ON=0;tem2=0;LINE1=1;}
}
}
}
P37=1;
}
//------------------------显示服务(逐位)--------------------------
void LED_Display_pa
rt(uchar address,uchar LED_data)
{
uchar xdata *p;
p=0x8fff;
*p=address;
p=0x9fff;
*p=seg[LED_data];
delay_3ms();
}
//------------------------显示服务(全屏)--------------------------
void LED_Display(uchar LED_data[])
{
uchar xdata *p; //外部指针p
p=0x8fff; //AJ00=0,段选使能有效
*p=0x80; //段选数码管1
p=0x9fff; //AJ01=0,位选使能有效
if(FLS_FLG&&flash_allow[0])
*p=seg[10];
else
*p=seg[LED_data[0]]; //LED数字
delay_3ms();
p=0x8fff;
*p=0x40;
p=0x9fff;
if(FLS_FLG&&flash_allow[1])
*p=seg[10];
else
*p=seg[LED_data[1]];
delay_3ms();
p=0x8fff;
*p=0x20;
p=0x9fff;
if(FLS_FLG&&flash_allow[2])
*p=seg[10];
else
*p=seg[LED_data[2]];
delay_3ms();
p=0x8fff;
*p=0x10;
p=0x9fff;
if(FLS_FLG&&flash_allow[3])
*p=seg[10];
else
*p=seg[LED_data[3]];
delay_3ms();
p=0x8fff;
*p=0x08;
p=0x9fff;
if(FLS_FLG&&flash_allow[4])
*p=seg[10];
else
*p=seg[LED_data[4]];
delay_3ms();
p=0x8fff;
*p=0x04;
p=0x9fff;
if(FLS_FLG&&flash_allow[5])
*p=seg[10];
else
*p=seg[LED_data[5]];
delay_3ms();
p=0x8fff;
*p=0x02;
p=0x9fff;
if(FLS_FLG&&flash_allow[6])
*p=seg[10];
else
*p=seg[LED_data[6]];
delay_3ms();
p=0x8fff;
*p=0x01;
p=0x9fff;
if(FLS_FLG&&flash_allow[7])
*p=seg[10];
else
*p=seg[LED_data[7]];
delay_3ms();
}
//-----------------主函数----------------------------
void main()
{
uchar i=120;
uchar j=0;
uint k=0;
uint n=24;
TMOD=0x11;
TH0=19453/256;
TL0=19453%256;
count=20;
IE=0x8A; //开中断
TR0=1; //启动定时器T0
TR1=0; //不启动定时器T1
clk.h=23; //---------------------预置时间初值---------------
clk.m=59;
clk.s=30;
START:
while(1)
{ P16=1; //关蜂鸣器
TR1=0; //关TI计数器
keyvalue=0; //键盘初始化
key_ctrl(); //调用键盘服务
if(keyvalue)
{
if(keyvalue==1) //K1被按下 设定当前时间
{
//if(RUN_FLG)
{flash_allow[p]=!flash_allow[p];flash_allow[p-1]=!flash_allow[p-1];}
RUN_FLG=!RUN_FLG;
if(RUN_FLG)
{TH0=19453/256;
TL0=19453%256;
count=20;}
}
else if(keyvalue==2) //K2被按下 光标右移
{if(!RUN_FLG)
{ flash_allow[p]=0;flash_allow[p-1]=0;
if(p==1) p=4;
else p=1;
flash_allow[p]=1; flash_allow[p-1]=1;
}
}
else if(keyvalue==3) //K3被按下 数值加1
{if(!RUN_FLG)
{ if(p==1) disbuf[1]++;
if(p==4) disbuf[4]++;
if(p==1&&disbuf[0]
if(p==1&&disbuf[0]==2&&disbuf[1]==4) {disbuf[1]=0;disbuf[0]=0;}
if(p==4&&disbuf[4]>9) {disbuf[4]=0; disbuf[3]++;}
if(disbuf[3]>5) {disbuf[3]
=0;disbuf[4]=0;}
disbuf_to_clk();
}
}
else if(keyvalue==4) //-----K4循环显示3遍日历----
{ i=0;
do
{
do
{
keyvalue=0;
key_ctrl();
if(keyvalue==1) {i=27;break;}
LED_Display_part(0x80,rili[i%12]);
LED_Display_part(0x40,rili[(i+1)%12]);
LED_Display_part(0x20,rili[(i+2)%12]);
LED_Display_part(0x10,rili[(i+3)%12]);
LED_Display_part(0x08,rili[(i+4)%12]);
LED_Display_part(0x04,rili[(i+5)%12]);
LED_Display_part(0x02,rili[(i+6)%12]);
LED_Display_part(0x01,rili[(i+7)%12]);
}while(n--);n=24;
i++;
}
while(i
}
/*
else if(keyvalue==4) //-----K4循环显示3遍日历----加学号版
{ i=0;
do
{
do
{
keyvalue=0;
key_ctrl();
if(keyvalue==1) {i=55;break;}
LED_Display_part(0x80,rili[i%12]);
LED_Display_part(0x40,rili[(i+1)%21]);
LED_Display_part(0x20,rili[(i+2)%21]);
LED_Display_part(0x10,rili[(i+3)%21]);
LED_Display_part(0x08,rili[(i+4)%21]);
LED_Display_part(0x04,rili[(i+5)%21]);
LED_Display_part(0x02,rili[(i+6)%21]);
LED_Display_part(0x01,rili[(i+7)%21]);
}while(n--);n=24;
i++;
}
while(i
}
*/
else if(keyvalue==5) //------------------------K5调整日期----------------------
{
p=3;
flash_allow[p]=1;flash_allow[p-1]=1;// flash_allow[p-2]=1;flash_allow[p-3]=1;
while(1)
{
keyvalue=0;
key_ctrl();
if(keyvalue==2) //K2被按下
{
{ flash_allow[p]=0;flash_allow[p-1]=0;
switch(p)
{case 3:p=5;break;
case 5:p=7;break;
case 7:p=3;break;}
flash_allow[p]=1;flash_allow[p-1]=1;
}
}
if(keyvalue==3) //K3被按下
{ keyvalue=0;
if(p==3) riqi[3]++;
if(p==5) riqi[5]++;
if(p==7) riqi[7]++;
riqi_to_rili();
}
if(keyvalue==4) //K4被按下
{ keyvalue=0;
if(p==3) riqi[3]--;
if(p==5) riqi[5]--;
if(p==7) riqi[7]--;
riqi_to_rili();
}
if(keyvalue==1) {
// for(p=0;p++;p
{flash_allow[0]=0;flash_allow[1]=0;flash_allow[2]=0;flash_allow[3]=0;
flash_allow[4]=0;flash_allow[5]=0;flash_allow[6]=0;flash_allow[7]=0;
}
p=1;goto NOW;}
LED_Display(riqi);
}
}
else if(keyvalue==6) //----------------------K6调节闹铃 -------------------
{ p=1;
flash_allow[p]=1;flash_allow[p-1]=1;
while(1)
{
keyvalue=0;
key_ctrl();
if(keyvalue==2) //K2被按下
{
{ flash_allow[p]=0;flash_allow[p-1]=0;
if(p==1) p=4;
else p=1;
flash_allow[p]=1;flash_allow[p-1]=1;
}
}
if(keyvalue==3) //K3被按下
{
if(p==1) ring[1]++;
if(p==4) ring[4]++;
if(ring[0]9) {ring[0]++;ring[1]=0;}
if(ring[0]==2&&ring[1]>3) {ring[0]=0;ring[1]=0;}
if(ring[3]9) {ring[3]++;ring[4]=0;}
if(ring[3]==5&&ring[4]>9) {ring[3]=0;ring[4]=0;}
}
if(keyvalue==1) {flash_allow[0]=flash_allow[1]=flash_allow[3]=flash_allow[4]=0;p=1;break; }
LED_Display(ring);
}
}
else if(keyvalue==7) //----------------------K7定时器 -------------------
{ BACKRING_START=0;
BACKRING_ON=0;
p=1;
flash_allow[p]=1;flash_allow[p-1]=1;
while(1)
{
keyvalue=0;
key_ctrl();
if(keyvalue==2) //K2被按下
{
flash_allow[p]=flash_allow[p-1]=0;
switch(p)
{ case 1: p=4;break;
case 4: p=7;break;
case 7: p=1;break;
}
flash_allow[p]=flash_allow[p-1]=1;
}
if(keyvalue==3) //K3被按下
{
if(p==1) backring[1]++;
if(p==4) backring[4]++;
if(p==7) backring[7]++;
if(backring[0]9) {backring[0]++;backring[1]=0;}
if(backring[0]==9&&backring[1]>9) {backring[0]=0;backring[1]=0;}
if(backring[3]9) {backring[3]++;backring[4]=0;}
if(backring[3]==5&&backring[4]>9) {backring[3]=0;backring[4]=0;}
if(backring[6]9) {backring[6]++;backring[7]=0;}
if(backring[6]==5&&backring[7]>9) {backring[6]=0;backring[7]=0;}
disbuf_to_backclk();
}
if(keyvalue==1)
{ for(i=0;i
flash_allow[i]=0;P16=1;p=1;break;}
if(keyvalue==7) {for(i=0;i
if(backring[0]==0&&backring[1]==0&&backring[3]==0&&backring[4]==0&&backring[6]==0&&backring[7]==0&&BACKRING_ON)
{ BACKRING_START=0; //----响铃条件
//music
i=0;RING_ON=1;
while(notetab[i].delay)
{if(!notetab[i].tone) TR1=0;
else
{th1=TH1=tonetab_E[notetab[i].tone-1]>>8;
tl1=TL1=tonetab_E[notetab[i].tone-1]&0xff;
TR1=1;
}
for(j=0;j
{
for(k=0;k
{
keyvalue=0; //键盘初始化
key_ctrl(); //调用键盘服务
if(keyvalue==1) {RING_ON=0;goto START;}
LED_Display_part(0x01,0);
LED_Display_part(0x02,0);
LED_Display_part(0x04,12);
LED_Display_part(0x08,0);
LED_Display_part(0x10,0);
LED_Display_part(0x20,12);
LED_Display_part(0x40,0);
LED_Display_part(0x80,0);
}
}//delay_ms(150)延时用于显示;
i++;
}
RING_ON=0;
goto START;
}
LED_Display(backring);
}
}
else if(keyvalue==8) // ----------------K8秒表-------------------
{ MSEC=1;
TR1=1;
clkms.ms=0;
clkms.s=0;
clkms_to_disbuf();
while(1)
{ keyvalue=0;
key_ctrl();
if(keyvalue==8) TR1=!TR1;
if(keyvalue==1) {MSEC=0;ms_stay=0;break;}
if(keyvalue==4) ms_stay=!ms_stay;
LED_Display_part(0x20,disbufms[0]);
LED_Display_part(0x10,disbufms[1]);
LED_Display_pa
rt(0x08,12);
LED_Display_part(0x04,12);
LED_Display_part(0x02,disbufms[2]);
LED_Display_part(0x01,disbufms[3]);
}
}
//----------------------------可在此添加新键盘服务 ------------------------
}
//------------当前时钟显示-----------
NOW:
LED_Display(disbuf);
// -------------------------------------闹钟---------------------
if(disbuf[0]==ring[0]&&disbuf[1]==ring[1]&&disbuf[3]==ring[3]&&disbuf[4]==ring[4]&&disbuf[6]
{ i=0;RING_ON=1;
while(notetab[i].delay)
{if(!notetab[i].tone) TR1=0;
else
{th1=TH1=tonetab_E[notetab[i].tone-1]>>8;
tl1=TL1=tonetab_E[notetab[i].tone-1]&0xff;
TR1=1;
}
for(j=0;j
{
for(k=0;k
{
keyvalue=0; //键盘初始化
key_ctrl(); //调用键盘服务
if(keyvalue==1) {RING_ON=0;goto START;}
//
LED_Display(disbuf);
}
}//delay_ms(150)延时用于显示;
i++;
}
RING_ON=0;
goto START;
}
}
}