1. 程式人生 > >基於51微控制器控制的籃球比賽計時、計分系統設計與模擬(含設計圖和C語言程式原始碼)

基於51微控制器控制的籃球比賽計時、計分系統設計與模擬(含設計圖和C語言程式原始碼)

1. 設計任務:

本次設計用由AT89C51程式設計控制LED七段數碼管作顯示的球賽計時計分系統。系統應具有賽程定時設定,賽程時間暫停,及時重新整理甲、乙雙方的成績以及賽後成績暫存等功能。
內容包括:顯示、鍵盤、時鐘等內容

2. 設計說明

2.1 需求分析

2.1.1 計分系統:

(1)分為“A隊”和“B隊”的“3分”,“2分”,“1分”各六個按鍵輸入部分,以及兩隊比分的LED顯示部分。在每次增加分數的同時,“24秒”計時恢復為初始值,“12分鐘”計時暫停,等待比賽的繼續進行

2.1.2 計時系統:

(1)比賽開始/繼續:當“比賽開始/繼續”鍵按下後,“24s”和“12分鐘”計時器開始倒計時;
(2)手動24s復位:當“24s復位” 鍵按下後,“24s”倒計時恢復初始值,“12分鐘”倒計時暫停,等待比賽的繼續;
(3)比賽暫停:“比賽暫停”鍵按下後,“24s”倒計時和“12分鐘”倒計時均暫停,等待比賽的繼續進行;
(4)自動增加比賽節數:當“12分鐘”倒計時完成後,判斷當前節數是否為最後一節,若不是,則節數自動增加,並“12分鐘”和“24s”均恢復預設值,等待下一節比賽的進行。

2.2 原理分析

採用微控制器AT89C51作為本設計的核心元件。利用7段共陰LED作為顯示器件。在此設計中共接入了6個7段共陰LED顯示器,其中2個4位LED顯示器用於記錄AB隊的分數,每隊1個4位LED顯示器顯示範圍可達到0~999分,足夠滿足賽程需要;2個兩位LED顯示器用來記錄賽程時間,其中1個用於顯示分鐘,1個用於顯示秒鐘;使用1個2位LED顯示器用於顯示“24s”倒計時,賽程計時均採用倒計時方式。即比賽前將時間設定好,即12分鐘,比賽開始時啟動計時,直至計時到零為止。本設計中設立了10個按鍵,其中6個用於設定兩隊的比分,1個用於比賽開始/比賽繼續,1個用於暫停,1個用於手動增加比賽節數,一個用於恢復“24s”倒計時等功能。

2.3 總體設計

系統主要包括微控制器、LED顯示電路、按鍵控制電路、時鐘電路及復位電路等組成

2.4 軟硬體設計

2.4.1 硬體設計

設計思路:
(1)按鍵模組設計 :
按鍵接至P1口和P3口,按鍵按下時輸入是低電平。鍵的設定如下:“A1”,“A2”,“A3”鍵是A隊加1分、加2分,加3分鍵盤,B隊同理。“比賽開始/比賽繼續”是啟動鍵,“比賽暫停”是暫停鍵。此外,還有兩個按鍵, “24s”復位鍵,“增加比賽節數”鍵。
(2) LED顯示模組設計 :
顯示分為計時和計分顯示兩個部分,均採用共陰極LED數碼管動態掃描顯示,由2個四位一體和4個兩位一體的共陰極數碼管構成。數碼管的7個段控端輸出經過74HC573驅動器進行電流放大驅動接至P0口。採用動態掃描方式,在足夠短的週期內,使各位數碼管逐個輪流受控顯示。

設計截圖:
設計截圖

2.4.2 軟體設計

軟體設計採用C語言模組設計方法,程式由主程式、T0中斷程式、顯示程式、外部中斷0程式、按鍵程式、初始函式、計時函式、延時函式組成。

C語言程式程式碼:

#include<reg52.h>
#include<absacc.h>

