找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的篮球计分计时板程序+电路设计

[复制链接]
跳转到指定楼层
楼主
在主程序中,先使能全局中断,然后使能74HC245来控制数码管。配置定时器0工作在模式1并设置定时初值1ms,清零TF位,使能定时器0并启动定时器0。按键动作函数keys进行按键消抖。进入中断后,不断扫描按键动作,并在中断中完成队伍比分、倒计时和蜂鸣器的显示。最后while(1)循环中调用按键扫描扫描函数Keys、 600s和24s倒计时, 检测一次按键状态,如果在连续的8次移位检测中按键状态保持不变,则判定为按键已动作,显示相应的数码管动态。主程序流程图如图6所示:
                             
图6 主程序流程图

3.2蜂鸣器子程序设计
在中断子程序中,对蜂鸣器函数进行调用,并判断600s和24s函数中sec是否为0。当十分钟倒计未结束的时候,蜂鸣器不工作,当十分钟倒计时结束的时候,蜂鸣器发出响声。蜂鸣器电路流程图如图6所示:

                                  图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所示:
   
图8 按键动作函数流程图
3.4中断子程序设计
中断子程序中,通过定时器T0调用数码管动态刷新函数、矩阵按键扫描函数以及蜂鸣器函数。中断1000次即一秒,当达到一秒时,清零计数值以重新开始下一个一秒计时,同时设置一秒定时器标志为1。定时器中断流程图如图9所示:

