基于AT89S51的单片机无线双显示抢答器C代码

 

#include <REG51.h>
#include
<STRING.H>

/******************************************************************
* 自定义Macro
******************************************************************
*/

//编码的均为反向编码

#define CLEAR 0x7f //定义清空的反码
#define LED_BEGIN 0x01 // 定义开始时数码管的显示
#define LED_FOUL 0x38 // 犯规后显示字母"F",数码管编码
#define LED_C 0x31 // 字母"C"的编码
#define LED_L 0x71 // 字母"L"的编码,两个用来在主持人取消之后显示"CL"--cancel
#define GET 1 // 这个是作为一个函数的参数来混的,就是成功抢答的意思
#define FOUL 0 // 和上面的参数一起混的,犯规---这两个的用法在后面体现
#define READY 0x7e

//下面是给上位机发送的指令,对应的是cmdID
#define _STRING_READY_ 9//调整好抢答倒计时,准备开始抢答
#define _STRING_START_ 8//读秒结束,抢答开始
#define _STRING_CANCEL_ 7//取消抢答
#define _CHANGE_TIME_ 6//每次读秒
//发送1--4的指令代表抢答端的序号

//因为在板子上面采用的是12M的晶振,仿真时候采用的是11.0529M的晶振,为了方便不同时候编译方便,这里与后面的条件编译一起使程序修改参数比较方便
//#define CLOCK_FREQUENCY_12M 1

/******************************************************************
* 自定义数据类型
******************************************************************
*/
typedef unsigned
char Byte; // 一个字节
typedef unsigned int Word; // 一个字,两个字节
typedef bit Bool; // 模仿布尔型变量
//typedef sbit Port; // 本想用自定义一个端口类型的变量,比较方便,但是这句话步知道为何通不过编译

/******************************************************************
* 定义MAX7219寄存器
******************************************************************
*/
#define REG_NO_OP 0x00 // 定义空操作 register
#define DIG_1 0x01 // 定义数码管1 register
#define DIG_2 0x02 // 定义数码管2 register
#define DIG_3 0x03 // 定义数码管3 register
#define DIG_4 0x04 // 定义数码管4 register
#define DIG_5 0x05 // 定义数码管5 register
#define DIG_6 0x06 // 定义数码管6 register
#define DIG_7 0x07 // 定义数码管7 register
#define DIG_8 0x08 // 定义数码管8 register
#define REG_DECODE 0x09 // 定义解码控制 register
#define REG_INTENSITY 0x0a // 定义显示亮度 register
#define REG_SCAN_LIMIT 0x0b // 定义扫描限制 register
#define REG_SHUTDOWN 0x0c // 定义"shutdown"模式 register
#define REG_DISPLAY_TEST 0x0f // 定义"display test"模式 register
#define INTENSITY_MIN 0x00 // 定义最低显示亮度
#define INTENSITY_MAX 0x0f // 定义最高显示亮度

/*********************************************************************
* 定义硬件引脚连接
*********************************************************************
*/
sbit DATA
=P2^0; // MAX7219的数据口
sbit LOAD=P2^1; // MAX7219的锁存端口
sbit CLK=P2^2; // MAX7219的时钟端口

sbit HOST_START
=P0^0; //主持人按键,用来重新开始的按键 start
sbit HOST_CANCEL=P0^1; //主持人用来取消抢答的按键 clear

sbit SWITCH1_3
=P1^4; // 调节倒计时时间的拨码开关,下划线前面的号代表开关的序号,下划线后面的号代表该开关的数值
sbit SWITCH2_2=P1^5; // 同上
sbit SWITCH3_2=P1^6; // 同上
sbit SWITCH4_1=P1^7; // 同上

sbit BEEP
=P0^7; //定义蜂鸣器端口

#ifdef USE_SOUND
//可以通过define来选择要不要使用仿真时候的声音
sbit LS138_C=P2^4; //定义译码器输入端
sbit LS138_B=P2^5; //同上
sbit LS138_A=P2^6; //同上
sbit LS138_E1=P2^7; //定义译码器使能端
#endif