#define uchar unsigned char 
#define uint unsigned int

sbit A8=P2^0;  
sbit A9=P2^1;
sbit A10=P2^2;
sbit A11=P2^3;
sfr P00=0x80;


uchar code wei_1[]={0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80};
uchar code table[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0x77,0x7c,0x39,0x5e,0x79,0x71,0X00,0X40};

uchar minute=12;  //分
uchar second=0;   //秒
uchar key_status=0;     //按鍵狀態值
uchar scoreA=0;     //A隊得分
uchar scoreB=0;     //B隊得分
uchar count1=20;    //記錄定時器時間
uchar match=1;      //比賽節數
uchar rule_time=24; //記錄24秒規則
uchar rule_flag=0;          //記錄24秒規則是否啟用


/*
初始化IO口
*/
void IO_init(){
    A8=0;
    A9=0;
}
/*
初始化時間
*/

void time_init(){
    TMOD = 0x01;
    TH0 = (65536-50000)/256;
    TL0 = (65536-50000)%256; 
    EA = 1;
    ET0 = 1;
}
/*
延時函式
*/
void delay_ms(uint z){
  uint i;
    uchar j;
    for(i=0;i<z;i++){

        for(j=0;j<100;j++);
    }
}

/*
計時函式
*/
void T0_Time() interrupt 1 using 1{
    if (count1-- == 0) 
    {
        second--;
        rule_time--;
        count1 = 20; 
    }
    TH0 = (65536-50000)/256;
    TL0 = (65536-50000)%256;
}

/*
時間顯示函式
*/
void time_display(uchar w2,uchar d2){
    uchar shi1,ge1;
    shi1=d2/10;
    ge1=d2%10;

    P00=wei_1[w2];
    A10=1;
    A10=0;
    P00=table[shi1];;
    A8=1;
    A8=0;
    delay_ms(5);
    P00=0;
    A10=1;
    A10=0;
    A8=1;
    A8=0;

    P00=wei_1[w2+1];
    A10=1;
    A10=0;
    P00=table[ge1];
    A8=1;
    A8=0;
    delay_ms(5);
    P00=0;
    A10=1;
    A10=0;
    A8=1;
    A8=0;   
}

/*
分數顯示函式
*/
void score_dispaly(uchar w2,uchar d2){
    uchar qian2,shi2,ge2;
    qian2=d2/100;
    shi2=d2%100/10;
    ge2=d2%100%10;

    P00=wei_1[w2];
    A9=1;
    A9=0;
    P00=table[qian2];;
    A8=1;
    A8=0;
    delay_ms(10);
    P00=0;
    A9=1;
    A9=0;
    A8=1;
    A8=0;

    P00=wei_1[w2+1];
    A9=1;
    A9=0;
    P00=table[shi2];
    A8=1;
    A8=0;
    delay_ms(10);
    P00=0;
    A9=1;
    A9=0;
    A8=1;
    A8=0;   

    P00=wei_1[w2+2];
    A9=1;
    A9=0;
    P00=table[ge2];
    A8=1;
    A8=0;
    delay_ms(10);
    P00=0;
    A9=1;
    A9=0;
    A8=1;
    A8=0;
}

