找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的抢答器(程序+仿真)

[复制链接]
跳转到指定楼层
楼主
    本程序是基于51单片机的8位抢答器,仿真软件用proteus8.0以上的版本打开,若软件版本过低,可参考PNG格式图片绘制仿真图。 基于51单片机与数码管的抢答器仿真.zip (402.17 KB, 下载次数: 21)
    开机时数码管显示EA一段时间,然后显示00。第一步,按K_3或者K_2设定思考时间(总时间),K_3按一次加5秒,K_2按一次减5秒。第二步,设定好时间后按K_1确认开始。在3秒之后进入总时间计时,时间到后无人抢答自动结束。按k1~k8抢答,数码管显示抢答号数。最后,按K_4清零……
    但是就怕别人在开始的时候一直按着抢答键不放,然后开始时直接抢成功,所以有没有大神帮我解决这个问题?

抢答器仿真.png (180.46 KB, 下载次数: 81)

抢答器仿真.png
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:319666 发表于 2019-11-22 20:47 | 只看该作者
就像正在喊预备开始一样,你喊着预备,我就开始按着不放了,等你喊开始,我已经是成功了……怎么解决这个bug问题?
回复

使用道具 举报

板凳
ID:584814 发表于 2019-11-22 21:03 | 只看该作者
可以在K1按下前扫描按键,对已按下的设置为无效。
一般是没这个开始键而用人喊的,也就是个大概时间,对总提前按键的做处罚。
回复

使用道具 举报

