《计算机应用系统设计》

在这里插入图片描述

具体内容

一、课程设计的内容及其要求

1. 项目要求

  设计一个多路定时抢答器。主持人控制抢答开关模块,按下开始键之后开始 抢答。选手使用抢答按键进行地答,显示模块显示抢答阶段倒计时时间以及抢答 成功的选手号码,并可以显示选手答题时间在此过程中,状态指示模块的指示灯 对比赛的阶段以及抢答成功的选手进行指示。主持人按下复位键便可重新进入准 备阶段。

2. 设计要求

(1)开始答题的控制:按键开始;
(2)抢答的方案:按键抢答;
(3)状态的指示:包括显示当前处于竞赛的哪个环节,以及哪位选手抢答 成功等提示,可选用发光二极管等来指示当前状态。状态指示答题环节指示与选 手选择指示可选用不同颜色的指示灯。
(4)倒计时时间的显示,可用数码管来实现,倒计时时间为 30 s,需要显 示 2 位数;
(5)答题选手号码的显示,也可用数码管来实现,抢答人数为 8 人,需要 显示 1 位

二、设计方案

1.总体方案

  文字说明系统选取了哪些元器件,由哪些电路组成,并配上系统框架图。在这里插入图片描述

图1 8路抢答器系统结构图
2.主控电路

在这里插入图片描述

图2 主控电路

   VCC:供电电压。
   GND:接地。
  P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FLASH编程时,P0 口作为原码输入口,当FLASH进行校验时,P0输出原码,此时P0外部必须被拉高。
  P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。
  P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写1时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址1时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
  P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当  P3口写入1后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流。
  P3口也可作为AT89S51的一些特殊功能口,如下表所示:
  P3口管脚 备选功能
  P3.0 RXD(串行输入口)
  P3.1 TXD(串行输出口)
  P3.2 INT0(外部中断0)
  P3.3 INT1(外部中断1)
  P3.4 T0(记时器0外部输入)
  P3.5 T1(记时器1外部输入)
  P3.6 (外部数据存储器写选通)
  P3.7 (外部数据存储器读选通)
  P3口同时为闪烁编程和编程校验接收一些控制信号。
  ALE/ :当访问外部存储器时,地址锁存允许端的输出电平用于锁存地址的地址字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。
  PSEN:外部程序存储器的选通信号端。在由外部程序存储器取指期间,每个机器周期两次PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
   ~ EA/VP
当 ~ EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时, 将内部锁定为RESET;当 端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源。
  XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
  XTAL2:反向振荡器的输出,如采用外部时钟源驱动器件,应不接。

3. 显示电路

  数码显示管用来作为时间的显示输出,一般用7段数码显示管。本次设计中采用7段共阳数码显示管应用简单、可靠性高、成本低,作为显示输出。连接时段选信号接在P0口的P0.0~P0.7七个I/O口上,P1口是准双向I/O接口在输出驱动部分具有驱动4个TTL负载的能力,即输出电流不大于400μA,所以在接电阻时选择接10KΩ限流电阻。而在位选方面采用P2口的P2.0~P2.3用单片机四个I/O口作为位选信号的输出口。
在这里插入图片描述

图3 显示电路

  上图中数码管采用的是4位一体七段共阳数码管,其中A~H段分别接到单片机的P0口,由单片机输出的P0口数据来决定段码值,位选码COM1, COM2,COM3,COM4分别接到单片机的P2.0,P2.1,P2.2 ,P2.,3,由单片机来决定当前该显示的是哪一位。在图中还有一个排阻,连接在P0口上,用作P0口的上拉电阻,保证P0口没有数据输出时候处于高电平状态。
  通过查表法,将其在数码管上显示出来,其中P0口为字型码输入端,P2口低4位为字选段输入段。在这里我们通过查表将字型码送给7段数码管显示的数字。

4.报警电路

在这里插入图片描述

图4 报警电路

  报警电路用于报警,当遇到报警信号时,发出警报。一般喇叭是一种电感性图4报警电路图。8951驱动喇叭的信号为各种频率的脉冲。因此,最简单的喇叭驱动方式就是利用达林顿晶体管,或者以两个常用的小晶体管连接成达林顿架势。在右图中电阻R为限流电阻,在此利用晶体管的高电流增益,以达到电路快速饱和的目的。不过,如果要由P0输出到此电路,还需要连接一个10K的上拉电阻。
   选手在设定的时间内抢答时,实现:优先判断、编号锁存、编号显示、扬声器提示。当一轮抢答之后,定时器停止、禁止二次抢答、定时器显示剩余时间。如果再次抢答必须由主持人再次*作"清除"和"开始"状态开关。图面是数字抢答器的报警电路图。

