电子钟的c语言程序
- 格式:doc
- 大小:45.00 KB
- 文档页数:5
C语言Lcd1602万年历闹钟Proteus仿真单片机毕业课程电子设计
C语言Lcd1602万年历闹钟Proteus仿真单片机设计
AT89C51+Lcd1602+DS1302+独立按键+蜂鸣器
Lcd1602万年历闹钟。
时间信息来自DS1302,显示采用
Lcd1602,蜂鸣器提供闹音和按键提示音。
液晶上面显示年月日时分秒星期以及闹钟时间。
有时间调节和闹钟调节,可以调节年月日时分秒星期信息以及闹钟时间。
具体介绍如下。
1.做好的仿真图,如下图所示。
2.启动仿真后,先在液晶屏显示系统信息,然后在第二屏显示需要的万年历闹钟信息。
如下图所示!
3.通过单片机右侧的三个按键,即可设置闹钟。
如下图所示。
4.通过单片机左侧的四个按键,来设置年月日时分秒星期的值。
设置时,参数闪烁,同时会有按键提示音。
5.本设计默认套餐1,具体套餐详情请看下面的发货清单。
如需要其它套餐,请联系客服询问。
详情请:点击此处。
51单片机c语言电子钟(已加入调时、闹铃、整点报时功能)效果图:程序如下://51单片机c语言电子钟(已加入调时、闹铃、整点报时功能)#include<reg51.h>#include<absacc.h>#define uchar unsigned char#define uint unsigned int/*七段共阴管显示定义*///此表为LED 的字模,共阴数码管0-9 -uchar code dispcode[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //段码控制/*定义并初始化变量*/uchar seconde=0;//秒uchar minite=0;//分uchar hour=12; //时uchar shi=0;//闹铃功能uchar fen=0;uchar bjcs;//报警次数sbit P1_0=P1^0; //second 调整定义sbit P1_1=P1^1; //minite调整定义sbit P1_2=P1^2; //hour调整定义sbit P1_5=P1^5; //整点报时sbit P1_3=P1^3; //闹铃功能,调整时间sbit P1_6=P1^6; //调整时sbit P1_7=P1^7; //调整分sbit P1_4=P1^4; //关闭闹铃/*函数声明*/void delay(uint k ); //延时子程序void time_pro( ); //时间处理子程序void display( ); //显示子程序void keyscan( ); //键盘扫描子程序/*xx子程序*/void delay (uint k){uchar j;while((k--)!=0){for(j=0;j<125;j++){;}}}/*时间处理子程序*/void time_pro(void){if(seconde==60){seconde=0;minite++;if(minite==60){minite=0;hour++;if(hour==24){hour=0;}}}}/*显示子程序*/void display(void){if(P1_3==1){P2=0XFE; P0=dispcode[seconde%10];//秒个位delay(1);P2=0XFD;P0=dispcode[seconde/10];//秒十位delay(1);P2=0XFB;P0=dispcode[10];//间隔符-delay(1);P2=0XF7;P0=dispcode[minite%10];//分个位delay(1);P2=0XEF;P0=dispcode[minite/10];//分十位delay(1);P2=0XDF;P0=dispcode[10];//间隔符-delay(1);P2=0XBF;P0=dispcode[hour%10];//时个位delay(1);P2=0X7F;P0=dispcode[hour/10];//时十位delay(1);}}/*键盘扫描子程序*/void keyscan(void){if(P1_0==0)//秒位的调整{delay (30);if(P1_0==0){seconde++;if(seconde==60){seconde=0;}}delay(250);}if(P1_1==0)//分位的调整{delay(30);if(P1_1==0){minite++;if(minite==60){minite=0;}}delay(250);}if(P1_2==0)//时位的调整{delay(30);if(P1_2==0){hour++;if(hour==24){hour=0;}}delay(250);}}/*整点报警*/void zhengdian (void){if((seconde==0)&(minite==0))//整点报时{P1_5=0;delay(1000);P1_5=1;}}/*定时闹钟*/void dingshi(void){if(P1_3==0)//按住P1_3BU不松,显示闹铃设置界面,分别按P1_6、P1_7设置闹铃时间。
单片机技术课程设计数字电子钟学院:班级:姓名:学号:教师:摘要电子钟在生活中应用非常广泛,而一种简单方便的数字电子钟则更能受到人们的欢迎。
所以设计一个简易数字电子钟很有必要。
本电子钟采用AT89C52单片机为核心,使用12MHz 晶振与单片机AT89C52 相连接,通过软件编程的方法实现以24小时为一个周期,同时8位7段LED数码管(两个四位一体数码管)显示小时、分钟和秒的要求,并在计时过程中具有定时功能,当时间到达提前定好的时间进行蜂鸣报时。
该电子钟设有四个按键KEY1、KEY2、KEY3、KEY4和KEY5键,进行相应的操作就可实现校时、定时、复位功能。
具有时间显示、整点报时、校正等功能。
走时准确、显示直观、运行稳定等优点。
具有极高的推广应用价值。
关键词:电子钟 AT89C52 硬件设计软件设计目录NO TABLE OF CONTENTS ENTRIES FOUND.一、数字电子钟设计任务、功能要求说明及方案介绍1.1 设计课题设计任务设计一个具有特定功能的电子钟。
具有时间显示,并有时间设定,时间调整功能。
1.2 设计课题的功能要求说明设计一个具有特定功能的电子钟。
该电子钟上电或按键复位后能自动显示系统提示符“d.1004-22”,进入时钟准备状态;第一次按电子钟启动/调整键,电子钟从12时59分0秒开始运行,进入时钟运行状态;按电子钟S5键,则电子钟进入时钟调整状态,此时可利用各调整键调整时间,调整结束后可按S5键再次进入时钟运行状态。
1.3 设计课的设计总体方案介绍及工作原理说明本电子钟主要由单片机、键盘、显示接口电路和复位电路构成,设计课题的总体方案如图1所示:图1-1总体设计方案图本电子钟的所有的软件、参数均存放在AT89C52的Flash ROM和内部RAM 中,减少了芯片的使用数量简化了整体电路也降低了整机的工作电流。
键盘采用动态扫描方式。
利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据,同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。
#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]=" 2011-12-30 SA T";uchar code table1[]=" 23:59:55 ";uchar code week1[][3]={"MON","TUE","WEN","THU","FRI","SA T","SUN"}; /*uchar code week2[]="TUE";uchar code week3[]="WEN";uchar code week4[]="THU";uchar code week5[]="FRI";uchar code week6[]="SA T";uchar code week7[]="SUN"; */uchar count,shi,fen,miao,dnum,year,month,day,week,a=5;sbit rs=P2^0; //数据命令sbit rw=P2^1; //读写sbit en=P2^2; //使能sbit d1=P3^1; //独立键盘sbit d2=P3^2;sbit d3=P3^3;sbit d4=P3^4;void delay(uchar z) //延时{uint x,y;for(x=110;x>0;x--)for(y=z;z>0;z--);}void write_com(uchar com) //写指令{rs=0;rw=0;en=0;P0=com;delay(5);en=1;delay(5);en=0;}void write_date(uchar date) //写数据{rs=1;rw=0;en=0;P0=date;delay(5);en=1;delay(5);en=0;}void write_weekday (uchar a){uchar x;write_com(0x80+13);for(x=0;x<3;x++){write_date(week1[a][x]);}}void weekday(uint i){write_weekday(i%7);}void write_sfm(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add); //指向要写的地址write_date(0x30+shi); //0x30代表的数字是0,+shi表示shi的数字write_date(0x30+ge); //ge的数字}void write_ymd(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add); //指向要写的地址write_date(0x30+shi); //0x30代表的数字是0,+shi表示shi的数字write_date(0x30+ge); //ge的数字}void unit(){uchar num;en=0;write_com(0x38); //显示write_com(0x0c); //光标不显示write_com(0x06); //指针加1,整屏不移动write_com(0x01); //清屏write_com(0x80); //指针指向0x80for(num=0;num<16;num++) //第一行显示table数组{write_date(table[num]);delay(20);}write_com(0x80+0x40);for(num=0;num<16;num++) //第二行显示table1数组{write_date(table1[num]);delay(20);}TMOD=0X01;TH0=(65536-50000)/256; //开启中断TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;shi=23;fen=59;miao=55;year=11;month=12;day=30;}void jishu() //计数{if(count==20){count=0;miao++; //秒加if(miao==60){miao=0;fen++; //分加if(fen==60){fen=0;shi++;if(shi==24){shi=0;day++;a++;weekday(a);//时加}write_sfm(3,shi);write_ymd(9,day);if(day==31){day=0x01;write_ymd(9,day);month++;write_ymd(6,month);if(month==13){month=0x01;write_ymd(6,month);year++;write_ymd(3,year);}}}write_sfm(6,fen);}write_sfm(9,miao);}}void change(){d4=0;if(d1==0) //移光标{delay(10);if(d1==0){while(!d1);dnum++;if(dnum==1){TR0=0;write_com(0x0f);write_com(0x80+0x40+10);}if(dnum==2){write_com(0x80+0x40+7);}if(dnum==3){write_com(0x80+0x40+4);}if(dnum==4){write_com(0x80+10);}if(dnum==5){write_com(0x80+7);}if(dnum==6){write_com(0x80+4);}if(dnum==7){dnum=0;TR0=1;write_com(0x0c);}}}if(d2==0) //加数据{delay(10);if(d2==0){while(!d2);if(dnum==1){miao++;if(miao==60)miao=0;write_sfm(9,miao); //顺序不能换write_com(0x80+0x40+10); //顺序不能换}if(dnum==2){fen++;if(fen==60)fen=0;write_sfm(6,fen);write_com(0x80+0x40+7);}if(dnum==3){shi++;if(shi==24){shi=0;}write_sfm(3,shi);write_com(0x80+0x40+4);}if(dnum==4){day++;a++;weekday(a);if(day==31)day=1;write_ymd(9,day);write_com(0x80+10);}if(dnum==5){month++;if(month==13)month=1;write_ymd(6,month);write_com(0x80+7);}if(dnum==6){year++;write_ymd(3,year%100);write_com(0x80+4);}}}if(d3==0) //减数据{delay(10);if(d3==0){while(!d3);if(dnum==1){miao--;if(miao==-1)miao=59;write_sfm(9,miao);write_com(0x80+0x40+10);}if(dnum==2){fen--;if(fen==-1)fen=59;write_sfm(6,fen);write_com(0x80+0x40+7);}if(dnum==3){shi--;if(shi==-1)shi=23;write_sfm(3,shi);write_com(0x80+0x40+4);}if(dnum==4){day--;a--;weekday(a);if(day==0)day=30;write_ymd(9,day);write_com(0x80+10);}if(dnum==5){month--;if(month==0)month=12;write_ymd(6,month);write_com(0x80+7);}if(dnum==6){year--;write_ymd(3,year%100);write_com(0x80+4);}}}}void main(){unit();while(1){jishu();change();}}void timer0()interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;count++;}#include<reg52.h>#define uchar unsigned char //宏定义#define uint unsigned int //宏定义sbit rs=P3^5; //液晶数据/指令选择端:1-数据,0-指令sbit lcden=P3^4; //液晶使能控制端:1-有效,0-无效sbit shift_key=P3^2;//位置移动键sbit up_key=P3^3;//增加键uchar temp=0;//定义定时器溢出计数变量,每隔50ms产生1次溢出,temp加1uint year=2011;//定义年变量并赋初值2011年uchar month=06,day=01,week;//定义月、日、星期变量,并赋初值5月23日uchar hour=23,minute=59,second=58;//定义时、分、秒变量,并赋初值12时00分00秒uchar code week_string[7][4]={"MON","TUE","WED","THU","FRI","SA T","SUN"};//定义星期英文缩写表uchar data month_day[12]={31,0,31,30,31,30,31,31,30,31,30,31};//定义每月天数表/*--定时计数器T0及中断初始化函数--*/void init(void){TMOD=0x01;//设置定时器0为工作方式1TH0=(65536-50000)/256;//16位计数初值除以256得到高8位初值TL0=(65536-50000)%256;//16位计数初值除以256的余数得到低8位初值EA=1;//开总中断ET0=1;//开启定时器0中断EX0=1;//开启外部中断,外部中断用于调整时间PT0=1;//将定时器0中断设置高优先级,调整时间期不停止计时TR0=1;//启动定时器0}/*----------1ms延时函数----------*/void delay(uint n){uint i,j;for(i=n;i>0;i--)for(j=114;j>0;j--);}/*-------LCD1602写指令函数-----*/void LCD1602_write_com(uchar com){rs=0;//rs=0,置指令输入状态P0=com;//输出指令码delay(1);//延时1mslcden=1;//lcden=1,使能端有效delay(1);//延时1mslcden=0;//lcden=0,使能端无效}/*-------LCD1602写数据函数-----*/void LCD1602_write_dat(uchar dat){rs=1;//rs=1,置数据输入状态P0=dat; //输出待显示字符的字符码(ASCII码)delay(1);//延时1mslcden=1;//lcden=1,使能端有效delay(1);//延时1mslcden=0;//lcden=0,使能端无效}/*********************公历平年的2月只有28天,公历闰年的2月有29天。
SD2068低功耗、两线接口、数字时钟调整功能、多种中断/报警系统、12字节用户RAM,并具备多种抗干扰措施下为SD2068 AVR 单片机时钟C程序:#include <iom64v.h>#include <macros.h>#define uchar unsigned char#define uint unsigned int#define ulong unsigned long//数据sda的位设置#define sda_in DDRC &= ~(1 << PC1) //数据设置输入#define sda_out DDRC |= (1 << PC1) //数据设置输出#define sda_setb PORTC |= (1 << PC1) //数据拉高#define sda_clr PORTC &= ~(1 << PC1) //数据拉低#define sda_r PINC & (1 << PC1) //数据读取//时钟scl的位设置#define scl_in DDRC &= ~(1 << PC0) //时钟设置输入#define scl_out DDRC |= (1 << PC0) //时钟设置输出#define scl_setb PORTC |= (1 << PC0) //时钟拉高#define scl_clr PORTC &= ~(1 << PC0) //时钟拉低#define scl_r PINC & (1 << PC0) //时钟读取//===============#define true 1#define false 0//===============uchar date[7]; //日期数组/*date[6]=year,date[5]=month,date[4]=day,date[3]=week,date[2]=hour,date[1]=minute,date[0]=second*/uchar bat1,bat2,temp; //电池电量和温度uint bat; //电池电量值uchar data1[8]; //EEPROM数据//=================================================================== =/*延时子程序*/void delay_ms(uint time) //11.0592M,time=1表示延时1ms {uint i;for(;time>0;time--)for(i=0;i<1571;i++);asm("nop");asm("nop");asm("nop");}void delay_1us(void) //11.0592M, 1us延时函数{asm("nop");}void delay_us(uint time) //11.0592M, Nus延时函数{uint i;for (i=0;i<time;i++)asm("nop");}//=================================================================== ==/********开启SD30系列的I2C总线********/uchar I2CStart(void){sda_out;scl_out;delay_1us();sda_setb;scl_setb;delay_us(5);sda_in;delay_us(5);if(!sda_r)return false; //SDA线为低电平则总线忙,退出sda_out;delay_1us();sda_clr;delay_us(10);sda_in;delay_us(10);while(sda_r)return false; //SDA线为高电平则总线出错,退出scl_clr;delay_us(5);return true;}//********关闭SD30系列的I2C总线****// void I2CStop(void){scl_out;sda_out;delay_1us();sda_clr;delay_1us();scl_clr;delay_us(5);scl_setb;delay_us(2);sda_setb;}//*********发送 ACK****//void I2CAck(void){scl_out;sda_out;delay_1us();sda_clr;delay_1us();scl_clr;delay_us(5);scl_setb;delay_us(5);scl_clr;}/*********发送NO ACK*********/void I2CNoAck(void){scl_out;sda_out;delay_1us();sda_setb;delay_1us();scl_clr;delay_us(5);scl_setb;delay_us(5);scl_clr;}//*********读取ACK信号*********uchar I2CWaitAck(void) //返回为:1=有ACK,0=无ACK{uchar errtime=255;scl_out;sda_in;delay_1us();scl_clr;delay_us(5);scl_setb;delay_1us();sda_in;delay_1us();while(sda_r){errtime--;delay_1us();if(!errtime){delay_us(10);scl_clr;return false;}}scl_clr;return true;}/************MCU向SD30系列发送一个字节*************/void I2CSendByte(uchar demand) //数据从高位到低位{uchar bd=8;sda_out;scl_out;while(bd--){scl_clr;delay_1us;if(demand&0x80){sda_setb;}else{sda_clr;}demand<<=1;delay_us(3);scl_setb;delay_us(3);}scl_clr;}/*********MCU从SD30系列读入一字节*********/uchar I2CReceiveByte(void) //数据从高位到低位//{uchar bl=8;uchar ddata=0;scl_out;delay_1us();delay_1us();sda_in; //端口切换为输入状态!!sda_setb; //有的单片机需要加这句,如果不需要可以删掉delay_1us();while(bl--){ddata<<=1; //数据从高位开始读取delay_1us();scl_clr;delay_us(5); //从高位开始ddata|=SDA;ddata<<=1scl_setb;delay_us(5);if(sda_r){ddata|=0x01;}}scl_clr;return ddata;}/******读SD30系列实时数据寄存器******/char I2CReadDate(void){uchar n;if(!I2CStart())return false;I2CSendByte(0x65);if(!I2CWaitAck()){I2CStop(); return false;}for(n=0;n<7;n++){date[n]=I2CReceiveByte();if (n!=6) //最后一个数据不应答{I2CAck();}}I2CNoAck();I2CStop();}/******写SD30系列实时数据寄存器******/char I2CWriteDate(void) // 设置时间:2013年2月2日 07:59:55 星期一。
/*这是一个真正有意义的时钟key1功能键选择可调位,短按,每按一下有一位闪烁长按闪烁不断向下一位推移key2 加键短按相应闪烁的位加1,长按连续加1;key3 减键短按相应闪烁的位减1,长按连续减一;key4 确定键按下退出调时,正常显示;*/#include<reg52.h>#define uint unsigned int#define uchar unsigned char#define LED P0#define KEY_1 0x0e#define KEY_2 0x0d#define KEY_3 0x0b#define KEY_4 0x07#define KEY_NULL 0x0f#define KEY_PRESS 0x80#define KEY_LONG 0x40#define KEY_STATE_INIT 0#define KEY_STATE_PRESS 1#define KEY_STATE_LONG 2#define KEY_STATE_UP 3#define KEY_LONG_PERIOD 20#define KEY_CONTINUE_PERIOD 10bit set;bit dao1S=0;bit dao2MS=0;bit dao10MS;sbit dula=P2^6;sbit wela=P2^7;sbit key1=P3^4;sbit key2=P3^5;sbit key3=P3^6;sbit key4=P3^7;int main_flag,exit_flag,up_flag,down_flag;int tab[]={0,0,0,0,0,0};uchar weitable[]={0x01,0x02,0x04,0x08,0x10,0x20};uchar tab1[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; void nint(){ TMOD=0X01;TH0=0XF8;TL0=0XCC;TR0=1;ET0=1;}uchar KeyScan(){if(key1==0) return KEY_1;if(key2==0) return KEY_2;if(key3==0) return KEY_3;if(key4==0) return KEY_4;return KEY_NULL;}uchar GetKey(){uchar keyRetu=0,keyTemp=KEY_NULL;static uchar s_keyState=KEY_STATE_INIT,keyTime=0,keyLast=KEY_NULL;keyTemp=KeyScan();switch (s_keyState){case KEY_STA TE_INIT:if(keyTemp!=KEY_NULL){s_keyState=KEY_STA TE_PRESS;}break;case KEY_STA TE_PRESS:if(keyTemp!=KEY_NULL){s_keyState=KEY_STA TE_LONG;keyTime=0;keyLast=keyTemp;}else{s_keyState=KEY_STA TE_INIT;}break;case KEY_STA TE_LONG:if(keyTemp==KEY_NULL){s_keyState=KEY_STA TE_INIT;keyRetu=(keyLast|KEY_PRESS);}else{if(++keyTime>=KEY_LONG_PERIOD) //按下时间>1s{s_keyState=KEY_STATE_UP;keyTime=0;}}break;case KEY_STA TE_UP:if(keyTemp==KEY_NULL){s_keyState=KEY_STA TE_INIT;}else{if(++keyTime>=KEY_CONTINUE_PERIOD) //按下时间>0.5s {keyTime=0;keyRetu=(keyLast|KEY_LONG);}}break;}return keyRetu;}void updatetime(){if(dao1S){dao1S=0;if(++tab[5]==10){ tab[5]=0;if(++tab[4]==6){tab[4]=0;if(++tab[3]==10){ tab[3]=0;if(++tab[2]==6){ tab[2]=0;if(tab[0]<2){if(++tab[1]==10){ tab[1]=0;tab[0]++;}}else{ if(tab[1]==4){ tab[1]=0;tab[0]=0;}} }}}}}}void display(){ static uchar k=0;dula=1;LED=tab1[tab[k]];if(set&&((k==main_flag-1))){LED=0XFF;}dula=0;LED=0Xff;wela=1;LED=weitable[k];wela=0;if(++k>5) k=0;}void sittime(uchar hour,uchar minute,uchar second ) { uchar a1,a2,b1,b2,c1,c2;a1=hour/10;a2=hour%10;b1=minute/10;b2=minute%10;c1=second/10;c2=second%10;tab[0]=a1;tab[1]=a2;tab[2]=b1;tab[3]=b2;tab[4]=c1;tab[5]=c2;}void main(){ nint();EA=1;sittime(15,20,15);while(1){updatetime();if(dao2MS){dao2MS=0;display();}if(dao10MS){dao10MS=0;switch (GetKey()){case (KEY_1|KEY_PRESS):if(++main_flag>=7)main_flag=0;break;case (KEY_1|KEY_LONG):if(++main_flag>=7)main_flag=0;break;case (KEY_2|KEY_PRESS):switch(main_flag){case 1:{if(++tab[0]>=3)tab[0]=0;}break;case 2:{if(++tab[1]>4)tab[1]=0;}break;case 3:{if(++tab[2]>5)tab[2]=0;}break;case 4:{if(++tab[3]>9)tab[3]=0;}break;case 5:{if(++tab[4]>5)tab[4]=0;}break;case 6:if(++tab[5]>9)tab[5]=0;}break;case (KEY_2|KEY_LONG): switch(main_flag) {case 1:{if(++tab[0]>=3)tab[0]=0;}break;case 2:{if(++tab[1]>4)tab[1]=0;}break;case 3:{if(++tab[2]>5)tab[2]=0;}break;case 4:{if(++tab[3]>9)tab[3]=0;}break;case 5:{if(++tab[4]>5)tab[4]=0;}break;case 6:if(++tab[5]>9)tab[5]=0;}break;case (KEY_3|KEY_PRESS):switch(main_flag){case 1:{if(--tab[0]<0)tab[0]=2;}break;case 2:{if(--tab[1]<0)tab[1]=4;}break;case 3:{if(--tab[2]<0)tab[2]=5;}break;case 4:{if(--tab[3]<0)tab[3]=9;}break;case 5:{if(--tab[4]<0)tab[4]=5;}break;case 6:if(--tab[5]<0)tab[5]=9;}break;case (KEY_3|KEY_LONG): switch(main_flag){case 1:{if(--tab[0]<0)tab[0]=2;}break;case 2:{if(--tab[1]<0)tab[1]=4;}break;case 3:{if(--tab[2]<0)tab[2]=5;}break;case 4:{if(--tab[3]<0)tab[3]=9;}break;case 5:{if(--tab[4]<0)tab[4]=5;}break;case 6:if(--tab[5]<0)tab[5]=9;}break;case (KEY_4|KEY_PRESS):main_flag=0;display();}}}}void timer() interrupt 1{ static count=0;static count1=0;TH0=0XF8;TL0=0XCC;dao2MS=1;count++;if(++count1==10){ c ount1=0;dao10MS=1;}if(!(count%25)) set = !set;if(count==500) {count=0;dao1S=1; }}。
#include <reg52.h>
#include <ABSACC.H>
#include <intrins.h>
void display();
void timego1();
void timego();
void keyscan();
void delay(int);
char count=20,count1=7;
bit keyflag;
bit flaflag=1;
char keysbuf,avonum=0;
char setflag=5;
char xian[5]={0}; //初始时间
code zixing[21]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00}; void main()
{
EA=1;
TMOD=0x11; /*定时器方式*/ TH0=15536/256; /*50毫秒定时初值*/
TL0=15536%256;
TH1=5536/256; /*60毫秒定时初值*/
TL1=5536%256;
ET0=1; /*总中断允许*/
ET1=1;
TR1=0;
TR0=1; /*定时器0运行*/
while(1)
{
if(avonum>0) /*防止键盘重复读取*/
avonum--;
if(avonum==0) /*满足条件*/
{
keyscan(); /*键盘扫描*/
if(keyflag==1) /*键盘有按键*/
{
keyflag=0; /*标志位清除*/
if(keysbuf==0) /*键值为0*/
{if(setflag==0)//调时标志为0的话
{setflag=5;
TR0=1; //
TR1=0;
flaflag=1;
}
else
{setflag--;
TR0=0;
TR1=1;
}
}
if(keysbuf==1&&(setflag!=5)&&(setflag==3||setflag==5))
if(xian[setflag]<9) //判断分位
xian[setflag]++;
else
xian[setflag]=0;
if(keysbuf==1&&(setflag!=5)&&(setflag==4||setflag==2))
if(xian[setflag]<5) //判断分位
xian[setflag]++;
else
xian[setflag]=0;
if(keysbuf==1&&(setflag!=5)&&(setflag==0))
if((xian[0]==1&&xian[1]<4)||xian[0]==0) //判断分位
xian[0]++;
else
xian[0]=0;
if(keysbuf==1&&(setflag!=5)&&(setflag==1)) if(((xian[0]<2)&&xian[1]<9)||((xian[0]==2)&&(xian[1]<3)))
xian[1]++;
else
xian[1]=0;
if(keysbuf==2&&(setflag!=5)&&(setflag==3||setflag==5))
if(xian[setflag]>0) //判断分位
xian[setflag]--;
else
xian[setflag]=9;
if(keysbuf==2&&(setflag!=5)&&(setflag==4||setflag==2))
if(xian[setflag]>0) //判断分位
xian[setflag]--;
else
xian[setflag]=5;
if(keysbuf==2&&(setflag!=5)&&(setflag==0))
if(xian[0]>0) //判断分位
xian[0]--;
else
{
if(xian[1]>3)
xian[0]=2;
else xian[0]=1;
}
if(keysbuf==2&&(setflag!=5)&&(setflag==1))
if(xian[1]>0)
xian[1]--;
else
{if(xian[0]<2)
xian[1]=9;
if(xian[0]==2)
xian[1]=3;
}
avonum=50;
}
}
display();
}
}
void display()
{
char i,a,b,ziwei=0;
for(i=0;i<6;i++)
{
if(i==setflag&&flaflag==0)
a=20;
else
a=xian[i]; /*取显示值*/
b=P1; /*取p1口值*/
b=b&0x1f; /*屏蔽高三位*/
b+=ziwei; /*加片选码*/
P0=zixing[a]; /*字型送p0口*/
P1=b; /*片选送p1口*/
ziwei+=0x20
; /*片选移位*/
delay(50); /*延时*/
}
}
void delay(int a) //延时子函数
{int i;
for(i=0;i<a;i++)
_nop_();
}
void timego() interrupt 1 using 2 //T0中断子函数
{
TR0=0; //关定时器
TH0=15536/256; //重设初值
TL0=15536%256;
TR0=1; //开定时器
count--; //计数减一
if(count) //判断计数
_nop_();
else //延时够1s
{count=20; //重置计数
if(xian[5]<9) //判断秒位
xian[5]++; //小于9直接加1
else
{xian[5]=0; //秒位清零
if(xian[4]<5) //判断十秒位
xian[4]++; //小于5直接加1
else
{xian[4]=0; //十秒位清零
if(xian[3]<9) //判断分位
xian[3]++;
else
{xian[3]=0;
if(xian[2]<5)
xian[2]++;
else
{xian[2]=0;
if(((xian[0]<2)&&xian[1]<9)||((xian[0]==2)&&(xian[1]<3)))
xian[1]++;
else
{xian[1]=0;
if(xian[0]<2)
xian[0]=xian[0]+1;
else
xian[0]=0;
}
}
}
}
}
}
}
void keyscan()
{
char lnum,rnum;
P2=0x0f;
keyflag=0;
if((P2&0x0f)!=0x0f)
{
delay(100); //消抖
if((P2&0x0f)!=0x0f)
{
{
if(P2==0x0e)
rnum=0;
if(P2==0x0d)
rnum=1;
if(P2==0x0b)
rnum=2;
if(P2==0x07)
rnum=3;
}
P2=0xf0;
if((P2&0xf0)!=0xf0)
{
if(P2==0xe0)
lnum=0;
if(P2==0xd0)
lnum=1;
if(P2==0xb0)
lnum=2;
if(P2==0x70)
lnum=3;
keyflag=1;
keysbuf=rnum*4+lnum;
}
}
}
}
void timego1() interrupt 3 //T0中断子函数{
TR1=0; //关定时器TH0=5536/256; //重设初值TL0=5536%256;
TR1=1; //开定时器count1--; //计数减一
if(count1) //判断计数
_nop_();
else
{
count1=7;
flaflag=!flaflag;
}
}。