本帖最后由 努力努力在努力z 于 2019-7-8 22:58 编辑
#include<AT89x52.h> #define uchar unsigned char #define uint unsigned int void display();//显示时间子函数 void display1();//显示倒计时时间子函数 void disp(); //显示呼叫病床总数及当前呼叫病床子函数 void Time0() ; //定时中断子函数,用于改变时间参数 void Time1() ; void rest(); // 初始化子函数,用于病床复位后 uchar codeDSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0xc6,0xa1,0x86,0x8e,0x00}; //共阴极数码管显示段码 sbit P36=P3^6; //接蜂鸣器 sbit P37=P3^7; //病床复位按键 void DelayMS(uint x) //延时子函数 { uchar y; while(x--) for(y=0;y<120;y++); } uchar d[8]={0,0,0,0,0,0,0,0}; //用于存放呼叫病床的显示段码 uchar g=0,j=0,log=0,CEN=0; //下面有详细说明 void rest() // 初始化子函数,用于病床复位后 { g=0; //g计数:要显示的呼叫病床个数 log=0; //病床呼叫标志位,有人呼叫置1 P36=0; //接蜂鸣器,高电平响 CEN=0; //当前显示的病床号在数组d中的偏移量 for(j=0;j<8;j++) //清空数组d d[j]=0; } ucharhour=0,min=0,secon=0,tim0=0,hour1=0,min1=0,secon1=0,tim1=0;//时分秒的计数参数 uchar watch=0,t,KeyNo;//watch倒计时秒表标志位,KeyNo保存键号 void Keys_Scan()//4*4键盘扫描得到按键号即床号:0~7存于KeyNo中,8~15号用于时间调整 { uchar temp; P1=0xfe; temp=P1; if(temp!=0xfe) { log=1; //病床呼叫标志 P36=1; //只要有病床呼叫蜂鸣器便发出响声 DelayMS(10); //延时 P36=0; //关蜂鸣器 switch(temp) { case 0xee: KeyNo=0;break; case 0xde: KeyNo=1;break; case 0xbe: KeyNo=2;break; case 0x7e: KeyNo=3;break; } } P1=0xfd; temp=P1; if(temp!=0xfd) { log=1; //病床呼叫标志 P36=1; //只要有键按下就开蜂鸣器 DelayMS(10); //延时 P36=0; //关蜂鸣器 switch(temp) { case 0xed: KeyNo=4;break; case 0xdd: KeyNo=5;break; case 0xbd: KeyNo=6;break; case 0x7d: KeyNo=7;break; } } P1=0xfb; temp=P1; if(temp!=0xfb&&g==0) //无人呼叫时才能进行时间调整 switch(temp) { case 0xeb: KeyNo=8; if(watch!=0) t=secon1; else t=secon; if(++t>=60)t=0; if(watch!=0) secon1=t; else secon=t; break; case 0xdb: KeyNo=9; if(watch!=0) t=min1; else t=min; if(++t>=60)t=0; if(watch!=0) min1=t; else min=t; break; case 0xbb: KeyNo=10; if(watch!=0) t=hour1; else t=hour; if(++t>=60)t=0; if(watch!=0) hour1=t; else hour=t; break; case 0x7b: KeyNo=11;TR0=~TR0;break; //暂停计时 } P1=0xf7; temp=P1; if(temp!=0xf7&&g==0) switch(temp) { case 0xe7: KeyNo=12; if(watch!=0) t=secon1; else t=secon; if(t--==0)t=59; if(watch!=0) secon1=t; else secon=t; break; case 0xd7: KeyNo=13; if(watch!=0) t=min1; else t=min; if(t--==0)t=59; if(watch!=0) min1=t; else min=t; break; case 0xb7: KeyNo=14; if(watch!=0) t=hour1; else t=hour; if(t--==0)t=59; if(watch!=0) hour1=t; else hour=t; break; case 0x77: KeyNo=15;watch++; //倒计时watch=1设定倒计时时间, if(watch==2) TR1=1; //watch=2开始计时 if(watch==3) { watch=0; TR1=0; } break; } //等待按键松开 P1=0X0f; temp=P1; while(temp!=0x0f) { P1=0X0f; temp=P1; if(log==1)//当前按键为病床按键 disp(); //显示病床号及呼叫总数 else if(watch==0) //当前按键为时间调整按键且无人呼叫 display(); //显示时间 else display1(); //当前按键为倒计时时间调整按键且无人呼叫 } } void display() //显示时间函数 { P0=0xfe; P2=DSY_CODE[hour/10]; DelayMS(1); P0=0xfd; P2=DSY_CODE[hour%10]; DelayMS(1); P0=0xfb; P2=DSY_CODE[min/10]; DelayMS(1); P0=0xf7; P2=DSY_CODE[min%10]; DelayMS(1); P0=0xef; P2=DSY_CODE[secon/10]; DelayMS(1); P0=0xdf; P2=DSY_CODE[secon%10]; DelayMS(1); } void display1() //倒计时显示时间函数 { P0=0xfe; P2=DSY_CODE[hour1/10]; DelayMS(1); P0=0xfd; P2=DSY_CODE[hour1%10]; DelayMS(1); P0=0xfb; P2=DSY_CODE[min1/10]; DelayMS(1); P0=0xf7; P2=DSY_CODE[min1%10]; DelayMS(1); P0=0xef; P2=DSY_CODE[secon1/10]; DelayMS(1); P0=0xdf; P2=DSY_CODE[secon1%10]; DelayMS(1); } void disp() //显示呼叫病床总数及当前呼叫病床 { DelayMS(1); P0=0xfe; P2=DSY_CODE[g]; //显示当前呼叫病床总数 DelayMS(1); P0=0xfd; P2=d[CEN];//显示当前床号,CEN的值在定时中断中发生发生改变,实现一秒的闪烁显示,精华之处 DelayMS(1); } void main() //主程序 { TMOD=0x00; //定时器T0方式0 TH0=(8192-4000)/32; //计时250*4ms=1s TL0=(8192-4000)%32; TH1=(8192-5000)/32; //计时250*4ms=1s TL1=(8192-5000)%32; IE=0x8a; //开T0,T1中断 PX1=1; TR1=0; //关T1 TR0=1; //初始化完毕 while(1) //主程序在此处循环 { if(g!=0) //有人呼叫时,显示病床号 disp(); else if(watch==0)//无人呼叫时,显示时、分、秒 display(); else //无人呼叫显示倒计时 display1(); //判断是否有病床呼叫 P1=0xf0; if(P1!=0xf0) { Keys_Scan(); //有呼叫则求得床号 for(j=0;j<8;j++) //判断是否是重复按键若是则不再保存本次床号 if(DSY_CODE[KeyNo]==d[j]) { j=8; log=0; } if(log==1) { g++; if(g==9)g=0; switch(g) { case 1: d[0]=DSY_CODE[KeyNo];break; case 2: d[1]=DSY_CODE[KeyNo];break; case 3: d[2]=DSY_CODE[KeyNo];break; case 4: d[3]=DSY_CODE[KeyNo];break; case 5: d[4]=DSY_CODE[KeyNo];break; case 6: d[5]=DSY_CODE[KeyNo];break; case 7: d[6]=DSY_CODE[KeyNo];break; case 8: d[7]=DSY_CODE[KeyNo];break; } } } if(P37==0) //按下病床复位键 rest(); } } void Time0() interrupt 1 //显示时间 { TH0=(8192-4000)/32; //恢复初值 TL0=(8192-4000)%32; if(d[CEN]==0)CEN=0; //精华所在之处,非常巧妙 if(++tim0!=250) return; tim0=0; CEN++; if(CEN==8)CEN=0; secon++; if(secon==60) { secon=0; min++; if(min==60) { min=0; hour++; if(hour==24)hour=0; } } } void Time1() interrupt 3 //倒计时秒表 { TH1=(8192-5000)/32; //初值重装 TL1=(8192-5000)%32; if(++tim1!=2) return; //计时10ms tim1=0; if(secon1!=0) //秒针调整,此if与下面的两个else if语句能且只能执行其中的一个 secon1--; else if(hour1!=0) //秒针等于0,时针不为0 { secon1=99; min1--; if(min1>=60) { min1=59; hour1--; if(hour1==0) hour1=0; } } else if(min1!=0) //秒针,时针都为0,分针不为0 { secon1=99; min1--; } if(hour1==0&&min1==0&&secon1==0) TR1=0; }
|