/*********************************************************************
* 定义全局变量
*********************************************************************
*/
Byte data intrCounter;
// 计时器中断次数
Byte data beginNum; // 开始倒计时的时间
Byte data counterBack; // 将中断次数放在里面以备后用
Byte data showNum; // 数码管正在显示的时间
Bool data isStart; // 是否开始抢答
Bool data isFoul; // 是否犯规
Bool data isPressed; // 是否有抢答的键按下
Byte data number_temp; // 用来记录P1口上次状态的一个变量
Bool data needResetTimes;//记录是否需要重设Timer0的溢出次数

code unsigned
char C51BOX2[3] _at_ 0x43; //使用C51Box时候防止程序跑丢

/***********************************************************************
* 共阴极七段数码管显示对应段查询表(数字0-9分别对应code_table[0]-[9])
**********************************************************************
*/
Byte code code_table_zheng[
10]=
{
0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b};

Byte code code_table[
10]=
{
0x01,0x4f,0x12,0x06,0x4c,0x24,0x20,0x0f,0x00,0x04};

/***********************************************************************
* 函数声明
**********************************************************************
*/
void MAX7219_SendByte (Byte dataout);
void MAX7219_Write (Byte reg_number, Byte dataout);
void MAX7219_DisplayChar(Byte digit, Byte character);
void MAX7219_Clear (void);
void MAX7219_SetBrightness (Byte brightness);
void MAX7219_DisplayTestStart (void);
void MAX7219_DisplayTestStop (void);
void MAX7219_ShutdownStart (void);
void MAX7219_ShutdownStop (void);
void MAX7219_Init (void);
void Delay10ms(void);
Bool GetHostStartKey (
void);
Bool GetHostCancelKey (
void);
void GetCounter(void);
Byte GetPressed(Byte KeyState);
Byte GetPressedWireless(Byte KeyState);
void IT0_Init(void);
void Timer0_Overflow();
void PressedHandle(Byte keyPressed);
void GetOrFoulHandle(Bool state);
void CancelHandle();
void SPEAKER_count (void); //声明倒计时声音函数
void SPEAKER_start(void); //声明开始抢答声音函数
void SPEAKER_get(void); //声明抢到声音函数
void SPEAKER_foul(void); // 声明犯规声音函数
void initialSerial();
void sendNumber(int number);//串口发送数字,这里发送的是CommandID
void sendString(unsigned char *string);//串口发送字符串

/***********************************************************************
* MAX7219_SendByte()
*
* 描述: 向MAX7219传送一个字节的数据
* Arguments : dataout = data to send
* Returns : none
************************************************************************
*/
void MAX7219_SendByte (Byte dataout)
{
Byte i;
for (i=8;i>0;i--)
{
Byte mask
=1<<(i-1);//mask是个掩码,取位使用
CLK=0;//MAX7219的位传入是在时钟的上升沿之前,所以在每发一位之前都要变为低电平
if (dataout&mask)
DATA
=1;
else
DATA
=0;
CLK
=1;//八个bit都传递完成后变为高电平,锁存
}
}

/***********************************************************************
* MAX7219_Write()
*
* 描述: 向 MAX7219 写命令
* Arguments : reg_number = register to write to
* dataout = data to write to MAX7219
* Returns : none
未完~
**************************************************************************
*/
void MAX7219_Write (Byte reg_number, Byte dataout)
{
LOAD
=0;//也是锁存上升沿之前的,发这两个字节之前要变为低电平
MAX7219_SendByte(reg_number);//发送寄存器地址
MAX7219_SendByte(dataout);//发送数据
LOAD=1;//变为高电平,锁存
}

/**************************************************************************
* MAX7219_DisplayChar()
*
* 描述: 使某一位显示一个数字
* Arguments : digit = digit number (0-7)
* character = character to display (0-9, A-Z)
* Returns : none
*************************************************************************
*/
void MAX7219_DisplayChar(Byte digit, Byte character)
{
MAX7219_Write(digit, character);
}

