自动化—单片机—有线抢答器的设计

功能需求概述

源代码:

#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code seg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};     //共阳极数码管编码表0-9显示
sbit key1 = P1^0;
sbit key2 = P1^1;
sbit key3 = P1^2;
sbit key4 = P1^3;
sbit begin = P2^1;
sbit clear = P2^2;
sbit addtime = P3^2;            //按键定义
sbit P2_4 = P2^4;
sbit P2_5 = P2^5;
sbit P2_6 = P2^6;
sbit P2_7 = P2^7;              //数码管显示控制
sbit sounder = P3^7;          //喇叭控制
bit key1_flag = 0;
bit key2_flag = 0;
bit key3_flag = 0;
bit key4_flag = 0;
bit begin_flag = 0;
bit clear_flag = 0;           //按键标志位
bit a = 0;
uchar second = 0;
uchar b=0;
uchar c=0;
uchar i=0;
uchar j=1;
uchar k=0;
uchar number=0;
uchar number_display=0;

void delay(uint m)
{
    uchar n;
    while(m--)
    {
        for(n=0;n<120;n++);
    }
}
void display(uchar number,uchar second)    // 数码管显示驱动函数
{
    uchar second_first,second_second;
    second_first=second/10;
    second_second=second%10;           //将秒数分成两位
    P2_7=0;
    P2_4=1;          //选通第一个数码管
    P0=0xc0 ;   //显示0
    delay(2);
  P2_4=0;
    P2_5=1;         //选通第二个
    P0 = seg[number];           //显示编码数字
    delay(2);
    P2_5=0;
    P2_6=1;                       //选通第三个
    P0=seg[second_first];               //显示一位秒数
    delay(2);
    P2_6=0;
    P2_7=1;                                    //选通第四个
    P0=seg[second_second];                    //显示另一位秒数
    delay(2);
}

void display2()               //显示00功能
{
    P2_7=0;
  P2_6=1;              //选通一位秒表数码管
    P0 =seg[0];                     //显示0
    delay(2);
    P2_6=0;
    P2_7=1;            //选通另一位秒表数码管
    P0=seg[0];                    //显示0
    delay(2);
}

uchar key_scan4()     //四位抢答键扫描函数
{
    if(key1==0)     //如果按键1按下
    {
        delay(10);                    //防抖动延时
        if((key1==0)&&(!key1_flag))            //如果仍旧按下
        {
            key1_flag=1;
            number=1;                                //数字变量赋值1
            number_display=number;
        }
    }
    else
    {
        key1_flag = 0;
        number = 0;
    }
    if(key2==0)
    {
        delay(10);
        if((key2==0)&&(!key2_flag))
        {
            key2_flag=1;
            number=2;
            number_display=number;
        }
    }
    else
    {
        key2_flag=0;
        number=0;
    }
    if(key3==0)
    {
        delay(10);
        if((key3==0)&&(!key3_flag))
        {
            key3_flag=1;
            number=3;
            number_display=number;
        }
    }
    else
    {
        key3_flag=0;
        number=0;
    }
    if(key4==0)
    {
        delay(10);
        if((key4==0)&&(!key4_flag))
        {
            key4_flag=1;
            number=4;
            number_display=number;
        }
    }
    else
    {
        key4_flag=0;
        number=0;
    }
    if(number_display!= 0)
    {
        return 1;
    }
    else
    {
        return 0;                        //返回值控制是否有键按下
    }
}

void begin_keyscan()    //开始键扫描函数
{
    if(begin==0)            //启动按下
    {
        delay(10);                //防抖动延时
        if((begin==0)&&(!begin_flag))    //如果还是按下,同时标志位为0
        {
            begin_flag=1;     //标志位置1
            sounder=0;          //喇叭响
            j=1;
            b=0;                   //辅助循环变量
            a=1;
      if(second!=0)                //秒数不为0
          {
               TR0=1;                       //打开定时器0
          }
      }
    }
    else
    {
        begin_flag=0;
    }
}
void reset_keyscan()    //复位键扫描函数
{
  if(clear==0)
    {
        delay(10);           //防抖动
        if((clear == 0)&&(!clear_flag))//如果仍旧按下
        {
            clear_flag=1;
            number_display=0;
            sounder=1;                                //关闭喇叭
            j=0;
            b=1;                                           //循环控制变量赋值,可跳出主程序的某个死循环
        }
    }
    else
    {
        clear_flag=0;
    }
}

