书写的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); //数码管显示内容
}
}
|