/**************************************************************************
* MAX7219_Clear()
*
* 描述: 清除所有位的显示
* Arguments : none
* Returns : none
**************************************************************************
*/
void MAX7219_Clear (void)
{
Byte i;
for (i=1; i<=2; i++)
MAX7219_Write(i, CLEAR);
//把八个数码管全都清零了,已经写反了^_^
}

/**************************************************************************
* MAX7219_SetBrightness()
*
* 描述: 设置数码管显示亮度
* Arguments : brightness (0-15)
* Returns : none
**************************************************************************
*/
void MAX7219_SetBrightness (Byte brightness)
{
brightness
&= 0x0f;
MAX7219_Write(REG_INTENSITY, brightness);
}

/**************************************************************************
* MAX7219_DisplayTestStart()
*
* 描述: 进入 test 模式
* Arguments : none
* Returns : none
**************************************************************************
*/
void MAX7219_DisplayTestStart (void)
{
MAX7219_Write(REG_DISPLAY_TEST,
1);
}

/**************************************************************************
* MAX7219_DisplayTestStop()
*
* 描述: 退出 test 模式
* Arguments : none
* Returns : none
**************************************************************************
*/
void MAX7219_DisplayTestStop (void)
{
MAX7219_Write(REG_DISPLAY_TEST,
0);
}

/**************************************************************************
* MAX7219_ShutdownStart()
*
* 描述: 进入 shutdown 模式
* Arguments : none
* Returns : none
**************************************************************************
*/
void MAX7219_ShutdownStart (void)
{
MAX7219_Write(REG_SHUTDOWN,
0);
}

/**************************************************************************
* MAX7219_ShutdownStop()
*
* 描述: 退出 shutdown 模式
* Arguments : none
* Returns : none
**************************************************************************
*/
void MAX7219_ShutdownStop (void)
{
MAX7219_Write(REG_SHUTDOWN,
1);
}

/**************************************************************************
* MAX7219_Init()
*
* Description: MAX7219初始化模块; 应该先于其他MAX7219函数而被调用
* Arguments : none
* Returns : none
**************************************************************************
*/
void MAX7219_Init (void)
{
DATA
=1;
CLK
=1;
LOAD
=1;
MAX7219_Write(REG_SCAN_LIMIT,
1);//这里设置的是扫描两个数码管
MAX7219_Write(REG_DECODE, 0x00);
MAX7219_SetBrightness(INTENSITY_MAX);
//设置最大亮度显示
MAX7219_DisplayTestStart();
MAX7219_DisplayTestStop();
MAX7219_ShutdownStop();
MAX7219_Clear();
}