4.晶振电路

   晶振电路单片机必须在AT89C51的驱动下才能工作,在单片机内部有一个时钟震荡电路,只需要外接一个振荡器就能产生一定的时钟信号送到单片机内部的各个单元,外部震荡电路如下图。
在这里插入图片描述

图5 晶振电路

  一般选用石英晶体振荡器。此电路在加电大约延迟10ms后振荡器起振,在XTAL2引脚产生幅度为3V左右的正弦波时钟信号,其振荡频率主要由石英晶振的频率确定。电路中两个电容 C1,C2的作用有两个:一是帮助振荡器起振;二是对振荡器的频率进行微调。C1,C2的典型值为30PF。
  单片机在工作时,由内部振荡器产生或由外直接输入的送至内部控制逻辑单元的时钟信号的周期称为时钟周期。其大小是时钟信号频率的倒数,常用fosc表示。如时钟频率为12MHz,即fosc=12MHz,则时钟周期为1/12µs。

5.复位电路

在这里插入图片描述

图6 复位电路

  外部中断和内部中断并存,单片机硬件复位端,单片机的第9脚RST为硬件复位端,只要将该端持续4个机器周期的高电平即可实现复位,复位后单片机的各状态都恢复到初始化状态,硬件复位后的各状态可知寄存器以及存储器的值都恢复到了初始值,因为本设计中功能中有倒计时时间的记忆功能,所以不能对单片机进行硬件复位,只能用软件复位,软件复位实际上就是当程序执行完之后,将程序通过一条跳转指令让它完成复位。

6按键电路

在这里插入图片描述

图7 按键电路

  在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成1乘8的8个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

三、实现功能说明

  在本设计中包括了以下八个主要的程序:主程序;非法抢答序;抢答时间调整程序;倒计时程序;正常抢答处理程序;犯规处理程序;显示及发声程序。主流程图如图所示

1.程序流程图

  为了能够达到抢答的公平、公正、合理,应该在主持人发布抢答命令之前必须先设定抢答的时间,因而在编开始抢答前的程序得先编写设定时间的程序,当时间设好了之后,主持人发布抢答命令按下P1.7按键,程序开始打开定时中断开始倒计时,然后调用键盘扫描子程序,编写键盘扫描程序。当在扫描到有人按下了答题键,马上关闭T0、调用显示程序、封锁键盘。
在这里插入图片描述

图8 程序流程图
2.分功能描述

(1)当选手按下按键时,数码管自动显示选手编号,蜂鸣器同时发出响声。

图9 独立按键流程图

(2)当主持人按下开始键时,进入倒计时,秒减1。

在这里插入图片描述

图10 倒计时处理流程图

(3)选手抢答

在这里插入图片描述

图11 选手抢答

四、结论

  在Proteus仿真方面:由于第一次使用proteus软件,不知道如何使用,通过浏览讲解PPT、网上搜索并与组内成员讨论,完成连线并运行代码。起初选择单刀单掷开关发现发光二极管默认为亮状态,闭合开关后为灭状态,经过网上搜索、询问同学后改为单刀双掷开关才和实验所用开关符合,才能正确仿真。
  在电路焊接方面:起初设计时将电阻与发光二极管连接错误,询问老师后得知电阻应当接在发光二极管与地线之间,同时由于发光二极管和8255相连电压较为稳定,无需电阻也可以稳定运行,为了简化焊接电路,取消了原来与发光二极管相连的电阻。另外,焊接C52时将VCC引脚错误接地,导致运行时发光二极管和数码管无显示,改正连线后运行正常。
  通过本次硬件课程设计,掌握了C51、电路板、可编程接口芯片以及C语言的应用,也能够应用所学知识构建一个较完整的微型计算机控制系统。体会到了理论与实践结合的重要性,感受到了用所学知识实现一些具体硬件功能的乐趣,也认识到了团队合作的重要性。其次,老师在实验过程中也给予我们很大帮助,任何问题的解答都很细致。最后关于实验环境,可能由于实验器材的使用次数过多或器材保护不是很好,导致有一些实验器材反应不灵敏,使用不方便。总而言之,本次课程设计对我有很大帮助,加深了我对微机系统的理解,也具备了一定的应用能力。