单片机源程序如下:
  1. #include<reg52.h>
  2.   
  3. sbit ADDR0 = P1^0;
  4. sbit ADDR1 = P1^1;
  5. sbit ADDR2 = P1^2;
  6. sbit ADDR3 = P1^3;



  7. sbit KEY_OUT_1 = P2^3;
  8. sbit KEY_OUT_2 = P2^2;
  9. sbit KEY_OUT_3 = P2^1;
  10. sbit KEY_OUT_4 = P2^0;

  11. sbit KEY_IN_1 = P2^4;
  12. sbit KEY_IN_2 = P2^5;
  13. sbit KEY_IN_3 = P2^6;
  14. sbit KEY_IN_4 = P2^7;

  15. sbit BUZZ = P1^6;

  16. unsigned char code a[]={
  17.         0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  18.         0x80, 0x90};
  19. unsigned char  ledbuff[12] = {
  20. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  21. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
  22. };
  23. unsigned char  KeySta[4][4] = {
  24.         {1,1,1,1,},
  25.         {1,1,1,1,},
  26.         {1,1,1,1,},
  27.         {1,1,1,1,}};
  28. char x,z,k;
  29. char add1,add2;
  30. unsigned char flagls = 0;
  31. unsigned char rst24 = 24;
  32. int sec = 600;
  33. char cnt1 = 0;
  34. char cnt2 = 0;
  35. unsigned char b[4][4]={
  36.         {1,3,0,9,},
  37.         {2,4,0,0,},
  38.         {5,6,0,10,},
  39.         {7,8,0,0,}};


  40. //蜂鸣器部分
  41. void buzz()
  42. {
  43.    if(sec == 0) BUZZ=0;
  44. }


  45. //矩阵按键消抖
  46. void keyx()
  47. {
  48.     unsigned char i;
  49.     static unsigned char keyout = 0;   //矩阵按键扫描输出索引
  50.     static unsigned char keybuf[4][4] = {  //矩阵按键扫描缓冲区
  51.         {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF},
  52.         {0xFF, 0xFF, 0xFF, 0xFF},  {0xFF, 0xFF, 0xFF, 0xFF}
  53.     };

  54.     //将一行的4个按键值移入缓冲区
  55.     keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
  56.     keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
  57.     keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
  58.     keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
  59.     //消抖后更新按键状态
  60.     for (i=0; i<4; i++)  //每行4个按键,所以循环4次
  61.     {
  62.         if ((keybuf[keyout][i] & 0x0F) == 0x00)
  63.         {   //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
  64.             KeySta[keyout][i] = 0;
  65.         }
  66.         else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
  67.         {   //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
  68.             KeySta[keyout][i] = 1;
  69.         }
  70.     }
  71.     //执行下一次的扫描输出
  72.     keyout++;                //输出索引递增
  73.     keyout = keyout & 0x03;  //索引值加到4即归零
  74.     switch (keyout)          //根据索引,释放当前输出引脚,拉低下次的输出引脚
  75.     {
  76.         case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
  77.         case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
  78.         case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
  79.         case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
  80.         default: break;
  81.     }
  82. }



  83. //600s  and  24秒暂停
  84. void s600and24()
  85. {
  86.         
  87.         static char y;
  88.         y = rst24;
  89.         
  90.         if(cnt2 != 0)
  91.         {
  92.                 if(flagls == 1)
  93.                 {
  94.                         sec--;
  95.                         if(cnt1 % 2 == 1)
  96.                         {
  97.                                 flagls = 0;        
  98.                         }
  99.                         
  100.                 }
  101.         }
  102.         if(cnt1%2 == 0)
  103.         {
  104.                 if(flagls == 1)
  105.                 {
  106.                         rst24--;
  107.                         flagls = 0;
  108.                 }
  109.         }
  110.         else
  111.         {
  112.                 rst24 = y;
  113.         
  114.         }
  115. }


  116. //数码管扫描
  117. void LED()
  118. {        
  119.         static char n = 0;

  120.         P0 =0XFF;

  121.         ledbuff[0] = a[(sec%60)%10];
  122.         ledbuff[1] = a[(sec%60)/10];
  123.         ledbuff[2] = a[(sec/60)%10] & 0x7F;
  124.         ledbuff[3] = a[(sec/60)/10];

  125.         ledbuff[4] = a[rst24%10];
  126.         ledbuff[5] = a[rst24/10];

  127.         ledbuff[6] = a[add1%10];
  128.         ledbuff[7] = a[add1/10%10];
  129.         ledbuff[8] = a[add1/100%10];

  130.         ledbuff[9] = a[add2%10];
  131.         ledbuff[10] = a[add2/10%10];
  132.         ledbuff[11] = a[add2/100%10];

  133.         switch(n)
  134.         {
  135.                 case 0:   P3 = 0XFF;ADDR0 = 0;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[0];break;
  136.                 case 1:   P3 = 0XFF;ADDR0 = 1;ADDR1 = 0;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[1];break;
  137.                 case 2:   P3 = 0XFF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 0;ADDR3 = 1; n++;P0 = ledbuff[2];break;
  138.                 case 3:   P3 = 0XFF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 0; n++;P0 = ledbuff[3];break;
  139.                 case 4:   P3 = 0XFE;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[4];break;
  140.                 case 5:   P3 = 0XFD;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[5];break;
  141.                 case 6:   P3 = 0XFB;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[6];break;
  142.                 case 7:   P3 = 0XF7;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[7];break;
  143.                 case 8:   P3 = 0XEF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[8];break;
  144.                 case 9:   P3 = 0XDF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[9];break;
  145.                 case 10:  P3 = 0XBF;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n++;P0 = ledbuff[10];break;
  146.                 case 11:  P3 = 0X7F;ADDR0 = 1;ADDR1 = 1;ADDR2 = 1;ADDR3 = 1; n=0;P0 = ledbuff[11];break;
  147.                 default: break;
  148.                
  149.         

  150.                                                                                                                   

  151.         }

  152. }

  153. //矩阵按键动作函数,根据键码进行相关操作
  154. void  keys()
  155. {
  156.         unsigned char i, j;

  157.         static        unsigned char backup [4][4] = {
  158.         {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
  159.         };

  160.         for(i=0; i<4; i++)
  161.                 {
  162.                         for(j=0; j<4; j++)
  163.                         {
  164.                                 if(backup[i][j] != KeySta[i][j])
  165.                                 {
  166.                                         if(backup[i][j] == 0)
  167.                                         {
  168.                                                 k = b[i][j]        ;
  169.                                                 
  170.                                                 switch(k)
  171.                                                 {
  172.                                                          case 1: add1++;break;
  173.                                                         case 2: add1--;break;
  174.                                                         case 3: add2++;break;
  175.                                                         case 4: add2--;break;
  176.                                                         case 5: rst24=24;break;
  177.                                                         case 6: cnt1++;break;
  178.                                                         case 7: x = add1; add1 = add2; add2 =x;break;
  179.                                                         case 8: cnt2++;break;
  180.                                                         case 9: sec = sec+60; break;
  181.                                                         case 10: sec = sec-60;break;
  182.                                                         default: break;
  183.                                                 }
  184.                                                 

  185.                                         }
  186.                                         backup[i][j] = KeySta[i][j];
  187.                                 }
  188.                         }        
  189.                 }                  
  190.         
  191.         
  192. }



  193. void main()
  194. {
  195.         EA = 1;
  196.         TMOD = 0X01;
  197.         TH0 = 0XFC;
  198.         TL0 = 0X67;
  199.         ET0 = 1;
  200.         TR0 = 1;

  201.         add1 = add2 = 0;
  202.         while(1)
  203.         {
  204.                 keys();
  205.                 s600and24();        
  206.         }

  207. }

  208. //T0中断服务函数
  209. void InterruptTimer0()interrupt 1
  210. {
  211.         static int cnt = 0;

  212.         TH0 = 0XFC;
  213.         TL0 = 0X67;

  214.         cnt ++ ;
  215.         keyx();
  216.         LED() ;
  217.         if(cnt >= 1000)
  218.         {
  219.                 cnt = 0;
  220.                 flagls = 1;
  221.         }
  222.         buzz();

  223. }
复制代码

所有资料51hei提供下载:
篮球计分计时.rar (2.34 MB, 下载次数: 35)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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