#include<iom16v.h> #include<macros.h> #define uchar unsigned char #define uint unsigned int #define setb(val,bitn) (val|=(1<<(bitn)))//设置某IO口某位为1 #define clr(val,bitn) (val&=~(1<<(bitn)))//设置某IO口某位为0 #define get(val,bitn) (val&(1<<(bitn)))//读取某位状态 uchar shi=20,fen=39,miao,a=0xff,num; #pragma interrupt_handler zhong:9//它所对应的位置 #pragma data:code//定义程序存在ROM里面 const uchar table[]={ 0xc0,0xf9,0xa4,0xb0,0x99, 0x92,0x82,0xf8,0x80,0x90, 0x88,0x83,0xc6,0xa1,0x86, 0x8e }; /***********************************************/ /*******************延时子程序******************/ /***********************************************/ void delay(uchar z) { uchar x,y; for(x=0;x<255;x++) for(y=0;y<z;y++); } /***********************************************/ /*******************响一声子程序****************/ /***********************************************/ void bbtt() { DDRA|=BIT(1); clr(PORTA,1); delay(250); setb(PORTA,1); delay(250); } /***********************************************/ /*******************显示子程序******************/ /***********************************************/ void xian(uchar shia,uchar fena) { PORTB=table[shia/10];//小时十位 clr(PORTC,3); delay(2); setb(PORTC,3); if(a==0)//如果标志位等于0xff,则关闭小时个位数码管 PORTB=table[shia%10]|0x80;//小时个位 else//否则 PORTB=table[shia%10]&0x7f;//小时个位数码管强行点亮 clr(PORTC,2); delay(2); setb(PORTC,2); PORTB=table[fena/10];//分钟十位 clr(PORTC,1); delay(2); setb(PORTC,1); PORTB=table[fena%10];//分钟个位 clr(PORTC,0); delay(2); setb(PORTC,0); } /***********************************************/ /*****************按键处理子程序****************/ /***********************************************/ void sk() { uchar k;//定义一个变量来存数 DDRD&=0Xf0;//设置PD IO口为输入方式,高4位不管 PORTD|=0X0f;//设置IO口低4位为输入方式且带上拉电阻,即高电平 /***********************************************/ /****************主功能键产生键值***************/ /***********************************************/ if(!get(PIND,0))//如果键值为0则说明有按键按下了 { delay(1);//消抖一下 if(!get(PIND,0))//再次判断一下 { bbtt();//调用铃声 num++;//键值标志加1 a=0x00;//标志位变为0 if(num==4)//如果标志位为4则清0 { num=0; TIMSK|=BIT(2);//打开定时器中断 a=0x00; } } while(!get(PIND,0));//按键松手检测,即如果键值处理程序 为1则说明有键按下, } /***********************************************/ /*****************键值判断控制******************/ /***********************************************/ switch(num) { /*****************如果键值等于1时******************/ case 1: TIMSK&=~BIT(2);//关闭定时器中断 break; /*****************如果键值等于2时******************/ case 2: if(!get(PIND,1))//如果键值为0则说明有按键按下了 { delay(1);//消抖一下 if(!get(PIND,1))//再次判断一下 { bbtt(); shi++;//将小时加1 if(shi==24) shi=0; while(!get(PIND,1));//按键松手检测, 即如果键值处理程序为1则说明有键按下, } } if(!get(PIND,2))//如果键值为0则说明有按键按下了 { delay(1);//消抖一下 if(!get(PIND,2))//再次判断一下 { bbtt(); shi--;//将小时减1 if(shi==(0-1)) shi=23; while(!get(PIND,2));//按键松手检测, 即如果键值处理程序为1则说明有键按下, } } break; /*****************如果键值等于3时******************/ case 3: if(!get(PIND,1))//如果键值为0则说明有按键按下了 { delay(1);//消抖一下 if(!get(PIND,1))//再次判断一下 { bbtt(); fen++;//分钟加1 if(fen==60) shi=59; while(!get(PIND,1));//按键松手检测, 即如果键值处理程序为1则说明有键按下, } } if(!get(PIND,2))//如果键值为0则说明有按键按下了 { delay(1);//消抖一下 if(!get(PIND,2))//再次判断一下 { bbtt(); fen--;//分钟减1 if(fen==(0-1)) shi=59; while(!get(PIND,2));//按键松手检测, 即如果键值处理程序为1则说明有键按下, } } break; } } /***********************************************/ /*******************主程序*********************/ /***********************************************/ void main() { DDRB=0XFF;//设置PA口为输出方式 DDRC|=0x0f;//设置两位为输出方式 TCCR1B=0X04;//设置256分频 6M晶体=6000000/256分频-65535化成16 进制 TCNT1H=0XD2;//给它高位赋值 TCNT1L=0X38;//给它低位赋值 TIMSK|=BIT(2);//打开定时器中断 SREG|=BIT(7);//打开总中断 while(1) { sk();//按键调用 xian(shi,fen);//显示调用 } } /***********************************************/ /*****************中断服务子程序***************/ /***********************************************/ void zhong() { TCNT1H=0XD2;//给它高位赋值 TCNT1L=0X38;//给它低位赋值 miao++;//将变量加1 a=~a;//将标志位取反,小数点闪烁标志位 if(miao==120) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) shi=0; } } }
完整代码下载地址:http://www.51hei.com/f/dzza.rar