#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit P37=P3^7;
sbit P07=P0^7;
sbit P06=P0^6;
uchar m,a,b,c,i,k,s,r=0;
uint j,sum,d1=0,d2=0,d3=0,d4=0,d5=0,d6=0;
uchar code tab1[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //倒計時字符表
uchar code tab[6]={0x06,0x5b,0x4f,0x66,0x6d,0x7d}; //編號字符表
//頭文件及參數定義
main() //主函數
{
//中斷服務程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EA=1; //開中斷總開關
EX0=1; //開外部中斷INT0
IT0=1; //選擇下降沿觸發方式
TMOD=0x01; //定時器T0選擇方式一
while(1) //等待中斷
//跑馬程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{ for(k=0;k<6;k++)
{
P1=0x40; //P1口位選
for(i=0;i<6;i++)
{
if(P0==0xff) //無違規操作
{
P2=tab[k]; //P2對應輸出字符
for(j=0;j<=25000;j++); //延時
P1=_cror_(P1,1); //左移一位
for(j=0;j<=25000;j++);
}
else //有違規操作
{
P1=0x02; //對應位數碼管被選中
P2=0x6d;
for(j=0;j<=1000;j++);
P1=0x04;
P2=0x78;
for(j=0;j<=1000;j++);
P1=0x08;
P2=0x3f;
for(j=0;j<=1000;j++);
P1=0x10;
P2=0x73;
for(j=0;j<=1000;j++);
}
while(r==3) //3輪答題結束后顯示對應位得分結果
{
P1=0x01;P2=tab1[d1];for(j=0;j<50;j++);
P1=0x02;P2=tab1[d2];for(j=0;j<50;j++);
P1=0x04;P2=tab1[d3];for(j=0;j<50;j++);
P1=0x08;P2=tab1[d4];for(j=0;j<50;j++);
P1=0x10;P2=tab1[d5];for(j=0;j<50;j++);
P1=0x20;P2=tab1[d6];for(j=0;j<50;j++);
}
}
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int0() interrupt 0 //進入中斷(開始搶答)
{
P0=0xff; //初始化P0口開關無人撥開
for(m=9;m>=0;m--)
{
P1=0xff;
P2=0x00;
TR0=1; TMOD=0x01;
for(s=1;s<=20;) //定時器定時一秒
{
if(P0!=0xff)
{
switch(P0) //判開關
{
case 0xfe:{P2=0x06;sum=1;}break;
case 0xfd:{P2=0x5b;sum=2;}break;
case 0xfb:{P2=0x4f;sum=3;}break;
case 0xf7:{P2=0x66;sum=4;}break;
case 0xef:{P2=0x6d;sum=5;}break;
case 0xdf:{P2=0x7d;sum=6;}break;
}
if(P0!=0xff) goto ap1;
}
TH0=15536/256;
TL0=15536%256;
do{}while(!TF0);
s++;
TF0=0;
}
if(m==0) goto ap2;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ap1:
P1=~P0;
b=P2; //把P2口字符賦值給參數b
if(P0!=0xff)
{ r++; //搶答次數
//鳴笛程序 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for(a=0;a<sum;a++)
{
for(i=1;i<200;i++)
{
P37=~P37; //P37為喇叭開關控制
for(j=0;j<=100;j++);
}
for(i=1;i<200;i++)
for(j=0;j<=100;j++);
}
//對應位亮閃編號5次 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for(c=0;c<6;c++)
{ for(j=0;j<=25000;j++);
P1=0x01;
for(j=0;j<=25000;j++);
P1=0x00;
}
P1=~P0;
//答題倒計時 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for(m=9;m>=0;m--)
{
P2=tab1[m];
TR0=1; TMOD=0x01;
for(s=1;s<=20; s++)
{
while(P07==0) //撥P07答題正確 顯示PASS
{ P1=0x01;P2=0x73;for(j=0;j<50;j++);
P1=0x02;P2=0x77;for(j=0;j<50;j++);
P1=0x04;P2=0x6d;for(j=0;j<50;j++);
P1=0x08;P2=0x6d;for(j=0;j<50;j++);
if(P07==1) //答題正確對應位加一分
{ if(sum==1) d1=d1+1;
if(sum==2) d2=d2+1;
if(sum==3) d3=d3+1;
if(sum==4) d4=d4+1;
if(sum==5) d5=d5+1;
if(sum==6) d6=d6+1;
goto ap2;
}
}
while(P06==0) //撥P06答題錯誤 顯示ff
{ P1=0xff;P2=0x71;for(j=0;j<50;j++);
if(P06==1) goto ap2;
}
TH0=15536/256;
TL0=15536%256; //定時器初值
do{}while(!TF0); //查詢等待定時
TF0=0;
}
if(P0==0xff) goto ap2; //開關撥回跳到判復位程序
}
//判開關復位程序 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ap2:
while(P0!=0xff)
{ P1=~P0; //位選對應選手數碼管
P2=b; //P2口輸出顯示對應編號
if(P0==0xff) goto ap2; //開關復位 返回主程序中斷點
}
}}
~~//
這個搶答器有跑馬,鳴笛,判違規,倒計時等功能,
需要的芯片有AT89c51/52,和一個74ls573(可選擇別的代替)
僅供大家參考,也歡迎各位指出程序中的不足,我也好改正。
|