|
(原创!)基于51单片机的五路数显抢答器设计
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
要求如下:
程序难点分析:
1、抢答的判断,处于开始抢答环节还是不处于抢答环节,标志位要控制好。
2、灯的闪烁问题,需要通过计数的形式解决,否则数码管和LED一起闪烁。
附件有完整的程序(注释详细)+仿真原件+设计说明书+PCB图+原理图!在附件!!!
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件)
单片机源程序代码:#include<reg51.h>
#include<intrins.h>
sbit smg1=P2^0; //定义数码管第一位
sbit smg2=P2^1; //定义数码管第二位
sbit deng1=P2^3; //灯1号
sbit deng2=P2^4; // 灯2号
sbit deng3=P2^5; // 灯3号
sbit deng4=P2^6; // 灯4号
sbit deng5=P2^7; // 灯5号
sbit keyksqd=P3^7; //定义开始按键
sbit spk=P3^6; //定义蜂鸣器
int dingshi;js; //初始倒计时时间
int keyhao; //矩阵键值
int buzzbiaozhi=1; //10S倒计时结束后蜂鸣器响一下的标志位
int biaozhi1=0,biaozhi2=0,biaozhi3=0,biaozhi4=0,biaozhi5=0; //正确抢答唯一
int xxxx=0; //犯规抢答标志位
int flagD=0; // 控制是否显示倒计时
int zqqd,fgqd; //zqqd正确抢答,fgqd犯规抢答
int jishu; //用来控制LED闪烁的快慢,防止数码管闪烁
int table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0X71}; // 数码管段码0 1 2 3 4 5 6 7 8 9 f
//******延时子程序****//
void delayms(unsigned z) //定义毫秒
{
unsigned x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void Timer0_init() //定时器0初始化
{
js=0;
TMOD=0x01; //设置定时器0为工作方式1(M1M0为01)
TH0=(65536-50000)/256; //装初值12M晶振定时50ms数为50000,1US是1000初始值,所以50ms是5万
TL0=(65536-50000)%256;
ET0=1; //开定时器0中断
EA=1; //开总中断
}
void timer0() interrupt 1 using 1 //定时器0中断服务函数
{
TH0=(65536-50000)/256; //装初值12M晶振定时50ms数为50000
TL0=(65536-50000)%256;
js++; //叠加20次
if(js==20)
{
js=0; //清空
dingshi--; //产生1s的倒计时
}
}
///矩阵按键//
unsigned char key_juzhen(void)
{
unsigned key_value=0;
P1=0xf7;//给第一列赋值0,其余全为1
if(P1!=0xf7)//判断第一列按键是否按下
{
delayms(10);//消抖
switch(P1)//保存第一列按键按下后的键值
{
case 0x77: key_value=1;break; //记录键值1
case 0xb7: key_value=5;break; //记录键值5
case 0xd7: key_value=9;break; //记录键值9
case 0xe7: key_value=13;break; //记录键值13
}
}
while(P1!=0xf7);//等待按键松开
P1=0xfb;//给第二列赋值0,其余全为1
if(P1!=0xfb)//判断第二列按键是否按下
{
delayms(10);//消抖
switch(P1)//保存第二列按键按下后的键值
{
case 0x7b: key_value=2;break; //记录键值13
case 0xbb: key_value=6;break; //记录键值13
case 0xdb: key_value=10;break; //记录键值13
case 0xeb: key_value=14;break; //记录键值13
}
}
while(P1!=0xfb);//等待按键松开
P1=0xfd;//给第三列赋值0,其余全为1
if(P1!=0xfd)//判断第三列按键是否按下
{
delayms(10);//消抖
switch(P1)//保存第三列按键按下后的键值
{
case 0x7d: key_value=3;break; //记录键值3
case 0xbd: key_value=7;break; //记录键值7
case 0xdd: key_value=11;break; //记录键值11
case 0xed: key_value=15;break; //记录键值15
}
}
while(P1!=0xfd);//等待按键松开
P1=0xfe;//给第四列赋值0,其余全为1
if(P1!=0xfe)//判断第四列按键是否按下
{
delayms(10);//消抖
switch(P1)//保存第四列按键按下后的键值
{
case 0x7e: key_value=4;break; //记录键值4
case 0xbe: key_value=8;break; //记录键值8
case 0xde: key_value=12;break; //记录键值12
case 0xee: key_value=16;break; //记录键值16
}
}
while(P1!=0xfe);//等待按键松开
return key_value;
}
///倒计时函数////
void djsxs() //第一位,第二位 显示倒计时函数
{
int b1,b2;
b1=dingshi/10;
b2=dingshi%10; //将倒计时时间分成高低位
P0=table[b1];
smg1=0; //第1位显示十位
delayms(3);
smg1=1; //显示十位数字
P0=table[b2];
smg2=0; //第2位显示各位
delayms(3); //显示个位数字
smg2=1;
}
//**显示F犯规**//
void djsxs10() //高位数码管显示F 表示抢答犯规
{
P0=0X71; //高位数码管显示F
smg1=0;
delayms(3);
smg1=1;
}
////*****显示抢答选手号码*********///////
void haoma1() //第二位数码管显示1
{
P0=table[1];
smg2=0;
delayms(3);
smg2=1; //第二位数码管显示1
}
void haoma2() //第二位数码管显示2
{
P0=table[2];
smg2=0;
delayms(3);
smg2=1; //第二位数码管显示2
}
void haoma3() //第二位数码管显示3
{
P0=table[3];
smg2=0;
delayms(3);
smg2=1; //第二位数码管显示3
}
void haoma4() //第二位数码管显示4
{
P0=table[4];
smg2=0;
delayms(3);
smg2=1; //第二位数码管显示4
}
void haoma5() //第二位数码管显示5
{
P0=table[5];
smg2=0;
delayms(3);
smg2=1; //第二位数码管显示5
}
void main()
{
jishu=0; //记录多少毫秒累加
dingshi=10; //修改倒计时初始值
Timer0_init(); //初始化定时器中断
while(1)
{
// smg2=0; //上电数码管不亮,因为非门取反
// smg1=0; //上电数码管不亮,因为非门取反
keyhao=key_juzhen();
switch(zqqd) //显示抢答的号码
{
case 1:haoma1(); break;
case 2:haoma2(); break;
case 3:haoma3(); break;
case 4:haoma4(); break;
case 5:haoma5(); break;
default: ;
}
if(xxxx==0) ///大前提条件是,开始抢答之前有效,否则按下开始抢答数码管乱码!!!
{
switch(fgqd) //显示犯规的号码
{
case 1:djsxs10();haoma1(); break;
case 2:djsxs10();haoma2(); break;
case 3:djsxs10();haoma3(); break;
case 4:djsxs10();haoma4(); break;
case 5:djsxs10();haoma5(); break;
default: ;
}
}
///////选手正确抢答****/////////////////////
if((keyhao==1)&&(biaozhi1==1)) //在定时器运行状态下则说明1号抢答选手按下按键
{
spk=0;delayms(200);spk=1;
biaozhi1=0,biaozhi2=0,biaozhi3=0,biaozhi4=0,biaozhi5=0;
TR0=0; //启动定时器 开始倒计时
flagD=0; //显示倒计时函数
zqqd=1;
}
if((keyhao==2)&&(biaozhi2==1)) //在定时器运行状态下,key1==0 则说明2号抢答选手按下按键
{
spk=0;delayms(200);spk=1;
biaozhi1=0,biaozhi2=0,biaozhi3=0,biaozhi4=0,biaozhi5=0;
TR0=0; //启动定时器 开始倒计时
flagD=0; //显示倒计时函数
zqqd=2;
}
if((keyhao==3)&&(biaozhi3==1)) //在定时器运行状态下 则说明3号抢答选手按下按键
{
spk=0;delayms(200);spk=1;
biaozhi1=0,biaozhi2=0,biaozhi3=0,biaozhi4=0,biaozhi5=0;
TR0=0; //启动定时器 开始倒计时
flagD=0; //显示倒计时函数
zqqd=3;
}
if((keyhao==4)&&(biaozhi4==1)) //在定时器运行状态下,则说明4号抢答选手按下按键
{
spk=0;delayms(200);spk=1;
biaozhi1=0,biaozhi2=0,biaozhi3=0,biaozhi4=0,biaozhi5=0;
TR0=0; //启动定时器 开始倒计时
flagD=0; //显示倒计时函数
zqqd=4;
}
if((keyhao==5)&&(biaozhi5==1)) //在定时器运行状态下,则说明5号抢答选手按下按键
{
spk=0;delayms(200);spk=1;
biaozhi1=0,biaozhi2=0,biaozhi3=0,biaozhi4=0,biaozhi5=0;
TR0=0; //启动定时器 开始倒计时
flagD=0; //显示倒计时函数
zqqd=5;
}
////////成功抢答指示灯//////
if(zqqd==1) ///1号
{
jishu++;
delayms(20);
if(jishu==50) //计数到50次灯亮
{
deng1=0;
}
if(jishu==100) //计数到100次灯灭
{
deng1=1;
jishu=0;
}
}
//************* //
if(zqqd==2) ///2号
{
jishu++;
delayms(20); //20*50=1秒
if(jishu==50)
{
deng2=0;
}
if(jishu==100) //计数到100次灯灭
{
deng2=1;
jishu=0;
}
}
////*************//
if(zqqd==3) //3号
{
jishu++;
delayms(20);
if(jishu==50) //计数到50次灯亮
{
deng3=0;
}
if(jishu==100) //计数到100次灯灭
{
deng3=1;
jishu=0;
}
}
////****//////
if(zqqd==4) //4号
{
jishu++;
delayms(20);
if(jishu==50) //计数到50次灯亮
{
deng4=0;
}
if(jishu==100) //计数到100次灯灭
{
deng4=1;
jishu=0;
}
}
//////**************////////
if(zqqd==5) //5号
{
jishu++;
delayms(20);
if(jishu==50) //计数到50次灯亮
{
deng5=0;
}
if(jishu==100) //计数到100次灯灭
{
deng5=1;
jishu=0;
}
}
///////////////// *************犯规抢答***************************///////////////
if((keyhao==1)&&(xxxx==0)) //说明1号抢答选手按下按键犯规
{
spk=0;delayms(200);spk=1; delayms(500); spk=0;delayms(200);spk=1;
fgqd=1;
}
if((keyhao==2)&&(xxxx==0))//说明2号抢答选手按下按键犯规
{
spk=0;delayms(200);spk=1; delayms(400); spk=0;delayms(200);spk=1;
fgqd=2;
}
if((keyhao==3)&&(xxxx==0))//说明3号抢答选手按下按键犯规
{
spk=0;delayms(200);spk=1; delayms(200); spk=0;delayms(200);spk=1;
fgqd=3;
}
if((keyhao==4)&&(xxxx==0)) //说明5号抢答选手按下按键犯规
{
spk=0;delayms(200);spk=1; delayms(200); spk=0;delayms(200);spk=1;
fgqd=4;
}
if((keyhao==5)&&(xxxx==0)) //说明4号抢答选手按下按键犯规
{
spk=0;delayms(200);spk=1; delayms(200); spk=0;delayms(200);spk=1;
fgqd=5;
}
////////犯规抢答指示灯//////
if(xxxx==0) ///大前提条件是,开始抢答之前有效
{
if(fgqd==1) ///1号 犯规闪烁的快
{
jishu++;
delayms(20);
if(jishu==10) //计数10次灯亮
{
deng1=0;
}
if(jishu==20) //计数到20次灯灭
{
deng1=1;
jishu=0;
}
}
//************* //
if(fgqd==2) ///2号
{
jishu++;
delayms(20);
if(jishu==10) //计数10次灯亮
{
deng2=0;
}
if(jishu==20) //计数到20次灯灭
{
deng2=1;
jishu=0;
}
//////////******剩余程序请移步附件区域***///////////////// |
评分
-
查看全部评分
|