五、心得体会

  这次课程设计老师给我们安排了三个星期的时间,可以说是比较充裕的。虽然如此,我还是很用心的做设计,利用了周六周日两天的时间在宿舍思考本次的课程设计,拿到题目,感觉太繁杂了,不知怎么下手,虽然这些知识以前都有接触过,但也只是分部分来接触,而这次的设计是要对前面几次实验的一个综合,真的很难。也翻阅了一些资料,并自己事先编写好了程序,把自己写的程序烧进去芯片里面,发现不行,那些数字闪动得非常厉害,自己检查了好久好久,但还是发现不了问题,之后问了同学,才知是我把段码搞错了,我用的是共阳位选,但数据表的段码我却用了共阴的段码,所以不能在数码管上正常显示。通过运用单片机设计八路抢答器程设计,发现自己的很多不足,自己知识的很多漏洞,看到了自己的实践经验还是比较缺乏,理论联系实际的能力还急需提高。
  在这个过程中,我也曾经因为实践经验的缺乏失落过,也曾经仿真成功而热情高涨。特别是Proteus仿真软件的使用,不知是由于电脑的问题还是怎么,这个软件的安装就花了我很长的时间,好不容易安装好了,又对软件的使用一点都不熟悉,要从头开始学起,对着老师发给我们的芯片原理进行仿真画图,刚刚开始时候真的很难下手,因为是英文版的软件,很多东西都看不太明白,都是通过自己一个个来慢慢琢磨,才把仿真图画了出来,然后把写好的程序导入芯片,进行仿真,当看到程序正常运行的那一刻,心中真是有几分的喜悦。生活就是这样,汗水预示着结果也见证着收获。劳动是人类生存生活永恒不变的话题。虽然这只是一次的较简单的课程制作(八路抢答器),可是平心而论,也耗费了我不少的心血。
  通过这次课程设计,我想说:为完成这次课程设计我们确实很辛苦,但苦中仍有乐,和同学们相互帮助,我感觉我和同学们之间的距离更加近了。这个工程确实很累, LED亮了起来,喇叭响起的是我一生以来最好听的声音,我们的心中就不免兴奋,不免激动。以前种种艰辛这时就变成了最甜美的回忆!这次学习给我留下了深刻的印象,使我受益匪浅。而且对于论文的总体构思也有了很多经验,相信自己经过这一次的训练与学习,对于今后会更加努力,做得最好。
  对我而言,知识上的收获重要,精神上的丰收更加可喜。让我知道了学无止境的道理。我们每一个人永远不能满足于现有的成就,人生就像在爬山,一座山峰的后面还有更高的山峰在等着你。挫折是一份财富,经历是一份拥有。这次课程设计必将成为我人生旅途上一个非常美好的回忆!

附件(程序完整代码)

#include <reg52.h>	         //调用单片机头文件
#define uchar unsigned char  //无符号字符型 宏定义	变量范围0~255
#define uint  unsigned int	 //无符号整型 宏定义	变量范围0~65535

//数码管段选定义      0     1    2    3    4    5	 6	 7	  8	   9	
uchar code smg_du[]={0x05,0xdd,0x46,0x54,0x9c,0x34,0x24,0x5d,0x04,0x14};	 //断码

sbit smg_we1 = P3^3;	  //数码管位选定义
sbit smg_we2 = P3^4;	  //数码管位选定义
sbit smg_we3 = P3^5;	  //数码管位选定义
sbit smg_we4 = P3^6;	  //数码管位选定义

sbit beep    = P3^7;      //蜂鸣器IO口定义 

sbit key1 = P2^0;	    //按键IO口定义
sbit key2 = P2^1;		//按键IO口定义
sbit key3 = P2^2;		//按键IO口定义
sbit key4 = P2^3;		//按键IO口定义
sbit key5 = P2^4;		//按键IO口定义
sbit key6 = P2^5;		//按键IO口定义
sbit key7 = P2^6;		//按键IO口定义
sbit key8 = P2^7;		//按键IO口定义

sbit key9  = P3^0;		//按键IO口定义
sbit key10 = P3^1;		//按键IO口定义
sbit key11 = P3^2;		//按键IO口定义


uchar flag_start;         //开始抢答标志位
uchar flag_weigui;        //抢答违规标志位

