找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2371|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

基于51單片機的籃球計時計分器程序Proteus仿真設(shè)計原理圖PCB

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:1079968 發(fā)表于 2023-6-17 12:04 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
此次設(shè)計的計分器總共包括四個模塊,他們是24秒顯示、計時器、記分器。實現(xiàn)的功能是:24秒顯示能按鍵控制24秒計時器,當(dāng)控球時間超過24秒時,可發(fā)出報警信號。計時器可按鍵調(diào)節(jié),可以隨時暫停計時,暫停比賽,在每節(jié)結(jié)束和全場結(jié)束時報警。記分器記錄兩隊的積累分?jǐn)?shù),可通過按鍵分別加1、2、3分。

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)



設(shè)計分為硬件設(shè)計和軟件設(shè)計。硬件設(shè)計的主要包括的是:液晶顯示、按鍵控制系統(tǒng)設(shè)計以及輔助功能的設(shè)計。軟件設(shè)計包括:功能選擇、倒計時的實現(xiàn)。本文主要介紹了用單片機設(shè)計實現(xiàn)籃球計分器的整個流程,采用C語言編寫程序。時間顯示部分可以以秒為單位進行計時調(diào)整。比分顯示部分可以實現(xiàn)在半場結(jié)束后手動換場,顯示模塊均采用動態(tài)掃描方式進行顯示。按鍵控制部分采用獨立按鍵,共設(shè)12個按鍵,實現(xiàn)調(diào)整分?jǐn)?shù)、調(diào)整時間、比賽的開始/暫停、復(fù)位鍵和交換場地鍵等功能。報警部分由蜂鳴器加三級管驅(qū)動,實現(xiàn)了報警聲音的功能。


體育賽場中的計時計分系統(tǒng)是對體育比賽過程中所產(chǎn)生的時間、比分等數(shù)據(jù)信息進行快速采集、加工處理、傳遞和利用的系統(tǒng)。此系統(tǒng)能否清晰、穩(wěn)定、精確的反應(yīng)體育比賽中的客觀數(shù)據(jù),直接影響到比賽公平性和公正性。
1.2 設(shè)計的目的與意義

本次設(shè)計,籃球賽場計時計分器是一種非常廣泛的體育日用工具,在籃球體育中運用的越來越廣泛。它能夠?qū)崟r計時計分的優(yōu)點,并且在半場交換場地后,能夠交換分?jǐn)?shù)位置;還設(shè)置有24s進攻時間報警。它的實用性令我對這道項目產(chǎn)生了興趣,以前在數(shù)字電路這門課里使用各個計數(shù)器芯片做過簡易的檢測器,所以對單片機實現(xiàn)籃球賽場計時計分器的過程十分好奇,也想通過自己所學(xué)的知識,真正完成這樣實用的產(chǎn)品,雖然不能夠十分完美的還原真正功能完善的水位控制器,但是可以鞏固我的知識,也可以歷練自己。增進對單片機的感性認識,加深對單片機理論方面的理解。
1.3 設(shè)計內(nèi)容該系統(tǒng)以MCS-51單片機為籃球計時計分器的核心,用按鈕模擬加分;24s復(fù)位;時間控制的數(shù)字信號
      1、系統(tǒng)設(shè)計選用的部件以及系統(tǒng)設(shè)計的原理。
      2、硬件部分的設(shè)計。
      3、軟件程序的設(shè)計(里面包含對主程序、延遲程序、顯示程序的設(shè)計等實現(xiàn)特定功能的程序)。
1.4 計劃實現(xiàn)成果(1)能記錄全部賽程的比賽時間,并能修改比賽時間。
(2)能隨時刷新甲、乙兩隊在全盤比賽歷程中的比分。
(3)中場交換比賽場地時,能交換甲、乙兩隊比分的位置。
(4)比賽時間到時,能發(fā)出報警聲。
(5)實現(xiàn)24s進攻時間倒計時和復(fù)位。  