void main()
{
    TMOD=0x01;
    TH0=0x3c;
    TL0=0xb0;               //定时0.05s
    EA=1;
    EX0=1;
    ET0=1;
    IT0=1;
    TR0=0;
    while(1)
    {
        begin_keyscan();          //判断是否按了开始
        reset_keyscan();            //判断是否复位
        second=c;                    //每次将按键加的秒数实时显示
        while(a)                //当开始按下
        {
            while(!key_scan4())     //当无人抢答
            {
                display(number_display,second);          //显示号码和秒数,一秒后时间减一显示
                while((second==0)&&(j==1))                //减到0同时j=1
                {
                  display2();                           //显示00
                    sounder=0;                 //报警
                    reset_keyscan();                   //按下复位j=0,跳出循环
                }
                if(second==0)                           //如果秒数减到0,跳出抢答循环
                {
                  break;
                }
            }
            TR0=0;                      //关闭定时器
            k=0;                      //复位0
            while(b==0)
            {
                 display(number_display,second);  //显示当前数据
                 reset_keyscan();
            }
            a=0;
            break;
        }
        display(number_display,second);
    }
}

void timer0() interrupt 1
{
    TH0=0x3c;
    TL0=0xb0;
    k++;
    if(k==10)       //0.5s控制关闭喇叭
    {
      sounder=1;
    }
    if(k==20)          //1s控制秒数倒计时
    {
        k=0;
        second--;
        if(second==0)
        {
            TR0=0;
            number_display=0;
            a=0;
        }
    }
}

void int0() interrupt 0     //外部中断,当加时按钮按下一次加时间1S
{
  if(addtime==0)
  {
    if(i<=29)            //变量控制增加秒数直到30
      {
      i++;
        c=c+1;
      }
      else
    {
          i=0;
          c=0;
        }
   }
}

代码写的逻辑很清楚,注释和很明确。推荐自动化的同学细细研读。

最后小剧场:

事情起因:卢思毅同学邀请本人代画此程序设计流程图,当时是一口答应了;后来才发现画这个程序流程图是有多难。后来到了交图时间,只能草草收场,十分尴尬;没能给学霸菇凉画出来,还耽误人时间,十分抱歉。

源代码版权声明归卢思毅所有,在此有本人只进行总结和归纳,弥补自己对单片机领域的不足。

研究汇编语言,最好看是多看看单片机这块儿。

时间: 2024-08-24 03:16:18

自动化—单片机—有线抢答器的设计的相关文章

基于单片机的光控路灯设计含程序和仿真图

基于单片机的光控路灯设计含程序和仿真图本设计是以光敏电阻对于外界光线强弱的感应能力为基础进行的路灯自动化控制系统设计. 当光线强度弱到一定程度的时候, 路灯就会自动灭掉: 当光线强到一定程度的时候, 路灯就会自动开启. 本设计以当外界光线强度弱到使光敏电阻阻值大于等于 200 欧的时候, LED 灯会自动开启:小于 200 欧的时候,自动关闭.完整的资料在闯客网技术论坛可以免费下载,资料群:613377058下载地址:https://bbs.usoftchina.com/thread-21051

&ldquo;耐撕&rdquo;团队第一次讨论&mdash;&mdash;&ldquo;抢答器&rdquo;需求分析

团队名称:"耐撕" 团队成员:齐嘉亮.刘伟硕.濮成林.郑蕊 项目名称:"抢答器"(有待改善) 第一次讨论 时间:20160316 地点:软件所 人员:全体 内容:需求分析 主要内容: 本次希望开发一个手机软件,具有抢答器的功能,主要应用在辩论赛.知识竞赛等需要抢答的比赛中.今后经过进化,也可用于抢红包,抢女朋友,抢钱,抢银行等其它场合. 一.角色: 初步确定抢答器的角色有以下三种: 1. 抢答者(图中为普通用户) 2. 主持人 3. 系统管理员 二.针对不同用户,确

