- #include <reg52.h>
- //宏定義
- #define uc unsigned char
- #define ui unsigned int
- void display(); //聲明顯示函數
- uc code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //數字對應顯示碼表
- uc code tab1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};//帶小數點的數字碼表
- uc code index[]={0xef,0xdf,0xbf,0x7f}; //每位數字對應數碼管顯示位置
- uc num[8]; //num【0】-num【3】是計時用數組,4-7是范圍計時用(設置10s,計時到10秒報警)
- uc val[10][4]; //存儲的記錄 [10]為記錄序列,[4]為每組記錄中的數字
- char val_index;//記錄序列標志位
- uc set_index,ok_flag,timing; //set_index:設置的位。ok_flag:設置狀態標志,=0時是正常狀態,=1是設置狀態。timing:顯示狀態標志:=0正常顯示,=1閃爍設置位
- bit mode=1;//運行模式,1為正向計數,0為反向計數。
- bit fin_flag=0;//完成標志位,當反向計數結束時,此位為高電平,觸發蜂鳴器
- bit set_shan;
- sbit beep=P3^2; //蜂鳴器
- sbit key1=P3^3; //開始停止計時數據
- sbit key2=P3^4; //記錄按鈕/設置位置加
- sbit key3=P3^5; //復位
- sbit key4=P3^6; //模式切換
- sbit key5=P3^7; //設置按鈕
- void delay(ui z) //延時函數,大約延時z ms
- {
- ui i,j;
- for(i=0;i<z;i++)
- for(j=0;j<121;j++);
- }
- void init() //初始化
- {
- TMOD=0x11; //工作方式
- TH0=0x3c;
- TL0=0xb0; //定時器0賦初值
- TH1=0x3c;
- TL1=0xb0; //定時器1賦初值
- ET1=1; //允許中斷
- TR1=1; //定時開關
- ET0=1;
- TR0=0;
- EA=1; //中斷總開關
- val_index=0; //清零
- }
- void clr() //清除函數
- {
- uc i;
- for(i=0;i<8;i++) //將存儲的數據清零 for循環8次
- num[i]=0;
- }
- void setup() //設置函數
- {
- ok_flag=0xff; //ok_flag賦值1
- set_index=0; //設置位置0
- while (ok_flag) //進入設置后,循環,直到ok_flag為0
- {
- display(); //調用顯示函數
- if(key1==0) //按動KEY1設置值加1
- {
- delay(5); //延時去抖
- if(key1==0)//再次判斷按鍵是否按下
- {
- if ((set_index==0)|(set_index==2)|(set_index==4)|(set_index==6))//設置個位數據時
- {
- num[set_index]++; //數據加
- if(num[set_index]==10) //加到10
- num[set_index]=0; //清零
- }
- else if((set_index==1)|(set_index==3)|(set_index==5)|(set_index==7))//設置十位數據時
- {
- num[set_index]++; //數據加
- if(num[set_index]==6) //加到6時
- num[set_index]=0; //清零
- }
- while(!key1) display(); //按鍵釋放
- }
- }
- if(key2==0) //按動KEY2設置位置加1
- {
- delay(5);//延時去抖
- if(key2==0)//再次按下按鍵
- {
- set_index++; //設置位置加
- if(set_index==8) //設置位置加到最后一位時
- {
- set_index=0; //設置位置到0
- }
- while(!key2) display(); //按鍵釋放
- }
- }
- if(key5==0) //按動KEY5設置結束
- {
- delay(5);//延時去抖
- if(key5==0)//再次判斷按鍵是否按下
- {
- ok_flag=0x00; //ok_flag清零
- if((num[4]!=0)||(num[5]!=0)||(num[6]!=0)||(num[7]!=0)) //如果計時時間上限設置數據不都為0時
- {
- num[0]=0;num[1]=0;num[2]=0;num[3]=0;mode=1;//將正計時時間清零,Mode置1,正計時
- }
- else if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0))//如果計時時間上限設置數據都為0時
- {
- if((num[0]==0)&&(num[1]==0)&&(num[2]==0)&&(num[3]==0))//判斷計時時間都為0
- mode=1; //正計時模式
- else if((num[0]!=0)||(num[1]!=0)||(num[2]!=0)||(num[3]!=0))//判斷計時時間有不為0
- mode=0; //倒計時模式
- }
- while(!key5) display(); //按鍵去抖
- }
- }
- }
- }
- void display()
- {
- uc i;
- if(ok_flag!=0xff) //不是設置狀態時
- {
- if(timing==0)
- {
- for(i=0;i<4;i++)
- {
- P0=0xff; //清顯示
- P2=index[i]; //選中位
- if(i==2) //如果是第二位時
- P0=tab1[num[i]]; //顯示有小數點的數據
- else //不是第二位時
- P0=tab[num[i]]; //正常顯示數據
- delay(2); //修改此參數可修改刷新頻率
- }
- }
- else //設置時 閃爍相應位
- {
- if(set_shan==0)
- {
- for(i=0;i<4;i++)
- {
- P0=0xff;
- P2=index[i];
- P0=tab[10]; //熄滅
- delay(2); //修改此參數可修改刷新頻率
- }
- }
- else if(set_shan==1)
- { //點亮顯示
- for(i=0;i<4;i++)
- {
- P0=0xff;
- P2=index[i];
- if(i==2)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- }
- }
- }
- }
- else //設置時
- {
- if(set_shan==0)
- {
- if(set_index==0) //設置不同位時,閃爍相應位
- {
- for(i=0;i<4;i++)
- {
- if(i==0)
- {
- P2=index[0];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i];
- if(i==2)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==1)
- {
- for (i=0;i<4;i++)
- {
- if(i==1)
- {
- P2=index[1];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i];
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==2)
- {
- for (i=0;i<4;i++)
- {
- if(i==2)
- {
- P2=index[2];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i];
- if(i==2)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==3)
- {
- for (i=0;i<4;i++)
- {
- if(i==3)
- {
- P2=index[3];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i];
- if(i==2)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==4)
- {
- for (i=4;i<8;i++)
- {
- if(i==4)
- {
- P2=index[0];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i-4];
- if(i==6)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==5)
- {
- for (i=4;i<8;i++)
- {
- if(i==5)
- {
- P2=index[1];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i-4];
- if(i==6)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==6)
- {
- for (i=4;i<8;i++)
- {
- if(i==6)
- {
- P2=index[2];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i-4];
- if(i==6)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- else if(set_index==7)
- {
- for (i=4;i<8;i++)
- {
- if(i==7)
- {
- P2=index[3];
- P0=tab[10];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- else
- {
- P2=index[i-4];
- if(i==6)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- }
- else
- {
- if(set_index<4)
- {
- for (i=0;i<4;i++)
- {
- P2=index[i];
- if(i==2)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- else
- {
- for (i=4;i<8;i++)
- {
- P2=index[i-4];
- if(i==6)
- P0=tab1[num[i]];
- else
- P0=tab[num[i]];
- delay(2); //修改此參數可修改刷新頻率
- P0=0xff;
- }
- }
- }
- }
- }
- void alarm()
- {
- if((num[4]==0)&&(num[5]==0)&&(num[6]==0)&&(num[7]==0)) //計時時間到0時
- {timing=0;} //開始報警
- else
- {
- if((num[4]==num[0])&&(num[6]==num[2])&&(num[5]==num[1])&&(num[7]==num[3])) //設置上限模式時,計時時間到
- {timing=1;TR0=0;} //停止計時,并閃爍顯示
- }
- }
- void main()
- {
- uc h,g,k;
- init();
- clr();
- while(1)
- {
- display(); //刷屏顯示數碼管
- alarm();
- if(key1==0) //開始/暫停按鈕
- {
- delay(5);
- if(key1==0)
- {
- TR0=~TR0;
- while(!key1) display();
- }
- }
- if(key2==0) //記錄按鈕
- {
- delay(5);
- if(key2==0)
- {
- if(TR0==1) //當在運行中按下記錄鍵則存儲記錄
- {
- for(g=1;g<10;g++)
- {
- for(k=0;k<4;k++)
- {
- val[g-1][k]=val[g][k]; //低位存儲的數據向高位移一位
- }
- }
- for(h=0;h<4;h++)
- {
- val[9][h]=num[h]; //將當前時間存儲
- }
- }
- else //在停止狀態下按下記錄鍵查看記錄,按動一次序列遞減一次,即查看上一次記錄
- {
- for(h=0;h<4;h++)
- num[h]=val[val_index][h]; //將當前時間存儲
- val_index--;
- if(val_index<0)
- val_index=9;
- }
- while(!key2) display(); //按鍵釋放
- }
- }
- if(key3==0) //復位按鈕
- {
- delay(5);
- if(key3==0)
- {
- clr(); //將數據清零
- while(!key3) display(); //按鍵釋放
- }
- }
- if((key4==0)&&(TR0==0)) / /模式選擇按鈕,僅在停止狀態下有效
- {
- delay(5);
- if(key4==0)
- {
- mode=~mode; //正計時倒計時切換
- while(!key4) display();
- }
- }
- if((key5==0)&&(TR0==0)) //時間設置,僅在停止狀態下有效
- {
- delay(5);
- if(key5==0)
- {
- while(!key5)
- display();
- setup(); //調用設置函數
- }
- }
- }
- }
- void T0_time() interrupt 1
- {
- uc m;
- TH0=0x3c; //12M晶振定時器定時時間為50ms
- TL0=0xb0;
- m++;
- if(m==20)
- {
- m=0;
- if(mode==1) //正向計數
- {
- num[0]++; //秒個位加
- if(num[0]==10) //秒個位加到10時
- {
- num[0]=0; //個位清零
- num[1]++; //秒十位加
- if(num[1]==6) //秒十位加到6時
- {
- num[1]=0; //秒十位清零
- num[2]++; //分個位加
- if(num[2]==10) //分個位加到10時
- {
- num[2]=0; //分個位清零
- num[3]++; //分十位加
- if(num[3]==10)//分十位加到10時
- num[3]=0; //分十位清零
- }
- }
- }
- }
- else
- {
- num[0]--; //秒個位減
- if(num[0]>9) //小于0時,該數字的最高位會變1,所以判斷是否大于9 下同
- {
- num[0]=9;
- num[1]--;
- if(num[1]>5)
- {
- num[1]=5;
- num[2]--;
- if(num[2]>9)
- {
- num[2]=9;
- num[3]--;
- if(num[3]>9)
- {
- num[3]=0;
- TR0=0;
- fin_flag=1;
- clr();
- }
- }
- }
- }
- }
- }
- }
- void T1_time() interrupt 3 //定時器1的工作函數
- {
- uc shan,beep_stop;
- TH1=0x3c;
- TL1=0xb0; //重新賦初值
- shan++; //閃爍變量加
- if(shan==10) //加到10時(500ms)
- {
- shan=0; //清零
- set_shan=~set_shan; //設置的閃爍變量取反
- if((fin_flag)||(timing)) //當反向計數完成時 或計時時間到時
- {
- beep_stop++;
- beep=~beep; //蜂鳴器閃爍響
- if(beep_stop==10) //蜂鳴器響五聲停止
- {
- fin_flag=0;
- timing=0;
- num[4]=0;num[5]=0;num[6]=0;num[7]=0;
- beep_stop=0;
- beep=1;
- }
- }
- }
- }
復制代碼 |