第2章    系統(tǒng)分析與設(shè)計
2.1 系統(tǒng)功能分析此次設(shè)計的計分器總共包括四個模塊,他們是24秒顯示、計時器、記分器。實現(xiàn)的功能是:24秒顯示能按鍵控制24秒計時器,當(dāng)控球時間超過24秒時,可發(fā)出報警信號。計時器可按鍵調(diào)節(jié),可以隨時暫停計時,暫停比賽,在每節(jié)結(jié)束和全場結(jié)束時報警。記分器記錄兩隊的積累分?jǐn)?shù),可通過按鍵分別加1、2、3分。

2.2 系統(tǒng)部件的選擇分析
2.2.1 中央控制單元CPU采用傳統(tǒng)的 51 單片機作為整個電路的控制核心。單片機算術(shù)運算功能強, 軟件編程靈活、自由度大,可用軟件編程實現(xiàn)各種算法和邏輯控制,并且由于其功耗低、體積小、技術(shù)成熟和成本低等優(yōu)點,使其在各個領(lǐng)域應(yīng)用廣泛
2.2.2顯示模塊選擇采用LED液晶顯示屏,液晶顯示屏具有顯示功能強大且可顯示大量圖形、文字,
顯示內(nèi)容多樣,清晰可見,但是價格非常昂貴,需要的接口線較多,因此在此次設(shè)計中不會采用LED液晶顯示屏。
2.3 軟件算法選擇分析一般編寫單片機程序的語言有 C 語言編寫和匯編語言兩種,這兩種語言有以下的區(qū)別:

(1)兩者編譯組成不同。匯編語言是將由 0、1 組成的機器語言用具有簡單語義的英文代碼表示,而 C 語言不但將許多相關(guān)的機器指令合成為單條指令,并且去掉了與具體操作有關(guān)但與完成工作無關(guān)的細節(jié),例如使用堆棧、寄存器等。
(2)兩者被計算機識別的路徑不同。匯編語言通常用于對硬件的直接操控。而且
C 語言所編制的程序不能直接被計算機識別,必須經(jīng)過轉(zhuǎn)換才能被執(zhí)行。
(3)兩者用處不同。匯編語言通常用在程序中最核心的、控制硬件的代碼,一方面是安全,另一方面提高運行速度。而 C 語言通常用在計算機外用功能上。
(4)兩者學(xué)習(xí)難易程度不同。匯編語言所需要的編繪知識很多很復(fù)雜,經(jīng)常被開發(fā)者使用。而 C 語言是一門很簡單方便的語言,編程者也就不需要有太多的專業(yè)知識。

考慮到此次編程的復(fù)雜性,用匯編語言比較繁瑣復(fù)雜,容易出錯,因此選擇靈活的C語言編寫,并且分模塊進行編寫。

仿真運行結(jié)果在Keil軟件上新建一個新工程“單片機”,在工程下在建立一個新文件,將程序?qū)懭胛募4鏋椤皢纹瑱C.c”,將文件添加到“單片機”工程中,編譯調(diào)試查錯,直到編譯沒有錯誤時,連接建立目標(biāo)文件,并設(shè)置生成“.hex”文件,在Proteus軟件中雙擊AT89C51單片機選擇該hex文件,錄入后按下仿真按鈕。

(一)    按下比賽開始按鈕
(二)    比賽加分
通過加分按鈕,可給甲隊乙隊分別加分,分值13分,符合籃球賽場實際加分分值。
(三)    中場互換后,分值位置互換
(四)    24s進攻時間倒計時復(fù)位
(五)    時間控制
時間減少5s
時間增加5s
(六)    24s倒計時后,報警器響起

實物運行結(jié)果
實物接線圖
通電之后液晶屏顯示
按下比賽開始按鈕后,計時器開始工作
分別給甲隊和乙隊積分,計分器工作
中場休息,積分位置互換