/**************************************************************************
* Delay_100us()
*
* 描述: 延时100us,主要用在消除开关抖动时
* Arguments : none
* Returns : none
**************************************************************************
*/
void Delay10ms(void)
{
unsigned
char i,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
/**************************************************************************
* GetHostStartKey()
*
* Description: 取得主持人开始按键的键值
* Arguments : none
* Returns : 1-->主持人按键; 0-->主持人未按键
**************************************************************************
*/
Bool GetHostStartKey (
void)
{
if (HOST_START ==1)
return 0;
else
Delay10ms ();
//如果发现主持人按键接通,要先延时100us,防止抖动
if (HOST_START==1)
return 0;
else
return 1;//延时时候还是接通,则判断为该键确实按下
}

/**************************************************************************
* GetHostCancelKey()
*
* Description: 取得主持人取消按键的键值
* Arguments : none
* Returns : 1-->主持人按键; 0-->主持人未按键
**************************************************************************
*/
Bool GetHostCancelKey (
void)
{
if (HOST_CANCEL ==1)
return 0;
else
Delay10ms ();
//如果发现主持人按键接通,要先延时100us,防止抖动
if (HOST_CANCEL ==1)
return 0;
else
return 1;//延时时候还是接通,则判断为该键确实按下
}

/**************************************************************************
* GetCounter
*
* Description: 取得预先设置的倒计时时间
* Arguments : none
* Returns : none
**************************************************************************
*/
void GetCounter(void)
{
beginNum
=1;//在所有开关都没有拨动的时候倒计时为1秒,比设置为0秒要好
intrCounter=20;//每一秒对应的中断次数为20次
if (SWITCH1_3==1)
{
beginNum
+=3;
}
if (SWITCH2_2==1)
{
beginNum
+=2;
}
if (SWITCH3_2==1)
{
beginNum
+=2;
}
if (SWITCH4_1==1)
{
beginNum
+=1;
}
//以上判断语句为判断拨码开关状态
intrCounter=20*beginNum;//计算总扫描次数
}

/**************************************************************************
* GetPressed
*
* Description: 从P2口连接抢答端的四位来判断抢答情况
* Arguments : Byte KeyState-->P2 state
* Returns : 抢答端的号码 ; 0-->没人抢答
**************************************************************************
*/
Byte GetPressed(Byte KeyState)
{
Byte key;
//记录抢答端的号码
KeyState&=0xf0;//取P1口的低四位

switch (KeyState)
{
case 0xf0: key=0;break;//全高,无人抢答
case 0xe0: key=1;break;//只有P1.1,key1抢答
case 0xd0: key=2;break;//只有P1.2,key2抢答
case 0xb0: key=3;break;//只有P1.3,key3抢答
case 0x70: key=4;break;//只有P1.4,key4抢答
}
/*
switch (KeyState)
{
case 0x00: key=0;break;//全高,无人抢答
case 0x01: key=1;break;//只有P1.0,key1抢答
case 0x02: key=2;break;//只有P1.1,key2抢答
case 0x04: key=3;break;//只有P1.2,key3抢答
case 0x08: key=4;break;//只有P1.3,key4抢答
}
*/
//上面是在用高电平来判断抢答状态时的程序,经证明不知道为何无效

return key;
}

/**************************************************************************
* GetPressedWireless
*
* Description: P2口的高四位于Pt2272接受模块相连,该方法用来判断无线抢答序号
* Arguments : Byte KeyState-->P2 state
* Returns : 抢答端的号码 ; 0-->没人抢答
**************************************************************************
*/
Byte GetPressedWireless(Byte KeyState)
{
Byte key;
//记录抢答端的号码
KeyState&=0xf0;//取P2口的高四位

/*
switch (KeyState)
{
case 0x0f: key=0;break;//全高,无人抢答
case 0x0e: key=1;break;//只有P1.1,key1抢答
case 0x0d: key=2;break;//只有P1.2,key2抢答
case 0x0b: key=3;break;//只有P1.3,key3抢答
case 0x07: key=4;break;//只有P1.4,key4抢答
}
*/

switch (KeyState)
{
case 0x00: key=0;break;//全低,无人抢答
case 0x10: key=1;break;//只有P1.0,key1抢答
case 0x20: key=2;break;//只有P1.1,key2抢答
case 0x40: key=3;break;//只有P1.2,key3抢答
case 0x80: key=4;break;//只有P1.3,key4抢答
}
return key;
}

/**************************************************************************
* IT0_Init
*
* Description: 初始化计时器T0的状态
* Arguments : none
* Returns : none
**************************************************************************
*/
void IT0_Init(void)
{
TMOD
=0x21;//设置T0在方式1下工作,同时还要保证T1,也就是波特率所学的定时器的正常工作

#ifdef CLOCK_FREQUENCY_12M
//对使用哪种晶振进行条件编译
TH0=0x3C;//12M晶振时的装入值
TL0=0xAF;
#else
TH0
=0x4C;//11.0529M晶振时装入值
TL0=0x00;
#endif

ET0
=1;//使T0中断可以溢出
EA=1;//开启总中断
TF0=0;//溢出位清零
TR0=1;//开启T0
}

/**************************************************************************
* Timer0_Overflow() interrupt 1
*
* Description: 中断溢出服务程序, 采用的是中断方式1, 后面最好不加using选择寄存器组以免与系统用在主程序的寄存器冲突
* Arguments : none
* Returns : none
**************************************************************************
*/
void Timer0_Overflow() interrupt 1
{
static Byte times=20;//溢出次数,用20次中断来判断1秒
//这里存在重大bug,到由于有相应而停止Timer0后,再次启用时,这里的second没有回归原值

if (needResetTimes==1)
{
times
=20;
needResetTimes
=0;//已重设,不需要再次重新设置溢出次数
}

#ifdef CLOCK_FREQUENCY_12M
//对使用哪种晶振进行条件编译
TH0=0x3C;//12M晶振时的装入值
TL0=0xAF;//这两个寄存器存的是计数器的计数开始的值,计算发现这两个值累加至溢出后正好是50ms
#else
TH0
=0x4C;//11.0529M晶振时装入值
TL0=0x00;//同理,这两个寄存器存的是计数器的计数开始的值,计算发现这两个值累加至溢出后正好是50ms
#endif

times
--;
intrCounter
--;

/* 原来使用的方法
if (times==0)//每隔一秒的操作
{
MAX7219_DisplayChar(DIG_2,code_table[--showNum]); //要避免用上面的会造成显示"0"后面一秒钟,才进入开始
times=20;//重新赋值每秒计数器
if (intrCounter==0)
{
TR0=0;//关闭T0计数器
isStart=1;//计时结束,进入正常抢答
//SPEAKER_start();//开始抢答的声音
}
//待显示"0"以后就开始抢答
else
{
//SPEAKER_count();//倒计时声音
}
}
*/

if (times==0)//每隔一秒的操作
{
//if (showNum!=1) SPEAKER_count();//倒计时声音
//else SPEAKER_start();//开始抢答的声音
MAX7219_DisplayChar(DIG_2,code_table[--showNum]);//显示数字
sendNumber(_CHANGE_TIME_);//给上位机发送要显示数字的命令
times=20;//重新赋值每秒计数器
}//待显示"0"以后就开始抢答

if (intrCounter==0)
{
TR0
=0;//关闭T0计数器
isStart=1;//计时结束,进入正常抢答
}

}

/**************************************************************************
* PressedHandle
*
* Description: 按键处理
* Arguments : Byte keyPressed-->按下的按键
* Returns : none
**************************************************************************
*/
void PressedHandle(Byte keyPressed)
{
MAX7219_Clear();
//LED clear
MAX7219_DisplayChar(DIG_2,code_table[keyPressed]);//在右侧数码管显示抢答选手号码,此时没有去判断是否犯规

//给上位机发抢答选手的号码
sendNumber(keyPressed);
}

/**************************************************************************
* GetOrFoulHandle(Bool state)
*
* Description: 正常抢答或是犯规处理
* Arguments : Bool state-->是GET和FOUL两个宏的取之之一
* Returns : none
**************************************************************************
*/
void GetOrFoulHandle(Bool state)
{
if (!state)
{
MAX7219_DisplayChar(DIG_1,LED_FOUL);
//如果是犯规的话左边的LED要显示"F",foul
}
}

/**************************************************************************
* CancelHandle()
*
* Description: 处理主持人取消倒计时
* Arguments : none
* Returns : none
**************************************************************************
*/
void CancelHandle()
{
MAX7219_DisplayChar(DIG_1,LED_C);
MAX7219_DisplayChar(DIG_2,LED_L);
//主持人取消倒计时之后,两个数码管显示"CL"-->cancel
}

/**************************************************************************
* delayus()
*
* Description: 延时程序
* Arguments : t-->us
* Returns : time delayed
**************************************************************************
*/
void delayus(unsigned char t )
{
unsigned
char j;
for(;t>0;t--)
for(j=19;j>0;j--);
}

/**************************************************************************
* SPEAKER_count/start/foul/get()
*
* Description: speaker发声程序->计数/开始/犯规/抢答 四种声音
* Arguments : none
* Returns : none
**************************************************************************
*/
void SPEAKER_count(void)
{
unsigned
char i;
for (i=0;i<10;i++)
{
BEEP
=1; //点亮
delayus(20);
BEEP
=0; //熄灭
delayus(20);
}
}

void SPEAKER_start(void)
{
unsigned
char i;
for(i=0;i<200;i++)
{
BEEP
=1; //点亮
delayus(10);
BEEP
=0; //熄灭
delayus(10);
}
}

void SPEAKER_foul(void)
{
unsigned
char i;
for(i=0;i<250;i++)
{
BEEP
=1; //点亮
delayus(15);
BEEP
=0; //熄灭
delayus(17);
}

}

void SPEAKER_get(void)
{
unsigned
char i;
for(i=0;i<250;i++)
{
BEEP
=1; //点亮
delayus(10);
BEEP
=0; //熄灭
delayus(10);
}

for(i=0;i<250;i++)
{
BEEP
=1; //点亮
delayus(20);
BEEP
=0; //熄灭
delayus(20);
}
}

/**************************************************************************
* initialSerial()
*
* Description: 初始化串口
* Arguments : none
* Returns : none
**************************************************************************
*/
void initialSerial()
{
EA
=0;//关闭所有中断
TMOD=0x21;//设置T1定时器的工作模式:方式2;同时保证T0的工作模式正常.这儿太重要了
TH1=0xFA;
TL1
=0xFA;
PCON
=0x80;//设置SMOD=1
SCON=0x50;//选择工作方式1,即为UART
TR1=1;//设置好定时器并打开定时器,定好波特率9600bit/s
}

/**************************************************************************
* sendNumber(int number)
*
* Description: 通过串口发送一位数字
* Arguments : number->要发送的数字
* Returns : none
**************************************************************************
*/
void sendNumber(int number)
{
TI
=0;
SBUF
=number+48;
while(!TI);
TI
=0;
}

/**************************************************************************
* sendString(unsigned char *string)
*
* Description: 通过串口发送字符串
* Arguments : 要发送的字符串的头指针
* Returns : none
**************************************************************************
*/
void sendString(unsigned char *string)
{
do
{
SBUF
=*string;
while(!TI);
TI
=0;
string++;
}
while(*(string-1)!='\0');
}



/**************************************************************************
* 主程序
**************************************************************************
*/
void main()
{
//P1=0xff;
Byte keyPressed,i;//选手按键号码,没有的话为0
Bool hostPressed;//用来记录主持人按键取消,0为没有动作,1为取消
Byte buf[10];//设置发送缓冲区
number_temp=P1&0xf0;//P1口上次的状态,在调整倒计时时间的时候用到的

#ifdef USE_SOUND
LS138_E1
=1; //译码器初始化
#endif

needResetTimes
=0;//不需要重新设置溢出次数

MAX7219_Init();
//数码管初始化
initialSerial();//初始化串口发送

GetCounter();
//获取开始时候设置的倒计时时间
MAX7219_DisplayChar(DIG_1,code_table[beginNum]);//显示开始时设置的倒计时时间,在左位设置
MAX7219_DisplayChar(DIG_2,READY);//调时间的时候右位的显示

while(GetHostStartKey()==0)//当主持人没有按键的时候进入循环
{
if (number_temp!=(P1&0xf0))//若调整了倒计时时间,则P1口状态变了,就要重新设置和显示
{
GetCounter();
//获取调整以后的倒计时时间
MAX7219_DisplayChar(DIG_1,code_table[beginNum]);//显示调整以后的倒计时时间
number_temp=P1&0xf0;//记录下来现在P1口的状态,以备后面的比较
}
}
//当主持人按键以后就结束调整进入抢答倒计时
sendNumber(beginNum);

MAX7219_DisplayChar(DIG_1,READY);
while(GetHostCancelKey()==0);

sendNumber(_STRING_READY_);
//发送调节完毕准备抢答的命令;

//调整好倒计时时间后,按下start显示"--",再按下cancel则显示倒计时时间,此时可以开始倒计时了.
MAX7219_DisplayChar(DIG_1,READY);//清空右边一位数码管
MAX7219_DisplayChar(DIG_2,code_table[beginNum]);
for (i=100;i--;i>0)
Delay10ms();
//防止后面出现连读的情况..

counterBack
=intrCounter; //备份要中断的总次数
while(1)//这里要用自己加的循环来把程序束缚在这里运行
{
showNum
=beginNum;//设置要显示的时间,当然时从倒计时时间开始
intrCounter=counterBack;//设置总中断的次数
TR0=0;//禁用计时器0
isPressed=0;//记录是否有人按键
isStart=0;//没有开始抢答
while(GetHostStartKey()==0);

//给上位机发送开始倒计时的指令
sendNumber(_STRING_START_);

needResetTimes
=1;//Timer0已经是第二轮开始,需要重新设置溢出次数
IT0_Init();//初始化计时器0, 启用.

MAX7219_DisplayChar(DIG_1,CLEAR);
//清空左边一位数码管
while(!isPressed)//如果没有记录到有人按键就进入
{
keyPressed
=GetPressed(P2);//查询一下P2口的状态,即按键情况,P2口的后四位作为抢答端输入,有线时候使用
//keyPressed=GetPressedWireless(P2);//查询一下P2口的状态,即按键情况,无线使用
hostPressed=GetHostCancelKey();
if (!keyPressed&&!hostPressed)//如果没有人按键,就进入下次循环
continue;
else
{
TR0
=0;//关闭定时器
isPressed=1;//记录到有人按键,提供条件跳出循环
}
}

if (keyPressed!=0)
{
if (isStart)//如果已经开始抢答
{
PressedHandle(keyPressed);
//处理按键,即显示抢答选手号码
GetOrFoulHandle(GET);//处理抢答

#ifdef USE_SOUND
//对是否使用扬声器进行条件编译
LS138_E1=0; //译码器准备工作
switch (keyPressed)
{
case 1: LS138_A=0;LS138_B=0;LS138_C=0;break; //1号成功灯亮
case 2: LS138_A=0;LS138_B=1;LS138_C=0;break; //2号成功灯亮
case 3: LS138_A=1;LS138_B=0;LS138_C=0;break; //3号成功灯亮
case 4: LS138_A=1;LS138_B=1;LS138_C=0;break; //4号成功灯亮
default : break;
}
#endif
}

else//否则,没有开始抢答
{
PressedHandle(keyPressed);
//处理按键,即显示抢答选手号码
GetOrFoulHandle(FOUL);//处理犯规,必须要放在后面,因为显示数字的里面有一个clear

#ifdef USE_SOUND
//对是否使用扬声器进行条件编译
LS138_E1=0; //译码器准备工作
switch (keyPressed)
{
case 1: LS138_A=0;LS138_B=0;LS138_C=1;break; //1号犯规灯亮
case 2: LS138_A=0;LS138_B=1;LS138_C=1;break; //2号犯规灯亮
case 3: LS138_A=1;LS138_B=0;LS138_C=1;break; //3号犯规灯亮
case 4: LS138_A=1;LS138_B=1;LS138_C=1;break; //4号犯规灯亮
default : break;
}
#endif
}
}

if (hostPressed==1)
{
CancelHandle();
//向上位机发送主持人取消的指令
sendNumber(_STRING_CANCEL_);
for (i=100;i--;i>0)
Delay10ms();
//防止后面出现连读的情况..
}
while(GetHostCancelKey()==0);//如果主持人没有按键再次开始,则停在次死循环处

#ifdef USE_SOUND
//对是否使用扬声器进行条件编译
LS138_E1=1; //关闭译码器
#endif

MAX7219_DisplayChar(DIG_1,READY);
//清空右边一位数码管
MAX7219_DisplayChar(DIG_2,code_table[beginNum]);//左位显示设置的倒计时时间

//给上位机发送重新开始倒计时的指令
sendNumber(_STRING_READY_);

//到这里一次循环结束
}
}


 

转载于:https://www.cnblogs.com/bluecoffee/articles/1334625.html

你可能感兴趣的:(基于AT89S51的单片机无线双显示抢答器C代码)