找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1225|回复: 1
打印 上一主题 下一主题
收起左侧

基于51单片机的篮球计时计分器程序Proteus仿真设计原理图PCB

[复制链接]
跳转到指定楼层
楼主
此次设计的计分器总共包括四个模块,他们是24秒显示、计时器、记分器。实现的功能是:24秒显示能按键控制24秒计时器,当控球时间超过24秒时,可发出报警信号。计时器可按键调节,可以随时暂停计时,暂停比赛,在每节结束和全场结束时报警。记分器记录两队的积累分数,可通过按键分别加1、2、3分。

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


Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)



设计分为硬件设计和软件设计。硬件设计的主要包括的是:液晶显示、按键控制系统设计以及辅助功能的设计。软件设计包括:功能选择、倒计时的实现。本文主要介绍了用单片机设计实现篮球计分器的整个流程,采用C语言编写程序。时间显示部分可以以秒为单位进行计时调整。比分显示部分可以实现在半场结束后手动换场,显示模块均采用动态扫描方式进行显示。按键控制部分采用独立按键,共设12个按键,实现调整分数、调整时间、比赛的开始/暂停、复位键和交换场地键等功能。报警部分由蜂鸣器加三级管驱动,实现了报警声音的功能。


体育赛场中的计时计分系统是对体育比赛过程中所产生的时间、比分等数据信息进行快速采集、加工处理、传递和利用的系统。此系统能否清晰、稳定、精确的反应体育比赛中的客观数据,直接影响到比赛公平性和公正性。
1.2 设计的目的与意义

本次设计,篮球赛场计时计分器是一种非常广泛的体育日用工具,在篮球体育中运用的越来越广泛。它能够实时计时计分的优点,并且在半场交换场地后,能够交换分数位置;还设置有24s进攻时间报警。它的实用性令我对这道项目产生了兴趣,以前在数字电路这门课里使用各个计数器芯片做过简易的检测器,所以对单片机实现篮球赛场计时计分器的过程十分好奇,也想通过自己所学的知识,真正完成这样实用的产品,虽然不能够十分完美的还原真正功能完善的水位控制器,但是可以巩固我的知识,也可以历练自己。增进对单片机的感性认识,加深对单片机理论方面的理解。
1.3 设计内容该系统以MCS-51单片机为篮球计时计分器的核心,用按钮模拟加分;24s复位;时间控制的数字信号
      1、系统设计选用的部件以及系统设计的原理。
      2、硬件部分的设计。
      3、软件程序的设计(里面包含对主程序、延迟程序、显示程序的设计等实现特定功能的程序)。
1.4 计划实现成果(1)能记录全部赛程的比赛时间,并能修改比赛时间。
(2)能随时刷新甲、乙两队在全盘比赛历程中的比分。
(3)中场交换比赛场地时,能交换甲、乙两队比分的位置。
(4)比赛时间到时,能发出报警声。
(5)实现24s进攻时间倒计时和复位。  


第2章    系统分析与设计
2.1 系统功能分析此次设计的计分器总共包括四个模块,他们是24秒显示、计时器、记分器。实现的功能是:24秒显示能按键控制24秒计时器,当控球时间超过24秒时,可发出报警信号。计时器可按键调节,可以随时暂停计时,暂停比赛,在每节结束和全场结束时报警。记分器记录两队的积累分数,可通过按键分别加1、2、3分。

2.2 系统部件的选择分析
2.2.1 中央控制单元CPU采用传统的 51 单片机作为整个电路的控制核心。单片机算术运算功能强, 软件编程灵活、自由度大,可用软件编程实现各种算法和逻辑控制,并且由于其功耗低、体积小、技术成熟和成本低等优点,使其在各个领域应用广泛
2.2.2显示模块选择采用LED液晶显示屏,液晶显示屏具有显示功能强大且可显示大量图形、文字,
显示内容多样,清晰可见,但是价格非常昂贵,需要的接口线较多,因此在此次设计中不会采用LED液晶显示屏。
2.3 软件算法选择分析一般编写单片机程序的语言有 C 语言编写和汇编语言两种,这两种语言有以下的区别:

(1)两者编译组成不同。汇编语言是将由 0、1 组成的机器语言用具有简单语义的英文代码表示,而 C 语言不但将许多相关的机器指令合成为单条指令,并且去掉了与具体操作有关但与完成工作无关的细节,例如使用堆栈、寄存器等。
(2)两者被计算机识别的路径不同。汇编语言通常用于对硬件的直接操控。而且
C 语言所编制的程序不能直接被计算机识别,必须经过转换才能被执行。
(3)两者用处不同。汇编语言通常用在程序中最核心的、控制硬件的代码,一方面是安全,另一方面提高运行速度。而 C 语言通常用在计算机外用功能上。
(4)两者学习难易程度不同。汇编语言所需要的编绘知识很多很复杂,经常被开发者使用。而 C 语言是一门很简单方便的语言,编程者也就不需要有太多的专业知识。

考虑到此次编程的复杂性,用汇编语言比较繁琐复杂,容易出错,因此选择灵活的C语言编写,并且分模块进行编写。

