资源描述
- -
中国矿业大学2016-2017学年第一学期
电气工程专业?创新创业教育与实践?总结报告
班级
XX
学号
成绩
基于单片机的八路抢答器
一、方案比拟与选择
1、根据目前市场上抢答器的种类,抢答器的种类可以大体分为三种:
方案一: 抢答器系统的各局部均采用中小规模集成数字电路,利用硬件电子元器件实现,用机械开关按钮作为控制开关,完成抢答输入信号的触发。如采用74LS148优先编码器来实现抢答功能等。该方案的特点是中小规模集成电路应用技术成熟,性能可靠,能方便地完成选手抢答的根本功能,没有软件的设计局部,不需要编程,但是电路构造复杂,调试困难,涉及到的外围元器件很多,造成抢答器的本钱较高,并且制作过程工序比拟烦琐,不便于安装与调试,给实际操作带来很大的麻烦。
方案二:系统设计主要基于可编程的PLC设计,系统包括硬件和软件两大局部,依据控制系统的工作原理和技术性能,将硬件和软件分开设计。硬件设计局部包括电路原理图、合理选择元器件、绘制线路图,然后对硬件进展调试、测试,以到达设计要求。软件设计局部,首先在总体设计中完成系统总框图和各模块的功能设计,选择适宜的编程语言和工具,进展代码设计等;最后是对软件进展调试、测试,到达所需功能要求。
方案三:系统采用STC89C52单片机作为控制核心,其片带有8KBflashROM,256B的RAM,以及32根I/O口线能满足设计要求。该系统可以完成运算控制、信号识别以及显示功能的实现。利用单片机程序判断选手按键是否有效,是否有选手违规抢答,利用程序显示,启动蜂鸣器报警,告诉主持人有人违规操作,抢答无效。给出相应的延时,选手按正常的操作抢答,软件倒计时,利用数码管的动态扫描,实现倒计时显示时间,到5秒相应时间提醒选手时间快到了,要及时作答,并启动蜂鸣器。由于采用了单片机,其技术比拟成熟,应用起来方便、简单并且单片机周围的辅助电路也比拟少,便于控制和实现。整个系统具有极其灵活的可编程性,能方便地对系统进展功能的扩和更改。
2、方案比拟分析
第一个方案中,抢答器由抢答电路、定时电路、报警电路和时序控制电路四个关键电路局部组成。扩展电路是秒钟脉冲信号产生电路、译码电路、显示电路等,它的功能很齐全,设计的电路也很稳定,但是本钱却很高,所需集成电路非常多且连线复杂。
而方案二采用可编程PLC设计抢答器,但该系统的投入本钱过于高昂,软件编程过于繁琐,对编程的语言掌握程度要求很高,而且PLC在该领域的应用很少,普通人对PLC的理解及掌握都不是很深入,鉴于通用性和节省的原那么,我们不采用该方案。
方案三以单片机为核心器件,外围电路采用集成芯片,其可靠性好、构造简单,不但从性能上优于方案一和方案二,而且在使用及其功能的实现上都较其他方案简洁,并且由于单片机具有优越的高集成电路性,使其工作速度更快、效率更高。另外单片机采用12MHz的晶振,提高了信号的测量精度,并且使该系统可以通过软件改良来扩功能,经济实用,所以我们选用基于单片机的方案。
二、电路原理与设计
设计要求:
1、可同时提供最多包括8个人〔组〕的抢答数量。
2、需由主持人按下开场抢答按键后才视为抢答时间,在这个时间前抢答的,视为违规抢答,要求能显示出违规抢答的选手编号。
3、要求当主持人按下开场抢答的按键后,数码管进展抢答时间的倒计时,在这个倒计时完毕后,假设无人抢答,蜂鸣器报警,提示本轮抢答完毕,且这个抢答时间可设置。
4、要求具有抢答锁定功能,即某一选手抢到后,其它选手的抢答功能被锁定,无法进展抢答,直至下一轮抢答开场。
5、对于抢到题目的选手,要求能显示出该选手的编号,并将其答题时间进展倒计时显示,在倒计时完毕后,蜂鸣器报警,提示本次答题时间到,且这个抢答时间可设置。
6、原始状态下抢答时间为30s,答复下列问题时间为15s。通过加键和减键修改上述时间,改完后再断电、重新上电即可。
1、系统概述
整个系统以STC89C52单片机为核心器件,其它模块围绕着单片机展开。输入局部包括2个容,一个是选手的抢答输入,另一个是主持人的控制输入,由于这两个容都是通过按键控制的,所以这里统一使用普通的轻触开关作为本设计的输入模块,一共包括8个选手输入按键和2个主持人输入按键。输出局部那么采用蜂鸣器加四位共阳数码管进展声光的输出,蜂鸣器主要起到报警的作用,这里主要有几个需蜂鸣器发出报警的地方,如最后5秒仍无人抢答、答题剩余最后5秒、抢答时间完毕以及答题时间完毕等。而数码管那么主要用于信息的输出,包括当主持人按下开场抢答按键后,显示30秒〔默认〕的倒计时,当有选手违规抢答时,显示违规选手的编号,有人抢到题目时,显示选手编号以及该选手剩余的答题时间。
系统框图:
蜂鸣器报警模块
STC89C52
最小系统
选手抢答输入
数码管显示模块
主持人控制输入
图1
1〕、最小系统电路
STC89C52的最小系统如图2所示,整个最小系统由4个局部组成,晶振电路局部、复位电路局部、P0口上拉电路局部以及程序下载口局部。
30pF的电容C4和C5以及12M的晶振X1构成了单片机的晶振电路,2个小电容的作用是帮助X1起振。
复位电路由10uF的电解电容C1和10K的电阻R2构成,本复位电路包括上电自复位和按键复位2个功能。
本设计将P0口用作数码管的数据口,因此在P0口接了一个10K的排阻,使得P0口可以作为普通的I/O口使用,
最后,为了方便调试和下载,还把P30、P31、GND和VCC这4个引脚通过排针引出来作为程序的下载口。
图2
2〕、键盘扫描电路
键盘是人与单片机打交道的主要设备。站在系统监控软件设计的立场上来看,仅仅完成键盘扫描、读取当前时刻的键盘状态是不够的,还有不少问题需要妥善解决,否那么在操作键盘时就会出现误操作和操作失控现象。在单片机应用中,键盘用得最多的形式是独立键盘及矩阵键盘。它们各有自己的特点,其中独立键盘硬件电路简单,而且在程序设计上也不复杂,一般用在对硬件电路要求不高的简单电路中;矩阵键盘与独立键盘有很大区别,首先在硬件电路上它要比独立键盘复杂得多,而且在程序算法上比它要繁琐,但它在节省端口资源上有优势得多,因此它更适合于多按键电路。其次就是消除在按键过程中产生的“毛刺〞现象。这里采用最常用的方法,即延时重复扫描法,延时法的原理为:因为“毛刺〞脉冲一般持续时间短,约为几ms,而我们按键的时间一般远远大于这个时间,所以当单片机检测到有按键动静后再延时一段时间后再判断此电平是否保持原状态,如果是那么为有效按键,否那么无效。
本设计中采用了独立键盘的方式,有8个抢答按键输入、一个复位按键以及一个主持人使用的开场抢答按键,同时为了简化电路设计、节约单片机的I/O口资源,将设置抢答时间和答题时间等这些功能按键复合到了8个选手的抢答按键中。
图3
3〕、蜂鸣器报警电路
由于蜂鸣器工作时需要的电流比拟大,单片机的IO口输出的电流又比拟小,所以这里利用三极管来控制蜂鸣器发音,本设计选用的三极管型号是PNP三极管S8550,而且本设计选用的蜂鸣器属于有源蜂鸣器,即在蜂鸣器部已经置了震荡电路,单片机无需连续发出上下电平来驱动它,而只要输出高〔或低〕电平即可,这大大简化了单片机程序的设计,由于选用的是PNP型而单片机上电IO口默认是高电平的,所以上电时蜂鸣器是不会发出鸣叫的。蜂鸣器电路如图4所示。
图4
4〕、数码管显示电路
显示功能与硬件关系极大,当硬件固定后,如何在不引起操作者误解的前提下提供尽可能丰富的信息全靠软件来解决。在这里我们使用的是七段数码管显示,通常在显示上我们采用的方法一般包括两种:一种是静态显示,一种是动态显示。其中静态显示的特点是显示稳定不闪烁,程序编写简单,但占用端口资源多;动态显示的特点是显示稳定性没静态好,程序编写复杂,但是相对静态显示而言占用端口资源少。在本设计中根据实际情况采用的是动态显示方法。
数码管还分共阳型和共阴型,本设计采用的是4位共阳数码管。通过查表法,将其在数码管上显示出来,其中P0口为字型码输入端,P2口低4位为字选段输入端。在这里我们通过查表将字型码送给7段数码管,4位七段数码管显示电路如图5所示。其中A、B、C、D、E、F、G、DP段分别接到单片机的P0口,由单片机P0口输出的数据来决定段码值,位选码W1、W2、W3、W4分别接到单片机的P2^0、P2^1、P2^2以及P2^3上,由单片机来决定当前该显示的是哪一位。由于单片机的I/O口驱动电流不够,这里还使用了4个NPN的三极管S8050对电流放大来驱动数码管的位选。
图5
设计电路图〔原理图、PCB图〕
三、程序设计
1、总体程序设计
八路抢答器的整体程序流程图如图6所示,程序从定时器的初始化开场,这里用到了单片机的2个定时器,1个用于数码管的动态扫描,另一个用于答题时间的计时。接着程序开场判断是否进入抢答时间设置,如果有那么进入抢答时间设置模式,没有那么继续判断是否进入答题时间设置,如果有那么进入答题时间设置模式,没有那么跳出,进入主程序的大循环。
进入大循环之后,就扫描是否有按键按下,有的话就判断是哪个按键,如果是主持人按下了开场抢答按键,那么进入抢答模式,如果是选手按下了抢答键,那么蜂鸣器报警,此时有选手违规抢答〔即在主持人按下开场抢答按键前就抢答了〕,同时将违规选手的编号显示在数码管上,直至主持人按下复位键,那么去除报警状态。如果一直没检测到按键按下,那么一直在大循环里面扫描按键。
进入抢答模式后,数码管开场将抢答时间倒计时并显示在数码管上,如果在抢答时间无人抢答,那么在最后5秒蜂鸣器发出滴滴的报警声,并且5秒完毕后,蜂鸣器一直鸣叫,表示此轮抢答完毕,并且数码管显示“----〞,直至主持人按下复位键退出报警。如果在抢答时间有选手抢答题目时,那么在数码管将选手的编号显示出来,并显示答题时间的倒计时,同抢答时间一样,在最后5秒蜂鸣器会发出滴滴的报警声,答题时间完毕后,蜂鸣器也会一直鸣叫,表示此轮抢答完毕,直至主持人按下复位键退出报警。
开场
是
是否设置抢答时间
设置抢答时间
否
是
设置答题时间
是否设置答题时间
否
等待按键按下
是
是否违规抢答
否
是
发出警报
完毕
答题倒计时
是否有选
手抢答
否
图6
1〕、抢答、答题时间设置
为了简化抢答器的硬件电路,将抢答时间和答题时间的设置按键和抢答键合并到了一起。如需设置抢答时间,先断开抢答器的电源,然后按下按键一〔选手一的抢答键〕,然后上电,系统上电检测到按键一被按下了,那么就进入到抢答时间的设置,通过按键七〔减〕和按键八〔加〕来设置答题时间的大小。答题时间的设置也根本类似,只不过是在上电前按下按键二而已。
2〕、数码管动态扫描程序
为了简化程序、合理利用单片机的部资源,所以将数码管的动态扫描程序通过定时器来实现。本设计设置的定时器发生中断的时间为2毫秒,每次显示四位中的一位,因此完成四位数码管的扫描需要8毫秒的时间,即发生四次定时器中断。
四、测试方案
先在Proteus里画好电路总体原理图,再将写好的C程序文件用Keil编译生成hex文件载入单片机里,需要仿真的功能同设计要求。
五、系统调试
焊接好实物,上电对所设计的功能进展验证,记录现场。
六、仿真调试与事物验证
1、仿真记录
1〕、抢答时间调整
2〕、答题时间调整
3〕、违规抢答
4〕、正确抢答
2、实物验证
1〕、上电初始状态
2〕、正确抢答
3〕、4号违规抢答
4〕、抢答时间调整
5〕、答题时间调整
6〕、时间调整后8号正确抢答
七、总结
本次研究设计的八路抢答器利用STC89C52单片机及外围接口实现各种功能,将软硬件有机的结合起来。通过这次设计,我们学会了如何将学到的知识化为自己的东西,学会了怎么更好的处理理论和实践相结合的问题,把握重点、攻克难关、活学活用。此外,还可以将设计的扩展功能增强:可以设计声控装置,在主持人说“开场“时,系统自动进入抢答流程;增加计分模块,可以设定初始分数并记录每次抢答完成后的总分;将抢答按键使用无线实现,如红外线,使抢答者可远距离进展抢答,并简化按键模块的线路布置。相信基于单片机的抢答器在市场上更有竞争力和市场。
八、参考文献
[1]平.单片机的原理与接口技术[M].:电子工业,2006.
[2]王忠民.微型计算机原理[M].:科技大学,2003
[3]纪宗南.单片机外围器件使用手册[M].:航空航天大学
[4]余永权.单片机在控制系统中的应用[M].:电子工业
[5]周润景,丽娜.基于PROTEUS的电路及单片机系统设计与仿真[M].
:航空航天大学
[6]唐俊翟.单片机原理与应用[M].:冶金工业:252-267
[7]康华光.电子技术根底(数字局部)〔第四版〕[M].:高等教育,2003
九、附录
程序
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sfr ISP_DATA = 0xe2; // 数据存放器中
sfr ISP_ADDRH = 0xe3; // 地址存放器高八位
sfr ISP_ADDRL = 0xe4; // 地址存放器低八位
sfr ISP_CMD = 0xe5; // 命令存放器
sfr ISP_TRIG = 0xe6; // 命令触发存放器
sfr ISP_CONTR = 0xe7; // 命令存放器
sbit w1 = P2^3; // 定义了数码管第1位的控制脚
sbit w2 = P2^2; // 定义了数码管第2位的控制脚
sbit w3 = P2^1; // 定义了数码管第3位的控制脚
sbit w4 = P2^0; // 定义了数码管第4位的控制脚
sbit k1 = P1^0; // 定义了选手1的抢答按键〔可用于进入设置时间〕
sbit k2 = P1^1; // 定义了选手2的抢答按键〔可用于进入设置时间〕
sbit k3 = P1^2; // 定义了选手3的抢答按键
sbit k4 = P1^3; // 定义了选手4的抢答按键
sbit k5 = P1^4; // 定义了选手5的抢答按键
sbit k6 = P1^5; // 定义了选手6的抢答按键
sbit k7 = P1^6; // 定义了选手7的抢答按键〔设置时间时,是“减〞的功能〕
sbit k8 = P1^7; // 定义了选手8的抢答按键〔设置时间时,是“加〞的功能〕
sbit k9 = P3^7; // 定义了开场抢答的按键
sbit bp = P2^6; // 定义蜂鸣器的控制引脚
/* 数码管的显示值: 0 1 2 3 4 5 6 7 8 9 A B C D E F - */
uchar codeShowDig[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0xff};
uchar dig[4]; // dig[0]、dig[1]、dig[2]、dig[3]分别代表了四位数码管显示的容
char gWaitTime,gAnswerTime; // gWaitTime是抢答等待时间,gAnswerTime是答题等待时间
char gCount,gSecond; // gCount是用于计数的,gSecond是用于记录当前的剩余秒数的〔抢答时间和答题〕
/*********************************************************/
// 单片机部EEPROM不使能
/*********************************************************/
void ISP_Disable()
{
ISP_CONTR = 0;
ISP_ADDRH = 0;
ISP_ADDRL = 0;
}
/*********************************************************/
// 从单片机部EEPROM读一个字节,从0x2000地址开场
/*********************************************************/
unsigned char Byte_Read(unsigned int add)
{
ISP_DATA = 0x00;
ISP_CONTR = 0x83;
ISP_CMD = 0x01;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_TRIG = 0x46; // 对STC89C51系列来说,每次要写入0x46,
ISP_TRIG = 0xB9; // 再写入0xB9,ISP/IAP才会生效
_nop_();
ISP_Disable();
return (ISP_DATA); // 将读出的数据作为函数的返回值
}
/*********************************************************/
// 往单片机部EEPROM写一个字节,从0x2000地址开场
/*********************************************************/
void Byte_Program(unsigned int add,unsigned char ch)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x02;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_DATA = ch;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
}
/*********************************************************/
// 擦除单片机部EEPROM的一个扇区,写8个扇区中随便一个的
// 地址,便将该扇区整个擦除,写入数据前要先擦除
/*********************************************************/
void Sector_Erase(unsigned int add) //
{
ISP_CONTR = 0x83;
ISP_CMD = 0x03;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
_nop_();
ISP_Disable();
}
/*********************************************************/
// 毫秒级延时函数
/*********************************************************/
void DelayMs(uint n)
{
uint x,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
/*********************************************************/
// 定时器初始化
/*********************************************************/
void TimerInit()
{
TMOD = 0x11; // 定时器0用于数码管的动态扫描,定时器1用于秒数的计时
TH0 = (65536-1000)/256; // 给定时器0的TH0装初值
TL0 = (65536-1000)%256; // 给定时器0的TL0装初值
TH1 = (65536-50000)/256; // 给定时器1的TH1装初值
TL1 = (65536-50000)%256; // 给定时器1的TL1装初值
TR0 = 1; // 启动定时器0〔开场动态扫描数码管〕
ET0 = 1; // 定时器0中断使能
ET1 = 1; // 定时器1中断使能
EA = 1; // 翻开总中断
}
/*********************************************************/
// 判断是否进入等待时间设置
/*********************************************************/
void WaitTimeSet(void)
{
if(k1==0) // 判断按键1是否有按下,等于0代表按键按下了,那么进入抢答时间设置模式
{ // 数码管显示“EEEE〞
dig[0]=ShowDig[14];
dig[1]=ShowDig[14];
dig[2]=ShowDig[14];
dig[3]=ShowDig[14];
while(!k1); // 等待按键释放
DelayMs(500); // 利用延时去抖
dig[1]=ShowDig[17]; // 数码管显示“E EE〞
dig[2]=ShowDig[gWaitTime/10]; // 数码管显示“E 30〞〔30就是要设置抢答时间,30只是个例子,具体数字视具体情况而定〕
dig[3]=ShowDig[gWaitTime%10];
while(k1) // 当再次按下按键1时,退出抢答时间设置模式,否那么一直扫描“加〞、“减〞按键
{
if(k8==0) // 判断“加〞按键是否被按下
{
DelayMs(250); // 利用延时去抖
gWaitTime++; // 当前要设置的秒数自加1
if(gWaitTime==100) // 当自加到100时,自动清零
gWaitTime=0;
Sector_Erase(0x2000); // 擦除部EEPROM〔写入之前必须先擦除〕
Byte_Program(0x2000,gWaitTime); // 将新设置的等待时间写入到部EEPROM的0x2000这个地址
Byte_Program(0x2001,gAnswerTime); // 将答题时间写入到部EEPROM的0x2001这个地址
dig[2]=ShowDig[gWaitTime/10]; // 更新数码管的秒数显式〔十位〕
dig[3]=ShowDig[gWaitTime%10]; // 更新数码管的秒数显式〔个位〕
}
if(k7==0) // 判断“减〞按键是否被按下
{
DelayMs(250); // 利用延时去抖
gWaitTime--; // 当前要设置的秒数自减1
if(gWaitTime==-1) // 当自减到-1时,自动变成99
gWaitTime=99;
Sector_Erase(0x2000); // 擦除部EEPROM〔写入之前必须先擦除〕
Byte_Program(0x2000,gWaitTime); // 将新设置的等待时间写入到部EEPROM的0x2000这个地址
Byte_Program(0x2001,gAnswerTime); // 将答题时间写入到部EEPROM的0x2001这个地址
dig[2]=ShowDig[gWaitTime/10]; // 更新数码管的秒数显式〔十位〕
dig[3]=ShowDig[gWaitTime%10]; // 更新数码管的秒数显式〔个位〕
}
}
while(!k1);
DelayMs(500);
}
}
/*********************************************************/
// 判断是否进入答题时间设置
/*********************************************************/
void AnswerTimeSet(void)
{
if(k2==0) // 判断按键2是否有按下,等于0代表按键按下了,那么进入答题时间设置模式
{ // 数码管显示“FFFF〞
dig[0]=ShowDig[15];
dig[1]=ShowDig[15];
dig[2]=ShowDig[15];
dig[3]=ShowDig[15];
while(!k2); // 等待按键释放
DelayMs(500); // 利用延时去抖
dig[1]=ShowDig[17]; // 数码管显示“F FF〞
dig[2]=ShowDig[gAnswerTime/10]; // 数码管显示“F 15〞〔15就是要设置答题时间,15只是个例子,具体数字视具体情况而定〕
dig[3]=ShowDig[gAnswerTime%10];
while(k2) // 当再次按下按键2时,退出抢答时间设置模式,否那么一直扫描“加〞、“减〞按键
{
if(k8==0)
{
DelayMs(250); // 利用延时去抖
gAnswerTime++; // 当前要设置的秒数自加1
if(gAnswerTime==100) // 当自加到100时,自动清零
gAnswerTime=0;
Sector_Erase(0x2000); // 擦除部EEPROM〔写入之前必须先擦除〕
Byte_Program(0x2000,gWaitTime); // 将等待时间写入到部EEPROM的0x2000这个地址
Byte_Program(0x2001,gAnswerTime); // 将新设置的答题时间写入到部EEPROM的0x2001这个地址
dig[2]=ShowDig[gAnswerTime/10]; // 更新数码管的秒数显式〔十位〕
dig[3]=ShowDig[gAnswerTime%10]; // 更新数码管的秒数显式〔个位〕
}
if(k7==0) // 判断“减〞按键是否被按下
{
DelayMs(250); // 利用延时去抖
gAnswerTime--; // 当前要设置的秒数自减1
if(gAnswerTime==-1) // 当自减到-1时,自动变成99
gAnswerTime=99;
Sector_Erase(0x2000); // 擦除部EEPROM〔写入之前必须先擦除〕
Byte_Program(0x2000,gWaitTime); // 将等待时间写入到部EEPROM的0x2000这个地址
Byte_Program(0x2001,gAnswerTime); // 将新设置的答题时间写入到部EEPROM的0x2001这个地址
dig[2]=ShowDig[gAnswerTime/10]; // 更新数码管的秒数显式〔十位〕
dig[3]=ShowDig[gAnswerTime%10]; // 更新数码管的秒数显式〔个位〕
}
}
while(!k2); // 等待按键释放
DelayMs(500); // 利用延时去抖
}
}
/*********************************************************/
// 按键扫描程序,如果检测到没有按键按下,那么返回0
/*********************************************************/
uchar KeyScanf(void)
{
if(k1==0) // 选手1按下,返回1
return 1;
if(k2==0) // 选手2按下,返回2
return 2;
if(k3==0) // 选手3按下,返回3
return 3;
if(k4==0) // 选手4按下,返回4
return 4;
if(k5==0) // 选手5按下,返回5
return 5;
if(k6==0) // 选手6按下,返回6
return 6;
if(k7==0) // 选手7按下,返回7
return 7;
if(k8==0) // 选手8按下,返回8
return 8;
if(k9==0) // 开场抢答按键按下,返回9
return 9;
return 0;
}
/*********************************************************/
// 主函数
/*********************************************************/
void main(void)
{
uchar ret; // ret用于保存按键扫描程序的返回值
TimerInit();
// 新单片机下载程序请翻开,因为EEPROM的部数据读取出来是乱码,下载完第一次之后就可以注释掉这3行代码
// Sector_Erase(0x2000);
// Byte_Program(0x2000,30);
// Byte_Program(0x2001,15);
gWaitTime = Byte_Read(0x2000); // 读取EEPROM中设置温度上限的报警值,并赋给全局变量
gAnswerTime = Byte_Read(0x2001); // 读取EEPROM中设置温度下限的报警值,并赋给全局变量
WaitTimeSet(); // 判断是否要进入等待时间设置模式
AnswerTimeSet(); // 判断是否要进入答题时间设置模式
dig[0]=ShowDig[0]; // 数码管显示“0000〞
dig[1]=ShowDig[0];
dig[2]=ShowDig[0];
dig[3]=ShowDig[0];
while(1)
{
if(KeyScanf()!=0) // 当按键扫描程序的返回值不是0时,代表有按键被按下
{
ret=KeyScanf(); // 保存按键扫描程序的返回值
while(KeyScanf()); // 等待按键释放
DelayMs(500); // 利用延时去抖
if(ret==9) // 如果是开场抢答按键被按下
{
TR1=1; // 启动定时器,即开场秒数的倒计时
dig[0]=ShowDig[17]; // 数码管显示“ 00〞
dig[1]=ShowDig[17];
gSecond=gWaitTime; // 此时,gSecond代表了具体有多少秒需要倒计时
while(!KeyScanf()) // 如果一直没有人按键,那么一直判断秒数是不是计到0了
{
if(gSecond==0) // 如果计数到0了,数码管显示“----〞,表示此轮抢答完毕
{
dig[2]=ShowDig[16];
dig[3]=ShowDig[16];
}
else // 如果没有计到0,那么数码管一直显示当前倒数的秒数
{
dig[2]=ShowDig[gSecond/10];
dig[3]=ShowDig[gSecond%10];
}
}
ret=KeyScanf(); // 保存按键扫描程序的返回值
dig[0]=ShowDig[ret]; // 数码管第一位显示抢到答题权限的选手的编号
dig[1]=ShowDig[16]; // 数码管第二位显示“-〞
gSecond=gAnswerTime; // gSecond代表了答题的时间〔之前是代表抢答时间〕
while(1) // 一直判断秒数是不是计到0了
{
if(gSecond==0) // 如果计数到0了,数码管显示“----〞,表示此轮抢答完毕
{
dig[2]=ShowDig[16];
dig[3]=ShowDig[16];
}
else // 如果没有计到0,那么数码管一直显示当前倒数的秒数
{
dig[2]=ShowDig[gSecond/10];
dig[3]=ShowDig[gSecond%10];
}
}
}
else // 如果不是开场抢答按键被按下,说明是选手按键被按下,此时是违规的提前抢答
{
dig[0]=ShowDig[ret]; // 数码管第一位显示违规选手的编号
dig[1]=ShowDig[16]; // 数码管第二位显示“-〞
dig[2]=ShowDig[12]; // 数码管第三位显示“C〞
dig[3]=ShowDig[12]; // 数码管第四位显示“C〞
bp=0; // 蜂鸣器报警
while(1);
}
}
}
}
/*
展开阅读全文