uchar dis_smg[4] = {0};	 //数码管显示缓冲区
uchar miao,s_time = 30,s2_time = 25;        //时间
uchar flag_num;           //号码 
uchar menu_1 ;            //设置不同参数的变量
bit flag_200ms = 1;       //200ms的标志位
uchar flag_qd_en;          //抢答
uchar i,qd2_en;

/***************************数码管位选函数****************************/
void smg_we_switch(uchar i)
{
	switch(i)
	{
		case 0: smg_we1 = 0;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 1; break;
		case 1: smg_we1 = 1;  smg_we2 = 0; smg_we3 = 1;  smg_we4 = 1; break;
		case 2: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 0;  smg_we4 = 1; break;
		case 3: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 0; break;
	}	
}


/********************************************************************
* 名称 : delay_1ms()
* 功能 : 延时1ms函数
* 输入 : q
* 输出 : 无
***********************************************************************/
void delay_1ms(uint q)	 //延时1ms函数
{
	uint i,j;
	for(i=0;i<q;i++)
		for(j=0;j<120;j++);
}


/********************独立按键程序*****************/
uchar key_can;	 //按键值
void key()	 //独立按键程序
{
	static uchar key_new;        //key_new  这个变量的功能是做按键松手检测的 
	key_can = 0;			    //按键值还原
	if(key1 == 0 || key2 == 0 || key3 == 0 || key4 == 0 || key5 == 0 || key6 == 0 || key7 == 0 || key8 == 0)	//按键按下
	{
		delay_1ms(1);	     	//按键延时消抖动
		if(key_new == 1)
		{					 
			key_new = 0;		//key_new = 0   说明按键已按下
			if(key1 == 0)		//确认是按键按下
				key_can = 1; 	//得到按键值 
			if(key2 == 0)		//确认是按键按下
				key_can = 2; 	//得到按键值 
			if(key3 == 0)		//确认是按键按下
				key_can = 3; 	//得到按键值 
			if(key4 == 0)		//确认是按键按下
				key_can = 4; 	//得到按键值 
			if(key5 == 0)		//确认是按键按下
				key_can = 5; 	//得到按键值 
			if(key6 == 0)		//确认是按键按下
				key_can = 6; 	//得到按键值 
			if(key7 == 0)		//确认是按键按下
				key_can = 7; 	//得到按键值 
			if(key8 == 0)		//确认是按键按下
				key_can = 8; 	//得到按键值 
		}
	}else 
		key_new = 1; 	//key_new = 1   说明按键已经松开了	
}


/********************独立按键程序*****************/
void key_1()  	 //主持人独立按键程序
{
	static uchar key_new;        //key_new  这个变量的功能是做按键松手检测的 
 	if(key9 == 0 || key10 == 0 || key11 == 0)		//有按键按下 
	{
		delay_1ms(1);	     	//按键延时消抖动
		if(key_new == 1)
		{					 
			key_new = 0;		//key_new = 0   说明按键已按下
			if(key9 == 0)		//确认是按键按下
				key_can = 10; 	//得到按键值 
			if(key10 == 0)		//确认是按键按下
				key_can = 9; 	//得到按键值 
			if(key11 == 0)		//确认是按键按下
				key_can = 11; 	//得到按键值 
 		}	
		if(key_can == 11)    //抢答器复位
		{
			menu_1 = 0;
			beep = 1;
			flag_weigui = 0;   	
			flag_qd_en = 0;  
			miao = s_time;
			qd2_en = 0;
			flag_num = 0; 
			flag_start = 0;
			beep = 0;    //叫一声   
			delay_1ms(100);
			beep = 1;
		}		
 	}
	else 
		key_new = 1; 	//key_new = 1   说明按键已经松开了	
}