總    結(jié)
單片機這門課的應(yīng)用性非常廣泛,也很實用,所以掌握這門書本知識還是遠遠 不夠的,設(shè)計就是一個教大家將書本知識實際應(yīng)用到技術(shù)生產(chǎn)的絕好機會現(xiàn)在芯片、科技都趨于集成化,學(xué)著設(shè)計籃球賽場計時計分器是一個基礎(chǔ)。一個個基礎(chǔ)、技術(shù)、設(shè)計集成起來就可以構(gòu)成多元化、功能完善、多樣化的復(fù)雜系統(tǒng),所以認真研習(xí)如何完成設(shè)計十分有實用性和必要性,也是與未來技術(shù)生產(chǎn)投身于研究、社會工作的過渡。這次設(shè)計收獲還是很多的,通過自己的努力深入學(xué)習(xí)了STC89C51芯片,知道了它們的工作原理、工作方式,為自己的知識庫里添加知識和經(jīng)驗,同時也讓我感受到了單片機功能的強大。其次,只有交流討論才能夠判斷自己的設(shè)計是否正確或者有什么問題,這點研究生學(xué)長給我了很大的幫助,令我知道自己還有哪里不足,使我對單片機掌握的更加細致,鍛煉了我的交流闡述能力。
這次設(shè)計也讓看到了自己知識的局限性,比如在創(chuàng)新上還很欠缺,原本想再加上24s進攻時間的功能,但是自己編寫的程序在編譯上出了問題,說明我還需要在程序上多下功夫,對此也深感遺憾。我今后會多多鍛煉自己的邏輯思維,希望可以做的越來越好,也希望可以成為對學(xué)術(shù)嚴(yán)謹(jǐn)、樂于求知的人

