您的位置 首页 应用

8051单片机抢答器C程序

#includeREG51.h>/*******************************************************************自定义Macro*****

#include

/******************************************************************

* 自界说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

/******************************************************************

* 自界说数据类型

*******************************************************************/

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_SWITCH=P0^0; // 主持人开关的接口

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; //界说蜂鸣器端口

sbit LS138_C=P2^4; //界说译码器输入端

sbit LS138_B=P2^5; //同上

sbit LS138_A=P2^6; //同上

sbit LS138_E1=P2^7; //界说译码器使能端

/*********************************************************************

* 界说全局变量

**********************************************************************/

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口前次状况的一个变量

code unsigned char C51BOX2[3] _at_ 0x43;

/***********************************************************************

* 共阴极七段数码管显现对应段查询表(数字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);

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); // 声明犯规声响函数

/***********************************************************************

* 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: 从P1口衔接抢答端的四位来判别抢答状况

* Arguments : Byte KeyState–>P1 state

* Returns : 抢答端的号码 ; 0–>没人抢答

***************************************************************************/

Byte GetPressed(Byte KeyState)

{

Byte key;//记载抢答端的号码

KeyState&=0x0f;//取P1口的低四位

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 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;

}

/**************************************************************************

* IT0_Init

*

* Description: 初始化计时器T0的状况

* Arguments : none

* Returns : none

***************************************************************************/

void IT0_Init(void)

{

TMOD=0x01;//设置T0在方法1下作业

TH0=0x3C;

TL0=0xAF;//这两个寄存器存的是计数器的计数开端的值,核算发现这两个值累加至溢出后正好是50ms

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 second=20;//用20次中止来判别1秒

TH0=0x3C;

TL0=0xAF;

second–;

intrCounter–;

/*

if (second==0)//每隔一秒的操作

{

MAX7219_DisplayChar(DIG_2,code_table[–showNum]); //要避免用上面的会形成显现”0″后边一秒钟,才进入开端

second=20;//从头赋值每秒计数器

if (intrCounter==0)

{

TR0=0;//封闭T0计数器

isStart=1;//计时完毕,进入正常抢答

//SPEAKER_start();//开端抢答的声响

}

//待显现”0″今后就开端抢答

else

{

//SPEAKER_count();//倒计时声响

}

}

*/

if (second==0)//每隔一秒的操作

{

//if (showNum!=1) SPEAKER_count();//倒计时声响

//else SPEAKER_start();//开端抢答的声响

MAX7219_DisplayChar(DIG_2,code_table[–showNum]);//显现数字

second=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]);//在右侧数码管显现抢答选手号码,此刻没有去判别是否犯规

}

/**************************************************************************

* 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);

}

}

/**************************************************************************

* 主程序

***************************************************************************/

void main()

{

Byte keyPressed,i;//选手按键号码,没有的话为0

Bool hostPressed;//用来记载主持人按键撤销,0为没有动作,1为撤销

number_temp=P1&0xf0;//P1口前次的状况,在调整倒计时时刻的时分用到的

LS138_E1=1; //译码器初始化

MAX7219_Init();//数码管初始化

GetCounter();//获取开端时分设置的倒计时时刻

MAX7219_DisplayChar(DIG_1,code_table[beginNum]);//显现开端时设置的倒计时时刻,在左位设置

MAX7219_DisplayChar(DIG_2,READY);//调时刻的时分右位的显现

//while(1);

while(GetHostStartKey()==0)//当主持人没有按键的时分进入循环

{

if (number_temp!=(P1&0xf0))//若调整了倒计时时刻,则P1口状况变了,就要从头设置和显现

{

GetCounter();//获取调整今后的倒计时时刻

MAX7219_DisplayChar(DIG_1,code_table[beginNum]);//显现调整今后的倒计时时刻

number_temp=P1&0xf0;//记载下来现在P1口的状况,以备后边的比较

}

} //当主持人按键今后就完毕调整进入抢答倒计时

MAX7219_DisplayChar(DIG_1,READY);

while(GetHostCancelKey()==0);

MAX7219_DisplayChar(DIG_1,READY);//清空右边一位数码管

MAX7219_DisplayChar(DIG_2,code_table[beginNum]);

for (i=100;i–;i>0)

Delay10ms();//避免后边呈现连读的状况..

//调整好倒计时时刻后,按下start显现”–“,再按下cancel则显现倒计时时刻,此刻能够开端倒计时了.

counterBack=intrCounter;

//这儿原来写的是while(1),写上后就不行了,不知道为何..

while(1)//这儿要用自己加的循环来把程序捆绑在这儿运转

{

showNum=beginNum;//设置要显现的时刻,当然时从倒计时时刻开端

intrCounter=counterBack;//设置总中止的次数

TR0=0;//禁用计时器0

isPressed=0;//记载是否有人按键

isStart=0;//没有开端抢答

while(GetHostStartKey()==0);

IT0_Init();//初始化计时器0, 启用.

MAX7219_DisplayChar(DIG_1,CLEAR);//清空左面一位数码管

MAX7219_DisplayChar(DIG_2,code_table[beginNum]);

while(!isPressed)//假如没有记载到有人按键就进入

{

keyPressed=GetPressed(P1);//查询一下P1口的状况,即按键状况

hostPressed=GetHostCancelKey();

if (!keyPressed&&!hostPressed)//假如没有人按键,就进入下次循环

continue;

else

{

TR0=0;//封闭定时器

isPressed=1;//记载到有人按键,提供条件跳出循环

}

}

if (keyPressed!=0)

{

if (isStart)//假如现已开端抢答

{

PressedHandle(keyPressed);//处理按键,即显现抢答选手号码

GetOrFoulHandle(GET);//处理抢答

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;

}

//SPEAKER_get();//处理抢答

}

else//不然,没有开端抢答

{

PressedHandle(keyPressed);//处理按键,即显现抢答选手号码

GetOrFoulHandle(FOUL);//处理犯规,必需要放在后边,由于显现数字的里边有一个clear

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;

}

//SPEAKER_foul();//犯规发声

}

}

if (hostPressed==1)

{

CancelHandle();

for (i=100;i–;i>0)

Delay10ms();//避免后边呈现连读的状况..

}

while(GetHostCancelKey()==0);//假如主持人没有按键再次开端,则停在次死循环处

LS138_E1=1; //封闭译码器

MAX7219_DisplayChar(DIG_1,READY);//清空右边一位数码管

MAX7219_DisplayChar(DIG_2,code_table[beginNum]);//左位显现设置的倒计时时刻

//到这儿一次循环完毕

}

}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/273136.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部