找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机抢答器程序 之前发过一版但是这版更加的精细 我增加了按键和定时器自动走

[复制链接]
跳转到指定楼层
楼主
ID:1152291 发表于 2025-6-25 11:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
书写的51程序我之前发过一版但是这版更加的精细 我增加了按键和定时器自动走
#include <reg52.h>

//------------------------- 引脚定义 --------------------------//
sbit BEEP = P2^0;        //蜂鸣器控制引脚,高电平有效

sbit LED1 = P2^3;        //LED1,控制引脚,低电平有效
sbit LED2 = P2^2;        //LED2,控制引脚,低电平有效
sbit LED3 = P2^1;        //LED3,控制引脚,低电平有效

//数码管引脚定义
#define duanPore        P0                //数码管段控制端口,高电平有效
sbit DIG1 = P2^4;                        //数码管第1位位选控制端口,低电平有效
sbit DIG2 = P2^5;                        //数码管第2位位选控制端口,低电平有效
sbit DIG3 = P2^6;                        //数码管第3位位选控制端口,低电平有效
sbit DIG4 = P2^7;                        //数码管第4位位选控制端口,低电平有效

//按键引脚定义
sbit KEY1 = P1^0;                //1号选手
sbit KEY2 = P1^1;                //2号选手
sbit KEY3 = P1^2;                //3号选手
sbit KEY4 = P1^3;                //4号选手
sbit KEY5 = P1^4;                //5号选手
sbit KEY6 = P1^5;                //6号选手
sbit KEY7 = P3^2;                //主持人键
sbit KEY8 = P3^3;                //设置键
sbit KEY9 = P1^6;                //增加键
sbit KEY10 =P1^7;                //减少键
#define uchar unsigned char
#define uint unsigned int



//---------------------- 全局变量定义 --------------------//

//数码管段码表,适用于共阴数码管
unsigned char code tab_duan[18] =
{
        0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,        //0~9
        0x77,0x7c,0x39,0x5e,0x79,0x71,                //A~F
        0x40,0x00                                                        //'-',关闭显示
};
unsigned char dat_buf[4] = {0,0,0,0};        //显示数据缓存区,默认上电显示"  05"
int time = 10;                                //倒计时时间
unsigned char i = 0;
unsigned int count = 0;                //计数缓存变量
bit flag_lock = 1;                         //键盘锁定标志,1:不锁定,0:锁定
uint flag=0;



//------------------------------- 函数声明 ------------------------------------//
void DelayMs(unsigned int ms);                //延时函数,单位:ms
void dig_scan(unsigned char *dat);
unsigned char KeyScan(void);                //独立按键扫描
void InitTimer0(void);                                //定时器0初始化
void alarm(void);                //报警函数
void AnswerTask(void);        //抢答任务




/* 主函数 */
void main(void)
{
        BEEP = 0;                        //上电默认关闭蜂鸣器
        LED1 = 1;
        InitTimer0();                //定时器0初始化        

        while(1)
        {
                if(KeyScan() == 7)        //如果主持人键按下,则进行抢答
                {
                        alarm();                //蜂鸣器响一声
                        AnswerTask();        //进行抢答任务
                }
                if(KEY9 == 0)                //如果按键8按下
        {   
                DelayMs(50);        //延时10ms去除按键抖动        
                if(KEY9 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
        time++;
        if(time > 260)//只显示0~9,故到9 就归零
        {
                time =0;
        }
        while(KEY9 == 0);//保持对K1的判断,松开才执行下一句
        dat_buf[1] = time/ 100 % 10;
        dat_buf[2] = time / 10;                //取出倒计时的十位数
        
        dig_scan(dat_buf);        //测试数码管显示                                
        }
        if(KEY10 == 0)                //如果按键8按下
        {   
                DelayMs(50);        //延时10ms去除按键抖动        
                if(KEY10 == 0)                        //再确认一次按键按下,表示到这按键已经稳定了
                while(KEY10 == 0);
                          time--;
                                if(time <0)//让0~9不论是加还是减都能循环
                                {
                                        time =99;
                                }
        }
            dat_buf[1] = time/ 100 % 10;;                //取出倒计时的十位数
                dat_buf[2] = time / 10;                //取出倒计时的十位数
               
                dig_scan(dat_buf);        //测试数码管显示        
        }
}

/* 延时函数,单位:ms */
void DelayMs(unsigned int ms)
{
        unsigned char a,b,c;

        while(--ms)
        {
            for(c=1;c>0;c--)
                for(b=142;b>0;b--)
                    for(a=2;a>0;a--);        
        }
}

/* 数码管显示扫描 */
void dig_scan(unsigned char *dat)
{
        /* 动态扫描处理 */
        switch(i)
        {
                case 0:
                {
                        duanPore = tab_duan[dat[0]];        //显示第1位数码管内容        
                        DIG1 = 0;
                        break;
                }
                case 1:
                {
                        duanPore = tab_duan[dat[1]];        //显示第2位数码管内容        
                        DIG2 = 0;                                                //选通第2位数码管
                        break;
                }
                case 2:
                {
                        duanPore = tab_duan[dat[2]];        //显示第3位数码管内容        
                        DIG3 = 0;                                                //选通第3位数码管
                        break;
                }
                case 3:
                {
                        duanPore = tab_duan[dat[3]];        //显示第4位数码管内容        
                        DIG4 = 0;                                                //选通第4位数码管
                        break;
                }
                default: break;        
        }
        DelayMs(5);                //扫描延时10ms,根据实际情况适当修改改延时时间
        DIG1 = 1;                        //消隐
        DIG2 = 1;
        DIG3 = 1;
        DIG4 = 1;
        ++i;                                //扫描变量循环
        if(i > 3)
                i = 0;        
}

/* 独立按键扫描 */
unsigned char KeyScan(void)
{
        if(KEY1 == 0)                //如果按键1按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY1 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 1;        //输出按键值1
        }
        if(KEY2 == 0)                //如果按键2按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY2 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 2;        //输出按键值2
        }
        if(KEY3 == 0)                //如果按键3按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY3 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 3;        //输出按键值3
        }
        if(KEY4 == 0)                //如果按键4按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY4 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 4;        //输出按键值4
        }
        if(KEY5 == 0)                //如果按键5按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY5 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 5;        //输出按键值5
        }
        if(KEY6 == 0)                //如果按键6按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY6 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 6;        //输出按键值6
        }
        if(KEY7 == 0)                //如果按键7按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY7 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 7;        //输出按键值7
        }
        if(KEY8 == 0)                //如果按键8按下
        {
                DelayMs(10);        //延时10ms去除按键抖动        
                if(KEY8 == 0)        //再确认一次按键按下,表示到这按键已经稳定了
                        return 8;        //输出按键值8
        }
        //输出按键值8
        return 0;                        //无按键按下输出0
}