/******************按键处理函数*****************/
void key_with()	  //按键处理函数
{
	if(key_can == 10)    //设置按键
	{
		menu_1 ++;
		if(menu_1 == 1)
		{
			dis_smg[0] = smg_du[s_time % 10];	    //显示设置值
			dis_smg[1] = smg_du[s_time / 10 % 10];	//显示设置值
			dis_smg[2] = 0xfe;
			dis_smg[3] = 0x0c;	            //显示A
		}		
		if(menu_1 == 2)
		{
			dis_smg[0] = smg_du[s2_time % 10];	    //显示设置值
			dis_smg[1] = smg_du[s2_time / 10 % 10];	//显示设置值
			dis_smg[2] = 0xfe;
			dis_smg[3] = 0xa4;	            //显示B
		}
		if(menu_1 > 2)
			menu_1 = 0;
	}
	if(key_can == 9)        //开始抢答键
	{
		flag_start = 1;
		for(i=0;i<2;i++)
		{
			beep = ~beep;
			delay_1ms(20);	
		}
	}

	if((key_can < 9) && (key_can > 0))
	if(menu_1 == 0)
	{
		if(flag_qd_en == 0)	     //没有抢答		 
		{
			if(key_can == 1)
				flag_num = 1;    //1号选手
			if(key_can == 2)
				flag_num = 2;    //2号选手
			if(key_can == 3)
				flag_num = 3;    //3号选手
			if(key_can == 4)
				flag_num = 4;    //4号选手
			if(key_can == 5)
				flag_num = 5;    //5号选手
			if(key_can == 6)
				flag_num = 6;    //6号选手
			if(key_can == 7)
				flag_num = 7;    //7号选手
			if(key_can == 8)
				flag_num = 8;    //8号选手
			for(i=0;i<4;i++)
			{
				beep = ~beep;
				delay_1ms(100);   //蜂鸣器提示抢答
			}
		}
		if(flag_start == 1)		  //开始抢答
		{
			flag_weigui = 0;   	
			flag_qd_en = 1;       //已经抢答	 
			if(qd2_en == 0)
			{
				qd2_en = 1;
				miao = s2_time;				
			}
		}
		else 
		{
			flag_weigui = 1;   //违规了  
		}		
	}

	if(menu_1 == 1)
	{
		if(key_can == 8)   //加键
		{
			s_time ++;     //设置倒计时加1	
			miao = s_time;
			if(s_time >= 99)
				s_time = 99;
			dis_smg[0] = smg_du[s_time % 10];	//显示设置值
			dis_smg[1] = smg_du[s_time / 10 % 10];	//显示设置值
 		}
		if(key_can == 7) 
		{
			if(s_time > 3)
				s_time -- ;	//设置倒计时减1	
			miao = s_time;
			dis_smg[0] = smg_du[s_time % 10];	    //显示设置值
			dis_smg[1] = smg_du[s_time / 10 % 10];	//显示设置值
 		}
	}	

	if(menu_1 == 2)
	{
		if(key_can == 8)  //加键
		{
			s2_time ++;     //设置倒计时加1	
			if(s2_time >= 99)
				s2_time = 99;
			dis_smg[0] = smg_du[s2_time % 10];	//显示设置值
			dis_smg[1] = smg_du[s2_time / 10 % 10];	//显示设置值
 		}
		if(key_can == 7)
		{
			if(s2_time > 3)
				s2_time -- ;	//设置倒计时减1	
			dis_smg[0] = smg_du[s2_time % 10];	    //显示设置值
			dis_smg[1] = smg_du[s2_time / 10 % 10];	//显示设置值
 		}
	}	
}

/******************倒计时处理*****************/
void djs_dis()	   //倒计时处理
{
	static uchar value;
	if((flag_start == 1) && (flag_weigui == 0))
	{
		value ++;
		if(value >= 5)     //1s
		{
			value = 0;
			if(miao != 0)
				miao --;	 //倒计时减一 
		}			
		if(miao <= 5)
		{
			beep = ~beep; //蜂鸣器提示报警
		}
		if(miao == 0)
		{
			beep = 1;     //关闭蜂鸣器
			flag_start = 0;
		}
	}		
}

/********************************************************************
* 名称 : display()
* 功能 : 数码管显示
* 输入 : 无
* 输出 : 无
***********************************************************************/
void display()	   //数码管显示
{
	static uchar i;
	i++;
	if(i >= 4)
		i = 0;	
	P1 = 0xff;	        //消隐 
	smg_we_switch(i);	//位选
	P1 = dis_smg[i];	//段码	
}


/*************定时器0初始化程序***************/
void time_init()	//  定时器0初始化程序
{
	EA   = 1;	 	  //开总中断
	TMOD = 0X01;	  //定时器0、工作方式1
	ET0  = 1;		  //开定时器0中断 
	TR0  = 1;		  //允许定时器0定时
}

