单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

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

有倒计时功能的八路抢答器

[复制链接]
跳转到指定楼层
楼主
dzdiy 发表于 2015-4-12 02:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     有倒计时功能的八路抢答器,适合单片机初学者进行电子小制作练习用,显示部分用LCD1602作显示,四个控制按键,这个有倒计时功能的八路抢答器功能如下:
     1 八个人参赛,编号分号为0,1,2,3,4,5,6,7
     2 主持人按下开始键后,八人中抢先按下键者,液晶上显示其对应的编号,并锁定显示,后来按下者无效。
     3 按下开始键后蜂鸣器响起0.5s作提示
     4 主持人按下选择键,可以选择调整定时对象如分或秒,一次按键选中秒,二次按键选中分,三次按键恢复原状
     5 按下选择键后可按设定时间键来设定时间,秒是5s递增,分是1分递增。
     6 如果定时抢答时间到后却没有选手抢答,则本次抢答无效,系统短暂报警,并封锁输入电路禁止选手超时后抢答,时间在显示器上显示00:00
     7 主持人按下复位键后可以重新开始抢答。




源程序如下:
  1. //有倒订时功能的八路抢答器C语言程序:
  2. #include "AT89X52.h"
  3. #define  uint unsigned int
  4. #define  uchar unsigned char

  5. #define  LCDPORT P2  //LCD数据线
  6. #define  KEY   P3   //八路抢答按键
  7. #define  NO_KEY   25   //八路抢答按键
  8. sbit lcdrs=P1^0;
  9. sbit lcden=P1^1;
  10. sbit speaker=P1^2;  //控制蜂鸣器
  11. sbit  select=P1^3;  //选择分或秒的调整位
  12. sbit light=P1^4;
  13. sbit  begin=P1^5; //开始键
  14. sbit rst=P1^6;   //复位键
  15. sbit set=P1^7;   //设置时间键

  16. uchar table[]="00:15"; //初始值的设定

  17. void delay(uint z);    //延时z毫秒
  18. void write_com(uchar com);  //写指令
  19. void write_data(uchar date);  //写数据
  20. void lcd_init();   //液晶初始化
  21. void  timer_init();        //定时器初始化
  22. void  display(uchar miao);           //显示时间
  23. void  display1(uchar fen);
  24. void  restart();
  25. void  set_time(uchar temp);
  26. uchar keyscan();        //键盘扫描程序

  27. uint aa,bb,cc,dd;   //用于计数
  28. uchar start;   //开始标志
  29. uchar stop;   //结束标志
  30. uchar reset;   //复位标志
  31. uchar miao=15;
  32. uchar fen;
  33. bit  lockflag;   //锁定标志,标志着已经有人抢答成功
  34. bit spflag;   //开始声响标示
  35. bit  ovflag;//超时声响标志
  36. void main()
  37. {
  38.    uchar a;
  39.    lcd_init();
  40.    timer_init();
  41.    while(1)
  42.    {
  43.        a= keyscan();
  44.     if(a!=NO_KEY)
  45.      {   
  46.      set_time(a);   //设定时间
  47.         if(a==10)    //按下开始键
  48.        {
  49.       start=1;   //第一次按下就要开始抢答
  50.       light=0;  //灯亮表示开始
  51.       TR0=1;     //启动定时器
  52.       TR1=1;
  53.       spflag=1;   //标志开始的声响
  54.      }
  55.      if(a==9)   //按下复位键
  56.        {
  57.       
  58.        restart();  //复原到初始状态
  59.     }
  60.      
  61.      if(start) //已经按下开始键后才作下面处理
  62.       {
  63.       if(a>=0&&a<8&&lockflag==0)
  64.        {
  65.         write_com(0x80+0x40) ;
  66.         write_data(0x30+a);
  67.      TR0=0;  //关闭定时器停止计时
  68.      lockflag=1;  //锁定
  69.     }  
  70.    }
  71.     }
  72.    }
  73. }
  74. /******设定时间*******/
  75. void  set_time(uchar temp)
  76. {
  77.     if(temp==8)   //调整时间
  78.       {
  79.       if(cc==1)  //调整秒
  80.       {
  81.         miao+=5;
  82.      if(miao==60)
  83.        miao=0;
  84.      display(miao);  //更新显示数据
  85.      write_com(0x80+4);
  86.         write_com(0x0f); //出现光标并让光标闪烁
  87.       }
  88.      if(cc==2)  //调整分
  89.       {
  90.         fen++;
  91.      if(fen==5)
  92.       {
  93.         fen=0;
  94.       }
  95.       display1(fen);   //更新显示数据
  96.       write_com(0x80+1); //起到固定光标位置的作用
  97.          write_com(0x0f); //出现光标并让光标闪烁
  98.       }
  99.    }
  100.     if(temp==11)    //选择调整分或秒位
  101.      {
  102.           TR0=0;
  103.           if(cc==1)    //调整秒时间
  104.      {
  105.                    write_com(0x80+4);
  106.         write_com(0x0f); //出现光标并让光标闪烁
  107.      }
  108.     if(cc==2)   //调整分时间
  109.      {
  110.                    write_com(0x80+1);
  111.         write_com(0x0f); //出现光标并让光标闪烁
  112.      }
  113.      if(cc==3)
  114.      {
  115.         write_com(0x0c); //让光标消失
  116.    
  117.      }
  118.      }   
  119. }

  120. void restart()
  121. {
  122.    uchar num;
  123.    start=0;
  124.    TR0=0;    //关闭定时器才能停止计时
  125.    TR1=0;
  126.    miao=0;
  127.    fen=0;
  128.    spflag=0;
  129.    ovflag=0;
  130.    lockflag=0;  //各种标志清零
  131.    write_com(0x80) ;
  132.    for(num=0;num<5;num++)
  133. {
  134.      write_data(table[num]) ;   //显示清零
  135. }
  136.     write_com(0x80+0x40) ;
  137.     write_data(' ');
  138. }


  139. /*****显示秒*******/
  140. void  display(uchar miao)
  141. {
  142.    uchar shi,ge;
  143.   shi=miao/10;
  144.   ge=miao%10;
  145.   write_com(0x80+3) ;
  146.   write_data(0x30+shi);
  147.   write_data(0x30+ge);
  148. }
  149. /*****显示分*****/
  150. void  display1(uchar fen)
  151. {
  152.    uchar shi,ge;
  153.   shi=fen/10;
  154.   ge=fen%10;
  155.   write_com(0x80) ;
  156.   write_data(0x30+shi);
  157.   write_data(0x30+ge);
  158. }
  159. /******定时器0的中断服务程序******/
  160. void  timer0()  interrupt   1
  161. {
  162.   TH0=(65536-50000)/256;
  163.   TL0=(65536-50000)%256;
  164.   aa++;
  165.   if(aa==20)
  166.    {
  167.       aa=0;
  168.    miao--;
  169.    if(miao==0)
  170.      {
  171.      
  172.      if(fen==0)
  173.      {
  174.          
  175.       stop=1;  //时间到了,抢答超时
  176.       TR0=0;   //关闭定时器
  177.       light=1;  //把灯也关了
  178.       TR1=1;    //开启定时器1,响声
  179.       ovflag=1;   //超时标志
  180.      }
  181.      else
  182.       {
  183.      miao=59;
  184.      fen--;
  185.    }
  186.    
  187.   }
  188.   display(miao);  //更新显示数据
  189.   display1(fen);
  190.    }
  191. }
  192. /*******定时器1的中断服务程序*******/
  193. void  timer1()  interrupt   3
  194. {
  195.   TH1=(65536-500)/256;
  196.   TL1=(65536-500)%256;    //重装初值
  197.   if(spflag)   //开始时先响500ms
  198.    {
  199.      speaker=!speaker;
  200.   dd++;
  201.   if(dd>1000)
  202.    {
  203.      dd=0;
  204.   TR1=0;    //停止定时器
  205.    }
  206.    }
  207.    
  208.   if(ovflag) //超时声响
  209.    {
  210.      dd++;
  211.   if(dd>3000)
  212.     {
  213.        dd=0;
  214.     TR1=0;
  215.     }
  216.   if(dd%2==0)
  217.    {
  218.      speaker=!speaker;
  219.    }
  220.    }
  221.   


  222.       
  223.   
  224. }
  225. /******定时器初始化*******/
  226. void  timer_init()
  227. {
  228.   TMOD=0x11;   //工作方式的选择
  229.   TH0=(65536-50000)/256;
  230.   TL0=(65536-50000)%256; //50ms
  231.   ET0=1;

  232.   TH1=(65536-500)/256;
  233.   TL1=(65536-500)%256;   //0.5ms
  234.   ET1=1;

  235.   EA=1;
  236.   TR0=0;
  237.   TR1=0;
  238. }

  239. /*****键盘扫描程序********/
  240. uchar keyscan()
  241. {
  242.     uchar key=NO_KEY;
  243.     if(KEY!=0xff)
  244.    {
  245.        delay(5);  //延时5m作消抖处理
  246.     if(KEY!=0xff) //确认有按键按下
  247.       {
  248.        key=KEY;
  249.        switch(key)
  250.       {
  251.        case  0xfe:    key=0;
  252.          break;
  253.      case  0xfd:    key=1;
  254.          break;
  255.      case  0xfb:    key=2;
  256.          break;
  257.      case  0xf7:    key=3;
  258.          break;
  259.       case  0xef:    key=4;
  260.          break;
  261.      case  0xdf:    key=5;
  262.          break;
  263.      case  0xbf:    key=6;
  264.          break;
  265.                     case  0x7f:    key=7;
  266.          break;
  267.        }
  268.        while(KEY!=0xff) ;  //等待松手
  269.      
  270.    }
  271.    }
  272. if(set==0)
  273.    {
  274.       delay(5);  //延时5m作消抖处理
  275.    if(set==0)
  276.     {
  277.        key=8;
  278.     while(!set) ;
  279.     }
  280.    }
  281. if(rst==0)
  282.    {
  283.       delay(5);  //延时5m作消抖处理
  284.    if(rst==0)
  285.     {
  286.        key=9;
  287.     while(!rst) ;
  288.     }
  289.    }
  290. if(begin==0)
  291.    {
  292.       delay(5);  //延时5m作消抖处理
  293.    if(begin==0)
  294.     {
  295.        key=10;
  296.     while(!begin) ;
  297.     }
  298.    }
  299.   if(select==0)
  300.    {
  301.       delay(5);  //延时5m作消抖处理
  302.    if(select==0)
  303.     {
  304.        cc++;
  305.     if(cc==4)
  306.       {
  307.          cc=0;
  308.       }
  309.        key=11;
  310.     while(!select) ;
  311.     }
  312.    }
  313.   return(key) ;
  314. }
  315. /****延时z毫秒*******/
  316. void delay(uint z)
  317. {
  318.    uint x,y;
  319.    for(x=z;x>0;x--)
  320.       for(y=110;y>0;y--) ;
  321. }
  322. /***液晶写指令******/
  323. void write_com(uchar com)
  324. {
  325.   lcdrs=0;
  326. P2=com;
  327. delay(1);
  328. lcden=1;
  329. delay(1);
  330. lcden=0;
  331. }
  332. /****液晶写数据******/
  333. void write_data(uchar date)
  334. {
  335.   lcdrs=1;
  336. P2=date;
  337. delay(1);
  338. lcden=1;
  339. delay(1);
  340. lcden=0;
  341. }
  342. /***液晶初始化********/
  343. void lcd_init()
  344. {
  345.     uchar num;
  346.   lcden=0;
  347. write_com(0x38) ; //初始化
  348. write_com(0x0c) ; //打开光标    0x0c不显示光标   0x0e光标不闪,0x0f光标闪

  349. write_com(0x01) ;  //清显示
  350. write_com(0x80) ;
  351. for(num=0;num<5;num++)
  352. {
  353.      write_data(table[num]) ;
  354. }

  355. }
复制代码


评分

参与人数 1黑币 +1 收起 理由
尼古丁的味道 + 1 过来看看--

查看全部评分

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

使用道具 举报

沙发
avalycoris 发表于 2015-12-22 15:14 | 只看该作者
过来看看~
回复

使用道具 举报

板凳
MX安心 发表于 2016-6-20 11:38 | 只看该作者
过来看看~
回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;技术交流QQ群7344883

Powered by 单片机教程网

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