單片機源程序如下:
  1. #include<reg51.h>//51單片機頭文件
  2. typedef unsigned char uchar;
  3. typedef unsigned int  uint;
  4. sbit K1=P3^2;//比賽倒計時開始/暫停
  5. sbit K2=P3^3;//24s倒計時重新開始
  6. sbit K3=P1^3;//乙隊+1按鍵
  7. sbit K4=P1^2;//乙隊+2按鍵
  8. sbit K5=P1^1;//甲隊+1按鍵
  9. sbit K6=P1^0;//甲隊+2按鍵
  10. sbit K7=P1^4;//時間減少
  11. sbit K8=P1^5;//時間增加
  12. sbit K9=P1^6;//半場積分互換
  13. sbit beep=P2^0;//蜂鳴器接口  
  14. sbit RS=P2^7;
  15. sbit E=P2^5;
  16. char miao,fen,num,time,aa;
  17. uchar bb,cc,tt;
  18. uchar code table1[]={"H.T 000:000 R.T "};
  19. uchar code table2[]={"12:00  SEC-1  24"};
  20. //延時子函數(shù)
  21. void delay(uint z)  
  22. {
  23.         uint x;
  24.         uchar y;
  25.         for(x=z;x>0;x--)
  26.                   for(y=110;y>0;y--);
  27. }
  28. //LCD1602液晶寫指令子函數(shù)
  29. void write_com(uchar com)
  30. {
  31.         RS=0;
  32.         P0=com;
  33.         delay(5);
  34.         E=1;
  35.         delay(5);
  36.         E=0;
  37. }
  38. //LCD1602液晶寫數(shù)據(jù)子函數(shù)
  39. void write_date(uchar date)
  40. {
  41.         RS=1;
  42.         P0=date;
  43.         delay(5);
  44.         E=1;
  45.         delay(5);
  46.         E=0;
  47. }
  48. //LCD1602液晶初始化子函數(shù)
  49. void LCD1602_init()
  50. {
  51.         uchar i;
  52.         bb=0;    //H.T分?jǐn)?shù)初始化
  53.         cc=0;    //R.T分?jǐn)?shù)初始化
  54.         time=0;
  55.         TMOD=0x10;    //定時器1初始化
  56.         TL1=0x00;
  57.         TH1=0x4c;
  58.         EA=1;     //開總中斷
  59.         ET1=1;     //開定時器1
  60.         TR1=0;     //定時器1不工作
  61.         EX0=1;     //開中斷0
  62.         EX1=1;     //開中斷1
  63.         IT0=1;     //中斷0為邊沿觸發(fā)
  64.         IT1=1;     //中斷1為邊沿觸發(fā)
  65.         E=0;
  66.         beep=0;
  67.         miao=0;
  68.         fen=12;
  69.         num=1;
  70.         aa=24;
  71.         write_com(0x38);  //LCD設(shè)置初始化
  72.         write_com(0x0c);
  73.         write_com(0x06);
  74.         write_com(0x01);
  75.         write_com(0x80);  //LCD顯示初始化
  76.         for(i=0;i<16;i++)
  77.         {
  78.                   write_date(table1[i]);
  79.         }
  80.         write_com(0x80+0x40);
  81.         for(i=0;i<16;i++)
  82.         {
  83.                   write_date(table2[i]);
  84.         }
  85. }
  86. //分?jǐn)?shù)更新子函數(shù)
  87. void point_lcd(uchar add,uchar dat)
  88. {
  89.         write_com(0x80+add);
  90.         write_date(0x30+dat/100);
  91.         write_date(0x30+(dat%100)/10);
  92.         write_date(0x30+dat%10);
  93.         write_com(0x80+add);
  94. }
  95. //按鍵掃描子函數(shù)
  96. void keyscan()
  97. {
  98.         if(K3==0)     //K3按下H.T分?jǐn)?shù)加一
  99.         {
  100.                   while(K3==0);
  101.                 bb++;
  102.                   point_lcd(0x04,bb);  //分?jǐn)?shù)顯示更新
  103.                   if(K3==0)    //松手檢測
  104.                   {
  105.                            while(K3==0);
  106.                            delay(20);
  107.                   }
  108.         }
  109.         else if(K4==0)    //K4按下H.T分?jǐn)?shù)加二
  110.         {
  111.                   while(K4==0);
  112.                 bb=bb+2;
  113.                   point_lcd(0x04,bb);
  114.                   if(K4==0)
  115.                   {
  116.                            while(K4==0);
  117.                            delay(20);
  118.                   }
  119.         }
  120.         else if(K7==0)          //K7時間減少5s
  121.         {
  122.                 while(K7==0);
  123.                 {aa=aa-5;
  124.                 miao=miao-5;}
  125.         }
  126.         else if(K5==0)    //K5按下R.T分?jǐn)?shù)加一
  127.         {
  128.                   while(K5==0);
  129.                 cc++;
  130.                   point_lcd(0x08,cc);
  131.                   if(K5==0)
  132.                   {
  133.                            while(K5==0);
  134.                            delay(20);
  135.                   }
  136.         }
  137.         else if(K6==0)    //K6按下R.T分?jǐn)?shù)加2
  138.         {
  139.                   while(K6==0);
  140.                 cc=cc+2;
  141.                   point_lcd(0x08,cc);
  142.                   if(K6==0)
  143.                   {
  144.                            while(K6==0);
  145.                            delay(20);
  146.                   }
  147.         }
  148. else if(K8==0)          //K9時間增加5s
  149.         {
  150.                 while(K8==0);
  151.                 {aa=aa+5;
  152.                 miao=miao+5;}
  153.         }
  154.         else if(K9==0)    //K9半場場地互換,積分互換
  155.         {                                          
  156.                                 while(K9==0);
  157.                 {
  158.                         uchar code table3[]={"R.T 000:000 H.T "};
  159.                         tt=bb;bb=cc;cc=tt;
  160.                 }
  161.                         point_lcd(0x04,bb);
  162.                   point_lcd(0x08,cc);
  163.                 if(K9==0)
  164.                 {
  165.                         while(K9==0);
  166.                         delay(20);
  167.                 }
  168.         }
  169. }
  170. //比賽倒計時/24s倒計時
  171. void counter_down()
  172. {
  173.         uchar i;
  174.         if(time>=20)     //每1s倒計時做減一操作
  175.         {
  176.                   miao--;
  177.                   aa--;
  178.                   write_com(0x80+0x4e);  //24s倒計時顯示
  179.                   write_date(0x30+aa/10);
  180.                   write_date(0x30+aa%10);
  181.                 write_com(0x80+0x4e);
  182.                   if(aa==0)    //24s結(jié)束發(fā)出3s連續(xù)報警
  183.                   {
  184.                            beep=1;
  185.                            delay(3000);
  186.                            beep=0;
  187.                            aa=24;
  188.                   }
  189.                   if((miao==0)&&(fen==0))  //檢測一節(jié)比賽是否結(jié)束
  190.                   {
  191.                            TR1=0;     //定時器1暫停
  192.                            write_com(0x80+0x44);
  193.                            write_date(0x30);
  194.                            num++;
  195.                            aa=24;    //24s計時復(fù)位
  196.                            write_com(0x80+0x4e);  //24s倒計時顯示
  197.                            write_date(0x30+aa/10);
  198.                            write_date(0x30+aa%10);
  199.                         write_com(0x80+0x4e);
  200.                            if(num<5)    //每節(jié)結(jié)束蜂鳴器發(fā)出8s的間斷報警
  201.                            {
  202.                             for(i=80;i>0;i--)
  203.                             {
  204.                                      beep=1;
  205.                                      delay(500);
  206.                                      beep=0;
  207.                                      delay(500);
  208.                             }
  209.                            }
  210.                            if(num==5)    //終場結(jié)束,蜂鳴器發(fā)出10s的連續(xù)警報聲
  211.                            {
  212.                              beep=1;
  213.                              delay(10000);
  214.                              num=0;
  215.                            }        
  216.                            beep=0;     //蜂鳴器關(guān)閉
  217.                         write_com(0x80+0x4b); //更新"SEC-?"
  218.                         write_date(0x30+num);
  219.                         write_com(0x80+0x4b);
  220.                         miao=0;     //倒計時復(fù)位
  221.                         fen=12;
  222.                   }
  223.                   if(miao==-1)
  224.                   {
  225.                            miao=59;
  226.                            fen--;
  227.                   }
  228.                   write_com(0x80+0x40);  //更新倒計時顯示
  229.                   write_date(0x30+fen/10);
  230.                   write_date(0x30+fen%10);
  231.                   write_com(0x80+0x43);
  232.                   write_date(0x30+miao/10);
  233.                   write_date(0x30+miao%10);
  234.                 write_com(0x80+0x43);
  235.                   time=0;
  236.         }
  237. }
  238. //主函數(shù)
  239. void main()
  240. {
  241.         LCD1602_init();
  242.         while(1)
  243.         {
  244.                   keyscan();  //分?jǐn)?shù)按鍵檢測
  245.         }
  246. }
  247. //外部0中斷子函數(shù)
  248. void wb0() interrupt 0  //比賽時間開始/暫停
  249. {
  250.         TR1=~TR1;     //定時器1工作/暫停
  251.         if(TR1==1)  //當(dāng)?shù)褂嫊r工作時,S1按下定時器立即停止工作
  252.         {
  253.                   PT1=0;
  254.         }
  255.         else   //倒計時不工作時,S1按下倒計時立即工作
  256.         {
  257.                   PT1=1;
  258.         }
  259.         if(K1==0)     //松手檢測
  260.         {
  261.                   while(K1==0);
  262.                    counter_down();
  263.           //        delay(20);
  264.         }
  265. }
  266. //外部1中斷子函數(shù)
  267. void wb1() interrupt 2   //24s倒計時重新開始
  268. {
  269.         aa=24;
  270.         write_com(0x80+0x4e);   //24s倒計時顯示
  271.         write_date(0x30+aa/10);
  272.         write_date(0x30+aa%10);
  273.         write_com(0x80+0x4e);
  274.         if(K2==0)      //松手檢測
  275.         {
  276.                   while(K2==0)
  277.                   {
  278.                            counter_down();
  279.                   }
  280.                   delay(20);
  281.         }
  282. }
  283. //定時器1中斷子函數(shù)
  284. void t1() interrupt 3   //定時器1中斷20次為1s
  285. {
  286.         time++;
  287.         TL1=0x00;
  288.         TH1=0x4c;
  289.         counter_down();     //倒計時
  290. }
復(fù)制代碼

Keil代碼與Proteus8.13仿真 原理圖PCB 下載:
籃球計分器.7z (290.87 KB, 下載次數(shù): 37)

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:262 發(fā)表于 2023-6-20 02:59 | 只看該作者
好資料,51黑有你更精彩!!!
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表