/******************主程序**********************/	   
void main()
{
	static uchar value;
	beep = 0;    //开机叫一声   
	delay_1ms(100);
	P0 = P1 = P2 = P3 = 0XFF;    //IO口全部输出为1
 	time_init();  	   //  定时器0初始化程序
	miao = s_time;
	while(1)
	{
		key();	       //独立按键程序
		key_1();  	   //主持人独立按键程序
		if(flag_weigui == 0)
		{
			if((key_can != 0) || (key_can != 0))
				key_with();	   //按键处理函数
		}
		if(flag_200ms == 1)
		{
			flag_200ms = 0;
			if(menu_1 == 0)
			{				
				dis_smg[3] = smg_du[miao / 10 % 10];	//显示设置值
				dis_smg[2] = smg_du[miao % 10];			//显示设置值
				dis_smg[1] = 0xfe;
				dis_smg[0] = smg_du[flag_num];	//显示选手号码	
				if(flag_weigui == 1)  //违规了显示FF
				{
					dis_smg[3] = 0x2e;	//显示F
					dis_smg[2] = 0x2e;	//显示F	
					if(value == 0)		 //违规提示报警
					{
						value = 1;
						for(i=0;i<6;i++)
						{
							beep = ~beep;
							delay_1ms(100);
						}
						beep = 1;					
					}			
				}
				djs_dis();	   //倒计时处理				
			}
		}
		delay_1ms(1);
	}
}

/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{	
	static uchar value;
	TH0 = 0xf8;			
	TL0 = 0x30;     // 2ms
	display();	   //数码管显示
	value ++;
	if(value >= 100)
	{
		value = 0;
		flag_200ms = 1;
	}
}

系统仿真

功能一:抢答30秒倒计时显示

在这里插入图片描述

功能二:选手按答题键号在答题时候60秒倒计时

在这里插入图片描述

功能三:重新设置抢答倒计时时间及选手答题时间

在这里插入图片描述
在这里插入图片描述

功能四:重新设置选手答题时间

在这里插入图片描述

功能五:具有蜂鸣器电路,可以在答题时间剩余5秒时进行提醒选手

在这里插入图片描述

功能六:当主持人未按下开始时,系统检测选手犯规抢答

在这里插入图片描述

工作日志

2020级计科专业实训工作日志
姓名:XXX 班级:计科2001
课程名称:8路抢答器 学号:XXXXXXXXX
日期:2022年6月20日——2022年7月10日,共计21天 指导老师:XXX
项目名称:8路抢答器
项目功能简介:本设计是以八路抢答为基本理念。考虑到依需设定限时回答的功能,利用AT89C51单片机及外围接口实现的抢答系统,利用单片机的定时器/计数器定时和记数的原理,将软、硬件有机地结合起来,使得系统能够正确地进行计时,同时使数码管能够正确地显示时间。用开关做键盘输出,扬声器发生提示。同时系统能够实现:在抢答中,只有开始后抢答才有效,如果在开始抢答前抢答为无效;抢答限定时间和回答问题的时间可在1-99s设定;可以显示是哪位选手有效抢答和无效抢答,正确按键后有音乐提示;抢答时间和回答问题时间倒记时显示,满时后系统计时自动复位及主控强制复位;按键锁定,在有效状态下,按键无效非法。
本人负责模块:代码编写

  • 第1天

今日工作遇到问题及解决方法:在第一天首先是对整个任务的不熟悉。
心得:通过与同学们讨论,并在B站观看视频,熟悉任务流程。

  • 第2天

今日工作遇到问题及解决方法:确定方案(实现8路抢答器的各种函数);
心得:观看视频,学习教程,并熟悉Keil软件。

  • 第3天

今日工作遇到问题及解决方法:了解单片机使用的C语言,并进行查询库函数等等;
心得:观看B站的讲解,与队友进行讨论。

  • 第4天

今日工作遇到问题及解决方法: Protues的不熟悉
心得:观看视频,自己进行仿真学习。

  • 第5天

今日工作遇到问题及解决方法:在编写代码时,整体布局有问题。
心得:与队友的讨论使得思维打开,更好的书写代码。

  • 第6天

今日工作遇到问题及解决方法:程序不能完成仿真;
心得:通过不断的加入断点调试,解决问题。

  • 第7天

今日工作遇到问题及解决方法: 程序中优先级调试有问题
心得:进行加入断点,不断进行实验。

  • 第8天

今日工作遇到问题及解决方法:程序编写完成,其中实现出来有一些小问题;
心得:通过不断的探索,调试,最终解决;

  • 第9天

今日工作遇到问题及解决方法:keil软件和protues软件的结合有一定的问题;
心得:询问队友并在B站观看教程使得有一定的了解。

  • 第10天

今日工作遇到问题及解决方法:实现复杂的功能,例如调整倒计时时间;
心得:通过不断的学习并尝试,使得我们有了新的方法。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