/*
鍵盤輸入函式
*/
void key(){
    static uchar key_new = 0, key_l,temp;
    key_status = 0;                  
    P1 = 0x0f;
    if((P1 & 0x0f) != 0x0f)     
    {
        delay_ms(1);            
        if(((P1 & 0x0f) != 0x0f) && (key_new == 1))
        {                       
            key_new = 0;
            /*
            矩陣鍵盤掃描
            */
            key_l = (P1 | 0xf0);   
            P1 = key_l;
            switch(P1)
            {
                /*
                開始計時/比賽繼續   
                */
                case 0x7e:  
                    TR0=1;  
                    rule_flag=1;
                    time_display(6,rule_time);
                    break;      
                /*
                暫停比賽
                */
                case 0x7d:
                    TR0=0;
                    break;  

                /*
                加分,同時24秒清零和總計時器停止計時
                */
                case 0xee: 
                    TR0=0; 
                    scoreA +=3;
                    rule_time=24;   
                    rule_flag=0;
                    break;
                case 0xed: 
                    TR0=0;                  
                    scoreA +=2;
                    rule_time=24;   
                    rule_flag=0;
                    break;
                case 0xeb:  
                    TR0=0; 
                    scoreA +=1;
                    rule_time=24;   
                    rule_flag=0;
                    break;
                case 0xde:  
                    TR0=0; 
                    scoreB +=3;
                    rule_time=24;   
                    rule_flag=0;
                   break;
                case 0xdd:  
                    TR0=0; 
                    scoreB +=2;
                    rule_time=24;   
                    rule_flag=0;
                    break;
                case 0xdb:  
                    TR0=0; 
                    scoreB +=1;
                    rule_time=24;   
                    rule_flag=0;
                    break;
                /*
                增加比賽節數,同時24秒復位和總計時器復位
                */
                case 0xbd:
                    match++;
                    minute=12;
                    second=0;
                    TR0=0; 
                    rule_time=24;   
                    rule_flag=0;
                    break;
                /*
                手動24秒復位
                */
                case 0xbe:
                    if(TR0==1){
                            rule_time=0;   
                            rule_flag=0;
                    }else{
                            rule_flag=0;  
                    }
                    break;
            }   
        }           
    }
    else 
    {
        key_new = 1;
    }
}

void main()
{
    IO_init();
    time_init();
    while(1){
        key();

        if(second==0){
            /*
                判斷某節比賽是否結束
            */
            if(minute==0){ 
                /*
                判斷是否為最後一節比賽
                */
                if(match<4){
                    /*
                    計時系統恢復為預設值,比賽節數加一
                    */
                    second=60;
                    minute=11;
                    match++;
                    rule_time=24;   
                    rule_flag=0;
                }   
                TR0=0;
            }
            /*
            比賽分鐘數減一
            */
            else {  
                second=60;
                minute--;
            }               
        }
        /*
        24秒結束,計時器暫停和24秒復位
        */
        if(rule_time<=0){
            TR0=0;
            rule_time=24;   
        }

        /*
        顯示
        */
        time_display(0,minute);
        time_display(2,second);
        time_display(4,match);
        time_display(6,rule_time);
        score_dispaly(1,scoreA);
        score_dispaly(5,scoreB);
    }
}

2.5 方案論證及可行性分析

本設計以微控制器AT89C51為核心的控制電路實現了計時計分、計時的功能,設計中,使用大尺寸數碼管的製造構思巧妙和軟體設計,降低了整個系統的成本,實現了多用途的目的。通過模擬和實物實驗驗證了該系統的正確性和實用性。系統電路製造簡單,顯示清晰,成本低廉。

2.6 測試結果與分析

設計採用C語言程式設計,在Keil C51軟體編譯環境中,經過編譯和連線,生成十六進位制的目的碼檔案.hex。在硬體上,用Proteus軟體繪製出原理圖,經過純電路除錯無誤後,將生成的目的碼檔案載入到Proteus介面的AT89C51中。接著再進行軟硬體聯合除錯,反覆除錯,直至所有顯示及按鍵功能實現,直至模擬成功。\

執行截圖:

這裡寫圖片描述

2.7 參考文獻:

[1] 胡輝. 微控制器原理與應用[M].北京:中國水利水電出版社,2007.
[2] 戴佳. 51微控制器C語言應用程式設計例項精講[M].北京:電子工業出版社,2006.

3. 設計檔案以及原始碼下載

CSDN下載地址
或者關注博主公眾號,回覆:籃球計時器即可下載,還有更多資源分享哦~

掃碼關注作者個人技術公眾號,有關技術問題後臺回覆即可,不定期將有學習資源分享
這裡寫圖片描述