在主程序中,先使能全局中斷,然后使能74HC245來控制數碼管。配置定時器0工作在模式1并設置定時初值1ms,清零TF位,使能定時器0并啟動定時器0。按鍵動作函數keys進行按鍵消抖。進入中斷后,不斷掃描按鍵動作,并在中斷中完成隊伍比分、倒計時和蜂鳴器的顯示。最后while(1)循環中調用按鍵掃描掃描函數Keys、 600s和24s倒計時, 檢測一次按鍵狀態,如果在連續的8次移位檢測中按鍵狀態保持不變,則判定為按鍵已動作,顯示相應的數碼管動態。主程序流程圖如圖6所示:
51hei.png (10.5 KB, 下載次數: 47)
下載附件
2019-12-15 01:09 上傳
圖6 主程序流程圖
3.2蜂鳴器子程序設計
在中斷子程序中,對蜂鳴器函數進行調用,并判斷600s和24s函數中sec是否為0。當十分鐘倒計未結束的時候,蜂鳴器不工作,當十分鐘倒計時結束的時候,蜂鳴器發出響聲。蜂鳴器電路流程圖如圖6所示:
51hei.png (15.59 KB, 下載次數: 42)
下載附件
2019-12-15 01:10 上傳
圖7 蜂鳴器電路
3.3按鍵動作子程序設計
在中斷中完成按鍵掃描并消抖,主程序調用按鍵動作函數。如果檢測到按鍵1按下,給k賦值1;如果檢測到按鍵2按下,給k賦值2;如果檢測到按鍵3按下,給k賦值3;如果檢測到按鍵4按下,給k賦值4;如果檢測到按鍵5按下,給k賦值5;如果檢測到按鍵6按下,給k賦值6;如果檢測到按鍵7按下,給k賦值7;如果檢測到按鍵8按下,給k賦值8;如果檢測到按鍵9按下,給k賦值9;如果檢測到按鍵10按下,給k賦值10。按鍵動作函數流程圖如圖8所示:
51hei.png (33.96 KB, 下載次數: 35)
下載附件
2019-12-15 01:09 上傳
圖8 按鍵動作函數流程圖
3.4中斷子程序設計
中斷子程序中,通過定時器T0調用數碼管動態刷新函數、矩陣按鍵掃描函數以及蜂鳴器函數。中斷1000次即一秒,當達到一秒時,清零計數值以重新開始下一個一秒計時,同時設置一秒定時器標志為1。定時器中斷流程圖如圖9所示:
單片機源程序如下:
- #include<reg52.h>
-
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit KEY_OUT_1 = P2^3;
- sbit KEY_OUT_2 = P2^2;
- sbit KEY_OUT_3 = P2^1;
- sbit KEY_OUT_4 = P2^0;
- sbit KEY_IN_1 = P2^4;
- sbit KEY_IN_2 = P2^5;
- sbit KEY_IN_3 = P2^6;
- sbit KEY_IN_4 = P2^7;
- sbit BUZZ = P1^6;
- unsigned char code a[]={
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90};
- unsigned char ledbuff[12] = {
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
- 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
- };
- unsigned char KeySta[4][4] = {
- {1,1,1,1,},
- {1,1,1,1,},
- {1,1,1,1,},
- {1,1,1,1,}};
- char x,z,k;
- char add1,add2;
- unsigned char flagls = 0;
- unsigned char rst24 = 24;
- int sec = 600;
- char cnt1 = 0;
- char cnt2 = 0;
- unsigned char b[4][4]={
- {1,3,0,9,},
- {2,4,0,0,},
- {5,6,0,10,},
- {7,8,0,0,}};
- //蜂鳴器部分
- void buzz()
- {
- if(sec == 0) BUZZ=0;
- }
-
- //矩陣按鍵消抖
- void keyx()
- {
- unsigned char i;
- static unsigned char keyout = 0; //矩陣按鍵掃描輸出索引
- static unsigned char keybuf[4][4] = { //矩陣按鍵掃描緩沖區
- {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
- {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
- };
- //將一行的4個按鍵值移入緩沖區
- keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
- keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
- keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
- keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
- //消抖后更新按鍵狀態
- for (i=0; i<4; i++) //每行4個按鍵,所以循環4次
- {
- if ((keybuf[keyout][i] & 0x0F) == 0x00)
- { //連續4次掃描值為0,即4*4ms內都是按下狀態時,可認為按鍵已穩定的按下
- KeySta[keyout][i] = 0;
- }
- else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
- { //連續4次掃描值為1,即4*4ms內都是彈起狀態時,可認為按鍵已穩定的彈起
- KeySta[keyout][i] = 1;
- }
- }
- //執行下一次的掃描輸出
- keyout++; //輸出索引遞增
- keyout = keyout & 0x03; //索引值加到4即歸零
- switch (keyout) //根據索引,釋放當前輸出引腳,拉低下次的輸出引腳
- {
- case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
- case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
- case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
- case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
- default: break;
- }
- }
- //600s and 24秒暫停
- void s600and24()
- {
-
- static char y;
- y = rst24;
-
- if(cnt2 != 0)
- {
- if(flagls == 1)
- {
- sec--;
- if(cnt1 % 2 == 1)
- {
- flagls = 0;
- }
-
- }
- }
- if(cnt1%2 == 0)
- {
- if(flagls == 1)
- {
- rst24--;
- flagls = 0;
- }
- }
- else
- {
- rst24 = y;
-
- }
- }
- //數碼管掃描
- void LED()
- {
- static char n = 0;
- P0 =0XFF;
- ledbuff[0] = a[(sec%60)%10];
- ledbuff[1] = a[(sec%60)/10];
- ledbuff[2] = a[(sec/60)%10] & 0x7F;
- ledbuff[3] = a[(sec/60)/10];
- ledbuff[4] = a[rst24%10];
- ledbuff[5] = a[rst24/10];
- ledbuff[6] = a[add1%10];
- ledbuff[7] = a[add1/10%10];
- ledbuff[8] = a[add1/100%10];
- ledbuff[9] = a[add2%10];
- ledbuff[10] = a[add2/10%10];
- ledbuff[11] = a[add2/100%10];
- switch(n)
- {
- case 0: P3 = 0XFF;ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[0];break;
- case 1: P3 = 0XFF;ADDR0 = 1;ADDR1 = 0;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[1];break;
- case 2: P3 = 0XFF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 0;ADDR3 = 1; n++;P0 = ledbuff[2];break;
- case 3: P3 = 0XFF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 0; n++;P0 = ledbuff[3];break;
- case 4: P3 = 0XFE;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[4];break;
- case 5: P3 = 0XFD;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[5];break;
- case 6: P3 = 0XFB;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[6];break;
- case 7: P3 = 0XF7;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[7];break;
- case 8: P3 = 0XEF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[8];break;
- case 9: P3 = 0XDF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[9];break;
- case 10: P3 = 0XBF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[10];break;
- case 11: P3 = 0X7F;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n=0;P0 = ledbuff[11];break;
- default: break;
-
-
-
- }
- }
- //矩陣按鍵動作函數,根據鍵碼進行相關操作
- void keys()
- {
- unsigned char i, j;
- static unsigned char backup [4][4] = {
- {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
- };
- for(i=0; i<4; i++)
- {
- for(j=0; j<4; j++)
- {
- if(backup[i][j] != KeySta[i][j])
- {
- if(backup[i][j] == 0)
- {
- k = b[i][j] ;
-
- switch(k)
- {
- case 1: add1++;break;
- case 2: add1--;break;
- case 3: add2++;break;
- case 4: add2--;break;
- case 5: rst24=24;break;
- case 6: cnt1++;break;
- case 7: x = add1; add1 = add2; add2 =x;break;
- case 8: cnt2++;break;
- case 9: sec = sec+60; break;
- case 10: sec = sec-60;break;
- default: break;
- }
-
- }
- backup[i][j] = KeySta[i][j];
- }
- }
- }
-
-
- }
- void main()
- {
- EA = 1;
- TMOD = 0X01;
- TH0 = 0XFC;
- TL0 = 0X67;
- ET0 = 1;
- TR0 = 1;
- add1 = add2 = 0;
- while(1)
- {
- keys();
- s600and24();
- }
- }
- //T0中斷服務函數
- void InterruptTimer0()interrupt 1
- {
- static int cnt = 0;
- TH0 = 0XFC;
- TL0 = 0X67;
- cnt ++ ;
- keyx();
- LED() ;
- if(cnt >= 1000)
- {
- cnt = 0;
- flagls = 1;
- }
- buzz();
- }
復制代碼
51hei.png (3.39 KB, 下載次數: 41)
下載附件
2019-12-15 01:11 上傳
所有資料51hei提供下載:
籃球計分計時.rar
(2.34 MB, 下載次數: 35)
2019-12-14 19:57 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|