地板
ID:319666 发表于 2019-11-22 21:05 | 只看该作者
这是原代码?希望各位大神帮我修改,解决问题
  1. #include <reg51.H>
  2. sbit k1=P1^0;
  3. sbit k2=P1^1;
  4. sbit k3=P1^2;
  5. sbit k4=P1^3;
  6. sbit k5=P1^4;
  7. sbit k6=P1^5;
  8. sbit k7=P1^6;
  9. sbit k8=P1^7;
  10. sbit k_1=P3^0;
  11. sbit k_2=P3^1;
  12. sbit k_3=P3^2;
  13. sbit k_4=P3^3;
  14. sbit beep=P3^7;   
  15. unsigned int ms;          //毫秒
  16. unsigned int s,t0;              //显示值
  17. unsigned char biaozhi,buzhou=0;        //抢答标志,步骤
  18. unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};
  19. void delay(unsigned int t)//延时
  20. {  
  21.     unsigned int i,j;
  22.     for(i=0;i<t;i++)
  23.     for(j=0;j<110;j++);
  24. }
  25. void disp()//显示
  26. {
  27.    unsigned int ge,shi;
  28.    ge=s%10;          //提取个位
  29.    shi=s/10;  //提取十位
  30.    P2=0xfe;
  31.    P0=led[ge];  //显示个位
  32.    delay(5);
  33.    P2=0xfd;
  34.    P0=led[shi];        //显示十位
  35.    delay(5);
  36. }
  37. void ea()//显示开机界面
  38. {
  39.         unsigned char ci;
  40.         while(ci<200)//循环200次(持续一段时间)
  41.         {
  42.                 P2=0xfe;
  43.                 P0=0x77;  //显示A
  44.                 delay(5);
  45.                 P2=0xfd;
  46.                 P0=0x79;        //显示E
  47.                 delay(5);
  48.                 ci++;
  49.         }
  50. }
  51. void keys()        //抢答按键
  52. { /*抢答之后显示数值,改变标志终止抢答*/
  53.     if(k1==0&&biaozhi==0){s=1;biaozhi=1;beep=0;delay(500);beep=1;}         
  54.     if(k2==0&&biaozhi==0){s=2;biaozhi=1;beep=0;delay(500);beep=1;}
  55.     if(k3==0&&biaozhi==0){s=3;biaozhi=1;beep=0;delay(500);beep=1;}
  56.     if(k4==0&&biaozhi==0){s=4;biaozhi=1;beep=0;delay(500);beep=1;}
  57.     if(k5==0&&biaozhi==0){s=5;biaozhi=1;beep=0;delay(500);beep=1;}
  58.     if(k6==0&&biaozhi==0){s=6;biaozhi=1;beep=0;delay(500);beep=1;}
  59.     if(k7==0&&biaozhi==0){s=7;biaozhi=1;beep=0;delay(500);beep=1;}
  60.     if(k8==0&&biaozhi==0){s=8;biaozhi=1;beep=0;delay(500);beep=1;}
  61. }
  62. void set_time()        //设置时间,一次5秒
  63. {
  64.    if(k_2==0&&biaozhi==0&&s>0)
  65.    {
  66.       while(k_2==0);
  67.           s-=5;
  68.    }
  69.    if(k_3==0&&biaozhi==0&&s<95)
  70.    {  
  71.       while(k_3==0);
  72.              s+=5;
  73.    }
  74. }
  75. void main()
  76. {
  77. /*配置定时器*/
  78.   TMOD=0x01;
  79.   TH0=(65536-50000)/256;
  80.   TL0=(65536-50000)%256;
  81.   EA=1;
  82.   ET0=1;
  83.   ea();//开机显示EA
  84.   while(1)
  85.   {          
  86.      if(buzhou==0)         set_time();
  87.          if(k_1==0&&biaozhi==0&&P1==0xff&&s!=0)//开始抢答
  88.          {
  89.              while(k_1==0);
  90.                  for(t0=3;t0>0;t0--)
  91.          {
  92.                          P2=0xfe;
  93.                          P0=led[t0]; //3秒倒计时
  94.                          beep=0;delay(80);beep=1;                  
  95.                  delay(1000);                          
  96.          }
  97.                  P2=0xfc;
  98.                  P0=0x40;
  99.                  beep=0;delay(1000);beep=1;
  100.                  buzhou=1;
  101.              TR0=1;        //打开定时器开关          
  102.          }
  103.          if(P1!=0xff&&buzhou==1&&t0==0) //抢答
  104.          {         
  105.              TR0=0;//关闭定时器开关
  106.              keys();
  107.                  buzhou=3;
  108.          }
  109.          if(k_4==0)        //清除
  110.      {
  111.             beep=k_4;
  112.                 while(k_4==0);
  113.                 TR0=0;
  114.                 s=0;
  115.                 biaozhi=0;
  116.                 buzhou=0;
  117.                 beep=1;
  118.      }            
  119.          disp(); //显示
  120.   }
  121. }
  122. void zhongduan() interrupt 1
  123. { /*启动定时器*/
  124.   TH0=(65536-50000)/256;
  125.   TL0=(65536-50000)%256;//50000=50毫秒
  126.   ms++;
  127.   if(ms==20&&s>0)//50毫秒x20次=1秒
  128.   {
  129.         ms=0;
  130.     s--;  //倒计时
  131.         if(s==0)
  132.         {
  133.             TR0=0;
  134.                    biaozhi=0;
  135.                 buzhou=0;
  136.                 beep=0;       
  137.         }       
  138.   }         
  139. }
复制代码
回复

使用道具 举报

5#
ID:245004 发表于 2019-11-22 22:22 | 只看该作者
暂时没下载你的zip,所以说的不一定准确,你可以用状态来区分时间段,在抢答之前的时间段,在主函数的"while(1){}"循环里面检测“if(P1 != 0xff)"来判断是否有人按下按键。
回复

使用道具 举报

6#
ID:123289 发表于 2019-11-23 10:21 | 只看该作者
很简单:只以开关的边沿信号为准,不认开关的电平信号。
回复

使用道具 举报

7#
ID:123289 发表于 2019-11-23 10:27 | 只看该作者
学过触发器与锁存器吗?道理可以借鉴。
只认边沿,不认电平也不是最佳方案。留下空间,让你自己再发恢一下。点到了。

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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