标题:
有倒计时功能的八路抢答器
[打印本页]
作者:
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 主持人按下复位键后可以重新开始抢答。
源程序如下:
//有倒订时功能的八路抢答器C语言程序:
#include "AT89X52.h"
#define uint unsigned int
#define uchar unsigned char
#define LCDPORT P2 //LCD数据线
#define KEY P3 //八路抢答按键
#define NO_KEY 25 //八路抢答按键
sbit lcdrs=P1^0;
sbit lcden=P1^1;
sbit speaker=P1^2; //控制蜂鸣器
sbit select=P1^3; //选择分或秒的调整位
sbit light=P1^4;
sbit begin=P1^5; //开始键
sbit rst=P1^6; //复位键
sbit set=P1^7; //设置时间键
uchar table[]="00:15"; //初始值的设定
void delay(uint z); //延时z毫秒
void write_com(uchar com); //写指令
void write_data(uchar date); //写数据
void lcd_init(); //液晶初始化
void timer_init(); //定时器初始化
void display(uchar miao); //显示时间
void display1(uchar fen);
void restart();
void set_time(uchar temp);
uchar keyscan(); //键盘扫描程序
uint aa,bb,cc,dd; //用于计数
uchar start; //开始标志
uchar stop; //结束标志
uchar reset; //复位标志
uchar miao=15;
uchar fen;
bit lockflag; //锁定标志,标志着已经有人抢答成功
bit spflag; //开始声响标示
bit ovflag;//超时声响标志
void main()
{
uchar a;
lcd_init();
timer_init();
while(1)
{
a= keyscan();
if(a!=NO_KEY)
{
set_time(a); //设定时间
if(a==10) //按下开始键
{
start=1; //第一次按下就要开始抢答
light=0; //灯亮表示开始
TR0=1; //启动定时器
TR1=1;
spflag=1; //标志开始的声响
}
if(a==9) //按下复位键
{
restart(); //复原到初始状态
}
if(start) //已经按下开始键后才作下面处理
{
if(a>=0&&a<8&&lockflag==0)
{
write_com(0x80+0x40) ;
write_data(0x30+a);
TR0=0; //关闭定时器停止计时
lockflag=1; //锁定
}
}
}
}
}
/******设定时间*******/
void set_time(uchar temp)
{
if(temp==8) //调整时间
{
if(cc==1) //调整秒
{
miao+=5;
if(miao==60)
miao=0;
display(miao); //更新显示数据
write_com(0x80+4);
write_com(0x0f); //出现光标并让光标闪烁
}
if(cc==2) //调整分
{
fen++;
if(fen==5)
{
fen=0;
}
display1(fen); //更新显示数据
write_com(0x80+1); //起到固定光标位置的作用
write_com(0x0f); //出现光标并让光标闪烁
}
}
if(temp==11) //选择调整分或秒位
{
TR0=0;
if(cc==1) //调整秒时间
{
write_com(0x80+4);
write_com(0x0f); //出现光标并让光标闪烁
}
if(cc==2) //调整分时间
{
write_com(0x80+1);
write_com(0x0f); //出现光标并让光标闪烁
}
if(cc==3)
{
write_com(0x0c); //让光标消失
}
}
}
void restart()
{
uchar num;
start=0;
TR0=0; //关闭定时器才能停止计时
TR1=0;
miao=0;
fen=0;
spflag=0;
ovflag=0;
lockflag=0; //各种标志清零
write_com(0x80) ;
for(num=0;num<5;num++)
{
write_data(table[num]) ; //显示清零
}
write_com(0x80+0x40) ;
write_data(' ');
}
/*****显示秒*******/
void display(uchar miao)
{
uchar shi,ge;
shi=miao/10;
ge=miao%10;
write_com(0x80+3) ;
write_data(0x30+shi);
write_data(0x30+ge);
}
/*****显示分*****/
void display1(uchar fen)
{
uchar shi,ge;
shi=fen/10;
ge=fen%10;
write_com(0x80) ;
write_data(0x30+shi);
write_data(0x30+ge);
}
/******定时器0的中断服务程序******/
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
aa++;
if(aa==20)
{
aa=0;
miao--;
if(miao==0)
{
if(fen==0)
{
stop=1; //时间到了,抢答超时
TR0=0; //关闭定时器
light=1; //把灯也关了
TR1=1; //开启定时器1,响声
ovflag=1; //超时标志
}
else
{
miao=59;
fen--;
}
}
display(miao); //更新显示数据
display1(fen);
}
}
/*******定时器1的中断服务程序*******/
void timer1() interrupt 3
{
TH1=(65536-500)/256;
TL1=(65536-500)%256; //重装初值
if(spflag) //开始时先响500ms
{
speaker=!speaker;
dd++;
if(dd>1000)
{
dd=0;
TR1=0; //停止定时器
}
}
if(ovflag) //超时声响
{
dd++;
if(dd>3000)
{
dd=0;
TR1=0;
}
if(dd%2==0)
{
speaker=!speaker;
}
}
}
/******定时器初始化*******/
void timer_init()
{
TMOD=0x11; //工作方式的选择
TH0=(65536-50000)/256;
TL0=(65536-50000)%256; //50ms
ET0=1;
TH1=(65536-500)/256;
TL1=(65536-500)%256; //0.5ms
ET1=1;
EA=1;
TR0=0;
TR1=0;
}
/*****键盘扫描程序********/
uchar keyscan()
{
uchar key=NO_KEY;
if(KEY!=0xff)
{
delay(5); //延时5m作消抖处理
if(KEY!=0xff) //确认有按键按下
{
key=KEY;
switch(key)
{
case 0xfe: key=0;
break;
case 0xfd: key=1;
break;
case 0xfb: key=2;
break;
case 0xf7: key=3;
break;
case 0xef: key=4;
break;
case 0xdf: key=5;
break;
case 0xbf: key=6;
break;
case 0x7f: key=7;
break;
}
while(KEY!=0xff) ; //等待松手
}
}
if(set==0)
{
delay(5); //延时5m作消抖处理
if(set==0)
{
key=8;
while(!set) ;
}
}
if(rst==0)
{
delay(5); //延时5m作消抖处理
if(rst==0)
{
key=9;
while(!rst) ;
}
}
if(begin==0)
{
delay(5); //延时5m作消抖处理
if(begin==0)
{
key=10;
while(!begin) ;
}
}
if(select==0)
{
delay(5); //延时5m作消抖处理
if(select==0)
{
cc++;
if(cc==4)
{
cc=0;
}
key=11;
while(!select) ;
}
}
return(key) ;
}
/****延时z毫秒*******/
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--) ;
}
/***液晶写指令******/
void write_com(uchar com)
{
lcdrs=0;
P2=com;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
/****液晶写数据******/
void write_data(uchar date)
{
lcdrs=1;
P2=date;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
/***液晶初始化********/
void lcd_init()
{
uchar num;
lcden=0;
write_com(0x38) ; //初始化
write_com(0x0c) ; //打开光标 0x0c不显示光标 0x0e光标不闪,0x0f光标闪
write_com(0x01) ; //清显示
write_com(0x80) ;
for(num=0;num<5;num++)
{
write_data(table[num]) ;
}
}
复制代码
作者:
avalycoris
时间:
2015-12-22 15:14
过来看看~
作者:
MX安心
时间:
2016-6-20 11:38
过来看看~
作者:
houniao
时间:
2019-7-25 09:46
学习学习
作者:
鹏博士PBs
时间:
2019-7-25 11:01
51单片机的8路抢答器
作者:
whiteM3
时间:
2019-7-29 10:46
图文不符
作者:
奔跑步
时间:
2020-5-4 17:12
谢谢分享
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1