调试器开发实例_调试器框架设计

作为一个安全开发人员离不开调试器,它可以动态显示程序的执行过程,对于解决程序问题有极大的帮助,这些文章记录了我开发一个调试器雏形的过程,希望对你有帮助.或许我写的代码很拙劣,还请大家多多见谅! 我们使用  Microsoft Visual Studio 6.0 VC编译器来作为我们的开发工具想对一个程序进行调试,首先要做的当然是启动这个程序,这要使用CreateProcess这个Windows API来完成.例如: 1 // LilisiDebug.cpp : Defines the entry

【matlab】陷波器的设计

源代码: %陷波器的设计 %陷波器的传输函数为 %        B(1/z)       (z-exp(j*2*pi*f0))*(z-exp(-j*2*pi*f0)) %H(z) = -------- =  -------------------------------------------- %        A(1/z)      (z-a*exp(j*2*pi*f0))*(z-a*exp(-j*2*pi*f0)) %其中f0为陷波器要滤除信号的频率,a为与陷波器深度相关的参数,a越大,

Linux进程调度器的设计--Linux进程的管理与调度(十七)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度 前景回顾 进程调度 内存中保存了对每个进程的唯一描述, 并通过若干结构与其他进程连接起来. 调度器面对的情形就是这样, 其任务是在程序之间共享CPU时间, 创造并行执行的错觉, 该任务分为两个不同的部分, 其中一个涉及调度策略, 另外一个涉及上下文切换. 内核必须提供一种方法, 在各个进程之间尽可能公平地

[连载]《C#通讯(串口和网络)框架的设计与实现》-4.设备驱动管理器的设计

目       录 第四章           设备驱动管理器的设计... 2 4.1           接口定义... 2 4.2           设备容器... 7 4.3           生成设备ID.. 7 4.4           对设备容器操作的互斥... 8 4.5           获得设备列表... 8 4.6           设备计数器的特殊用处... 8 4.7           小结... 10 第四章     设备驱动管理器的设计 设备驱动管理器是对

[原创]基于51单片机的红外遥控课程设计

[注]: 一眨眼,大学接近尾声,具有找工作需要,所以把大学做的电子设计“劣作”放上来.希望考研失意,还能赶上“好工作”的春招班车.如果大伙有什么工作推荐也可以联系我哦,因为一年考研少接触了这方面,所以难免有些生疏.但请相信我!给我机会我会很认真学的! 邮箱:[email protected] 转载请注明出处呀! 基于51单片机的红外遥控课程设计 目录 第一章 设计简介... 3 第二章 系统方案... 3 一.设计方案对比... 3 二.方案设计... 4 第三章 硬件设计... 5 一.红外遥

微处理器原理与接口课程设计-八路抢答器

1.设计内容 ①抢答开关电路分别设定选手抢答键8个.主持人开始抢答键和复位键. ②系统工作后,首先由主持人按下开始键,同时单片机进入10秒倒计时并显示. ③选手们开始抢答,如果在10秒内无人抢答,则红灯全部亮起,等待主持人按复位键,进入下一题. ④若有人抢答,选手对应的抢答指示灯点亮,LED显示器上同步显示抢答选手的编号,表示抢答成功.同时封锁输入电路,禁止其他选手抢答 ⑤抢答成功后,单片机自动进入60秒回答问题倒计时 ⑥若选手在60秒内回答完问题并回答正确,抢答成功,且显示有效. ⑦主持人按下

[连载]《C#通讯(串口和网络)框架的设计与实现》- 11.调试器的设计

目       录 第十一章     调试器设计... 2 11.1         调试接口... 2 11.2         界面方式调试... 3 11.3         命令行方式调试... 5 11.4         小结... 6 第十一章      调试器设计 SuperIO 框架平台设计.开发完毕后,想把代码编译成程序集(DLL),二次开发都通过引用DLL实现接口.继承类库来实现驱动和插件的开发,SuperIO框架的代码不会轻易去改变.这是框架设计最终要达到的效果,但是在二