仿真运行结果在Keil软件上新建一个新工程“单片机”,在工程下在建立一个新文件,将程序写入文件保存为“单片机.c”,将文件添加到“单片机”工程中,编译调试查错,直到编译没有错误时,连接建立目标文件,并设置生成“.hex”文件,在Proteus软件中双击AT89C51单片机选择该hex文件,录入后按下仿真按钮。

(一)    按下比赛开始按钮
(二)    比赛加分
通过加分按钮,可给甲队乙队分别加分,分值13分,符合篮球赛场实际加分分值。
(三)    中场互换后,分值位置互换
(四)    24s进攻时间倒计时复位
(五)    时间控制
时间减少5s
时间增加5s
(六)    24s倒计时后,报警器响起

实物运行结果
实物接线图
通电之后液晶屏显示
按下比赛开始按钮后,计时器开始工作
分别给甲队和乙队积分,计分器工作
中场休息,积分位置互换


总    结
单片机这门课的应用性非常广泛,也很实用,所以掌握这门书本知识还是远远 不够的,设计就是一个教大家将书本知识实际应用到技术生产的绝好机会现在芯片、科技都趋于集成化,学着设计篮球赛场计时计分器是一个基础。一个个基础、技术、设计集成起来就可以构成多元化、功能完善、多样化的复杂系统,所以认真研习如何完成设计十分有实用性和必要性,也是与未来技术生产投身于研究、社会工作的过渡。这次设计收获还是很多的,通过自己的努力深入学习了STC89C51芯片,知道了它们的工作原理、工作方式,为自己的知识库里添加知识和经验,同时也让我感受到了单片机功能的强大。其次,只有交流讨论才能够判断自己的设计是否正确或者有什么问题,这点研究生学长给我了很大的帮助,令我知道自己还有哪里不足,使我对单片机掌握的更加细致,锻炼了我的交流阐述能力。
这次设计也让看到了自己知识的局限性,比如在创新上还很欠缺,原本想再加上24s进攻时间的功能,但是自己编写的程序在编译上出了问题,说明我还需要在程序上多下功夫,对此也深感遗憾。我今后会多多锻炼自己的逻辑思维,希望可以做的越来越好,也希望可以成为对学术严谨、乐于求知的人

单片机源程序如下:
  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. //延时子函数
  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液晶写指令子函数
  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液晶写数据子函数
  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液晶初始化子函数
  49. void LCD1602_init()
  50. {
  51.         uchar i;
  52.         bb=0;    //H.T分数初始化
  53.         cc=0;    //R.T分数初始化
  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为边沿触发
  64.         IT1=1;     //中断1为边沿触发
  65.         E=0;
  66.         beep=0;
  67.         miao=0;
  68.         fen=12;
  69.         num=1;
  70.         aa=24;
  71.         write_com(0x38);  //LCD设置初始化
  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. //分数更新子函数
  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. //按键扫描子函数
  96. void keyscan()
  97. {
  98.         if(K3==0)     //K3按下H.T分数加一
  99.         {
  100.                   while(K3==0);
  101.                 bb++;
  102.                   point_lcd(0x04,bb);  //分数显示更新
  103.                   if(K3==0)    //松手检测
  104.                   {
  105.                            while(K3==0);
  106.                            delay(20);
  107.                   }
  108.         }
  109.         else if(K4==0)    //K4按下H.T分数加二
  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分数加一
  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分数加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结束发出3s连续报警
  183.                   {
  184.                            beep=1;
  185.                            delay(3000);
  186.                            beep=0;
  187.                            aa=24;
  188.                   }
  189.                   if((miao==0)&&(fen==0))  //检测一节比赛是否结束
  190.                   {
  191.                            TR1=0;     //定时器1暂停
  192.                            write_com(0x80+0x44);
  193.                            write_date(0x30);
  194.                            num++;
  195.                            aa=24;    //24s计时复位
  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)    //每节结束蜂鸣器发出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)    //终场结束,蜂鸣器发出10s的连续警报声
  211.                            {
  212.                              beep=1;
  213.                              delay(10000);
  214.                              num=0;
  215.                            }        
  216.                            beep=0;     //蜂鸣器关闭
  217.                         write_com(0x80+0x4b); //更新"SEC-?"
  218.                         write_date(0x30+num);
  219.                         write_com(0x80+0x4b);
  220.                         miao=0;     //倒计时复位
  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. //主函数
  239. void main()
  240. {
  241.         LCD1602_init();
  242.         while(1)
  243.         {
  244.                   keyscan();  //分数按键检测
  245.         }
  246. }
  247. //外部0中断子函数
  248. void wb0() interrupt 0  //比赛时间开始/暂停
  249. {
  250.         TR1=~TR1;     //定时器1工作/暂停
  251.         if(TR1==1)  //当倒计时工作时,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中断子函数
  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中断子函数
  284. void t1() interrupt 3   //定时器1中断20次为1s
  285. {
  286.         time++;
  287.         TL1=0x00;
  288.         TH1=0x4c;
  289.         counter_down();     //倒计时
  290. }
复制代码

Keil代码与Proteus8.13仿真 原理图PCB 下载:
篮球计分器.7z (290.87 KB, 下载次数: 31)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:262 发表于 2023-6-20 02:59 | 只看该作者
好资料,51黑有你更精彩!!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表