/* 定时器0初始化 */
void InitTimer0(void)
{
    TMOD = 0x01;        //配置定时器0为工作模式1,16位定时器
    TH0 = (65536 - 10000) / 256;        //定时10ms
    TL0 = (65536 - 10000) % 256;
    EA = 1;                        //打开总中断
    ET0 = 1;                //打开定时器0中断
    TR0 = 0;                //上电默认关闭定时器0
}
/* 定时器0中断服务函数,10ms进一次中断 */
void Timer0Interrupt(void) interrupt 1
{
    TH0 = (65536 - 10000) / 256;        //定时10ms,重新装载计数值
    TL0 = (65536 - 10000) % 256;
           
        ++count;
        if(count > 100)                                 //1s时间计算:10ms * 100 = 1s
        {
                count = 0;                                        //计数值清零
                --time;                                                //倒计时时间减一次
                if(time <= 0)                                //如果倒计时结束,则关闭定时器0,停止倒计时,并声光报警和锁定键盘
                {
                        TR0 = 0;                                //关闭定时器0
                        BEEP = 1;                                //声光报警
                        LED1 = 0;
                        flag_lock = 0;                        //锁定键盘                                
                }                                
        }
        
}
/* 报警函数 */
void alarm(void)
{
        BEEP = 1;                //蜂鸣器响一下
        DelayMs(300);        //延时300ms
        BEEP = 0;
}
/* 实现抢答任务 */
void AnswerTask(void)
{
        unsigned char key_val;                //按键值缓存

        TR0 = 1;                                        //启动定时器0,开始倒计时
        while(1)
        {
                if(flag_lock == 1)
                {
                        key_val = KeyScan();                //获取按键值
                        switch(key_val)
                        {
                                case 1:
                                {
                                        dat_buf[0] = key_val;        //第1位数码管显示1号
                                                        //显示'-'
                                        time = 200;                                //倒计时20s,选手回答时间
                                        alarm();                                //蜂鸣器响一下
                                        flag_lock = 0;                        //锁定键盘
                                        break;
                                }
                                case 2:
                                {
                                        dat_buf[0] = key_val;        //第2位数码管显示2号
                                                        //显示'-'
                                        time = 20;                                //倒计时20s,选手回答时间
                                        alarm();                                //蜂鸣器响一下
                                        flag_lock = 0;
                                        break;
                                }
                                case 3:
                                {
                                        dat_buf[0] = key_val;        //第3位数码管显示3号
                                                        //显示'-'
                                        time = 20;
                                        alarm();                                //蜂鸣器响一下
                                        flag_lock = 0;
                                        break;
                                }
                                case 4:
                                {
                                        dat_buf[0] = key_val;        //第4位数码管显示4号
                                                //显示'-'
                                        time = 20;
                                        alarm();                                //蜂鸣器响一下
                                        flag_lock = 0;
                                        break;
                                }
                                case 5:
                                {
                                        dat_buf[0] = key_val;        //第5位数码管显示5号
                                                //显示'-'
                                        time = 20;
                                        alarm();                                //蜂鸣器响一下
                                        flag_lock = 0;
                                        break;
                                }
                                case 6:
                                {
                                        dat_buf[0] = key_val;        //第6位数码管显示6号
                                       
                                        time = 20;
                                        alarm();                                //蜂鸣器响一下
                                        flag_lock = 0;
                                        break;
                                }
                                default: break;
                        }
                }
                   dat_buf[1] = time / 100 % 10;                //取出倒计时的十位数
                dat_buf[2] = time / 10;                //取出倒计时的十位数
                dig_scan(dat_buf);                        //数码管显示内容
        }
}









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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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