找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 40483|回复: 4
收起左侧

基于单片机的八路智能抢答器课程设计论文

[复制链接]
ID:305238 发表于 2018-5-7 17:23 | 显示全部楼层 |阅读模式
西安科技大学

单片机课程设计

基于单片机的八路智能抢答器
电控学院
电气13班
随着科学技术的发展和普及,各种各样的竞赛越来越多,其中抢答器的作用也越来越重要。本文设计出以AT89C51单片机为核心的八路抢答器,采用了数字显示器直接指示,自动锁存显示结果,并自动复位的设计思想,它能根据不同的抢答输入信号,经过单片机的控制处理并产生不同的与输入信号相对应的输出信号,最后通过LED数码管显示相应的路数,即使两组的抢答时间相差几微秒,也可分辨出是哪组优先按下的按键,充分利用了单片机系统结构简单、功能强大、可靠性好、实用性强的特点。
本设计是以抢答为出发点。考虑到依需设定限时回答的功能,利用AT89C51单片机及外围接口实现的抢答系统,利用单片机的定时器/计数器定时和记数的原理,将软、硬件有机地结合起来,使得系统能够正确地进行计时,同时使数码管能够正确地显示时间。用开关做键盘输出,发光二极管和蜂鸣器发出提示。同时系统能够实现:在抢答中,只有开始后抢答才有效,如果在开始抢答前抢答为无效;满时后系统计时自动复位及主控强制复位;按键锁定。

1.

抢答器是一种应用非常广泛的设备,在各种竞赛、抢答场合中,它能迅速、客观的分辨出最先获得发言权的选手。早期的抢答器只有几个三极管、可控硅、发光管等组成,能通过发光管的指示辨认出选手号码。现在大多数抢答器均使用单片机(如MCS-51型)和数字集成电路,并增加了许多新功能,如选手号码显示、抢答前或抢答后的计时、选手得分显示等功能。能够实现抢答器功能的方式有多种,可以采用前期的模拟电路、数字电路或模拟与数字电路相结合的方式。近年来随着科技的飞速发展,单片机的应用正在不断深入。

抢答器作为一种电子产品,早已广泛应用于各种智力知识竞赛场合,但目前所使用的抢答器有的电路较复杂不便于制作,可靠性低,实现起来很困难。为适应目前的状况,需要一种电路简单,元件普通,易于购买等优点,并且能够很好的解决各种问题。而目前的多数抢答器存在几个不足之处:第一,现场线路连接复杂,降低了抢答器的可能性,增加了安装难度;第二,电路设计复杂。因为单片机只能完成号码处理、计时、数据运算等动能,其他功能仍只能靠数字集成电路完成,电路延迟时间较大。

本设计利用AT89C51单片机及外围借口实现抢答系统,利用单片机的定时/计数器和计数原理,将软硬件有机的结合起来,使系统能够正确地进行计时,同时使数码管能够正确的显示时间和选手号码。用按键作为键盘输出,二极管、扬声器发出提示。系统可达到的要求:在抢答中,只有按下开始键抢答才有效,若在之前抢答则记为违规。抢答限定时间及回答限定时间均可调节;可以显示哪位选手抢答,抢答剩余时间及无效抢答,正确按键有声音提示;抢答时间及回答时间倒计时显示,时间计完后可自动复位;剩余时间少于5s时声光报警;具有按键锁定功能。

本设计采用模块化设计智能抢答器,在各种场合下均可应用。各组分别有一抢答按键,主持人有开始键、回答问题开始键、复位键、抢答时间调节键和答题时间调节键。通过设计验证,采用单片机设计,电路连接简单工作可靠,抗干扰性能力强。

通过这次设计,可以掌握单片机的原理,了解多功能抢答器的组成原理,提高动手能力,巩固理论知识,建立一套完整的理论实践体系

2.系统方案论证
2.1总体方案论证

方案一:采用数字电路实现设计

采用CD4511实现设计方案,CD4511为常用的四—七段BCD译码器,当某按键按下时,通过按键传送给CD4511,通过译码,数码管显示。与此同时,这一高电平也送到三极管的基极,三极管导通,继电器吸和,当前状态锁定,再按其他键不起作用,而且断开了其他按键与电路的选择,杜绝了误操作。也可以采用74LS148优先编码器,当有按键按下时,经编码后,送到RS锁存器,然后经74LS48译码送到显示器显示。采用数字电路的好处就是设计简单。共设8个用户输入键,当抢答的时候,其中只有1个是有效按键,其它的都是干扰按键,若按下干扰键。电路通常由两大部分组成:显示器电路和主电源电源(UPS)。

方案二:采用AT89C51实现设计

采用以AT89C51为核心的单片机控制方案。利用单片机灵活的编程设计和丰富的IO端口,及其控制的准确性,不但能实现基本的抢答器功能,还能添加调节功能等等。虽然电路较复杂但功能更加丰富以及人性化。

通过比较以上两种方案,方案二有较大的活动空间,不但能实现所要求的功能而且能在很大的程度上扩展功能,故本次设计采用方案二。

2.2显示模块方案论证

方案一:采用数码管显示

系统采用四位一体八段数码管LED显示。LED应用可分为两大类:一是LED单管应用,包括背光源LED,红外线LED等;另外就是LED显示屏,目前,中国在LED基础材料制造方面与国际还存在着一定的差距,但就LED显示屏而言,中国的设计和生产技术水平基本与国际同步。LED显示屏是由发光二极管排列组成的显示器件。它采用低电压扫描驱动,具有:耗电少、使用寿命长、成本低、亮度高、故障少、视角大、可视距离远等特点。采用LED数码管动态扫描,价格上比较经济实惠且较为节约资源。

方案二:采用LCD显示

采用液晶(LCD)显示。液晶显示器具有低压微功耗、外观小巧、被动显示型、显示信息量大、易于彩色化、无电磁辐射和寿命长等特点。但经济性较LED差。

通过比较以上两种方案,方案一能更好的节约资源以及有更好的经济性,故本次设计采用方案一。

2.3键盘模块方案论证

方案一:采用独立键盘

独立式键盘每个按键占用一条I/O口线,当按键数量较多时,I/O口利用率不高,但程序编制简单。适用于所需按键较少的场合。

方案二:采用矩阵键盘

矩阵式键盘电路连接复杂,但提高了I/O口利用率,软件编程较复杂。适用于需大量按键的场合。

通过比较以上两种方案,由于本次设计所需按键数不多,故本次设计采用方案一。

2.4电路设计最终方案确定

最终选择单片机AT89C51作为主控制器;选择LED作为显示模块,此模块可以显示字母、数字,采用独立按键输入,并且采用发光二极管及蜂鸣器作为报警模块。

3.硬件设计

按照系统设计功能的要求,初步确定设计系统由主控模块、显示模块、键盘模块、蜂鸣器模块和灯光模块5个模块组成,电路系统构成框图如图3-1所示。主控芯片使用AT89C51,显示模块采用LED,键盘模块选用独立按键,其软硬件设计简单,可广泛应用于长时间连续运行的系统中。

3-1 系统总体框图

3.1各单元模块分析及电路分析
3.1.1AT89C51最小系统

AT89C51是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含4k bytes的可反复擦写的只读程序存储器和128 bytes的随机存取数据存储器,期间采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,功能强大的AT89C51单片机可灵活应用于各种控制领域。

AT89C51提供以下标准功能:4k字节Flash闪速存储器,128字节内部RAM,32个I/O口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

本系统中央控制器采用的单片机AT89C51,复位电路采用上电复位电路。外接的晶振为11.0592MHz晶振。系统的最小系统电路图如图3-2所示。

3-1 AT89C51最小系统

3.1.2显示模块

本次设计采用八段数码管显示,是四位一体共阴极数码管,由四个八段数码管集成,高电平点亮。在显示上我们通常采用两种方法:一种是静态显示,一种是动态显示。静态显示是指每个数码管的每一个段码都由一个单片机的I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。静态显示的优点是编程简单,显示亮度高,缺点是占用I/O端口多,实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。LED数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态显示是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态显示。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,但能够节省大量的I/O端口,而且功耗更低。故本次设计采用动态显示方法。其原理图如图3-2所示。

3-2 显示模块

3.1.3键盘模块

键盘是人与万年历实现信息交互的接口,本设计中,我们采用独立键盘。按钮需要十三个,分别为八路抢答按键、开始抢答键、开始答题键、抢答时间调节键、答题时间调节键和复位键。当按键按下,与主控芯片连接的端口被降为低电平,按键松开则也升为高电平。按键采用的是Tack Switch按钮开关,它具有自动恢复(弹回)的功能。当我们按下按钮时,其中的接点接通(或切断),放开按钮后,接点恢复为切断(或接通)。按照尺寸区分,电子电路或微型计算机所使用的Tack Swith可分为8mm、10mm、12mm等。虽然Tack Switch有4个引脚,但实际上,其内部只有一对a接点,即其中两个引脚是内部相连通的,而另外两个引脚内部也是相连通的。

本设计中13个按键实现了抢答,时间调节等功能,独立按键的引入使得体现了本设计的人性化,智能化,功能的强大。其电路分为主持人部分和选手部分。分别实现了控制、调节功能和抢答功能。其电路图如图3-3所示。

(a)主持人部分

(b) 选手部分

3-3 键盘模块

3.1.4蜂鸣器模块

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。 蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。蜂鸣器在电路中用字母“H”或“HA”(旧标准用“FM”、“LB”、“JD”等)表示。

本设计采用电磁式蜂鸣器进行。电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。因此需要一定的电流才能驱动它,单片机I/O引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放大的电路。如蜂鸣器电路图3-7所示,蜂鸣器的正极接到VCC(+5V)电源上面,蜂鸣器的负极接到三极管的发射极E,三极管的基极B经过限流电阻R3后由单片机的P3.7引脚控制,当P3.7输出高电平时,三级管T1截止,没有电流流过线圈,蜂鸣器不发声;当P3.7输出低电平时,三级管导通,这样蜂鸣器的电流形成回路,发出声音。因此,我们可以通过程序控制P3.7脚的电平来使蜂鸣器发出声音和关闭。其电路图如图3-4所示。

3-4 蜂鸣器模块

3.2电路原理图的绘制和电路的焊接
3.2.1原理图绘制软件PROTEL

PROTEL是PORTEL公司在80年代末推出的EDA软件,在电子行业的CAD软件中,它当之无愧地排在众多EDA软件的前面,是电子设计者的首选软件,它包含了电原理图绘制、模拟电路与数字电路混合信号仿真、多层印制电路板设计(包含印制电路板自动布线)、可编程逻辑器件设计、图表生成、电子表格生成、支持宏操作等功能,并具有Client/Server (客户/服务器)体系结构,同时还兼容一些其它设计软件的文件格式,如ORCAD,PSPICE,EXCEL等,其多层印制线路板的自动布线可实现高密度PCB的100%布通率。

3.2.2元器件的焊接

元器件装焊顺序依据的原则是:先低后高,先小后大。一般情况下,应按电阻、电容、二极管、三极管、集成电路、大功率管顺序焊接。

1.对元器件焊接的要求

(1)电阻的焊接:按图将电阻准确装入规定位置,型号标记要易见且方向也尽量一致。要求焊接一种规格后再焊接另一种规格。

(2)电容的焊接:按图将电容准确装入规定位置,并注意有极性电容的极性方向不能错。电容上的型号标记要易见见且方向也尽量一致。电解电容要紧靠PCB板,不可悬浮。

(3)二极管的焊接:正确辨认正负极性后按要求装入规定位置,型号标记要易见,焊接时间尽量可能短。

(4)三极管的焊接:正确辨认各引脚后按要求装入规定位置,型号标记要易见,焊接时间尽可能短。

(5)集成电路(芯片)的焊接:集成电路(芯片)焊接时,要注意按图纸要求检查型号、焊接位置是否符合要求,焊接时先焊芯片边沿的两只引脚,以便使其定位,然后再从左到右或从上到下进行逐点焊接。焊接时间尽可能短,禁止拉焊。

2.焊接质量检查

(1)元器件不得有错装、漏装、错联和歪斜松动等。

(2)焊点应吃锡饱满,无毛刺、无针孔、无气泡、裂纹、挂锡、拉点、漏焊、碰焊、虚焊等缺陷。

(3)焊接后电路板上的金属件表面应无锈蚀和其它杂质。

(4)焊接完成的电路板不得有斑点、裂纹、气泡、发白等现象,铜箔及敷形涂覆层不得脱落、不起翘、不分层。

(5)元器件的引脚或引线表面应渗锡均匀。

4.软件设计

系统软件设计中,我们使用了Keil μVision2。Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时更能体现高级语言的优势,所以我们选择该软件来开发我们的抢答器程序。

4.1 程序设计

当接通电源开始工作后,单片机中的程序开始运行,将对程序进行初始化,以便和单片机芯片达成通信协议。完成初始化后,将进行键盘扫描,同时判断开始按键、调节按键是否按下。最后完成倒计时和选手号码的显示。系统流程图如图4-1所示。

4-1 主流程图

5.仿真调试
5.1仿真软件

系统仿真调试过程,我们使用了Proteus软件。Proteus软件是英国Lab Center Electronics公司出版的EDA工具软件。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前比较好的仿真单片机及外围器件的工具。虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的科技工作者的青睐。

Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年又增加了Cortex和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。

Proteus可提供如下资源。仿真元器件资源:仿真数字和模拟、交流和直流等数千种元器件,有30多个元件库;仿真仪表资源:示波器、逻辑分析仪、虚拟终端、SPI调试器、I2C调试器、信号发生器、模式发生器、交直流电压表、交直流电流表。理论上同一种仪器可以在一个电路中随意的调用。除了现实存在的仪器外,Proteus还提供了一个图形显示功能,可以将线路上变化的信号,以图形的方式实时地显示出来,其作用与示波器相似,但功能更多。这些虚拟仪器仪表具有理想的参数指标,例如极高的输入阻抗、极低的输出阻抗。这些都尽可能减少了仪器对测量结果的影响。Proteus还提供了比较丰富的测试信号用于电路的测试。这些测试信号包括模拟信号和数字信号。

5.2仿真过程

1.初始化。

5-1 初始化

2.按下开始抢答键,进入抢答倒计时。

5-2倒计时

3.有选手按下抢答键,显示选手号码及剩余时间。

5-3 抢答成功

4.倒计时少于5s,报警。

5-4 报警

5.非法抢答。

5-5 非法抢答

5.3出现问题

在原理图绘制的过程中,我们未注意节点的放置,导致初次仿真不成功,但经过查阅资料修改原理图,最终仿真成功达到了抢答器系统预期的结果。

6.总结展望

在硬件电路焊接和软件程序设计分别完成的基础之上,进行软硬件的结合与调试。通过下载将在电脑上已完成的程序下载到单片机芯片中。在调试中发现软件中存在的问题,及时解决问题,确保系统能正常工作并达到设计要求。通过反复的调试与实验,可以证明该系统能够较好地完成设计所需的基本要求。即能够正确的完成抢答器预期功能。

在完成系统时我们遇到了很多困难,从一开始电路设计不够优化导致蜂鸣器不能正常发声,到后来查阅资料一点点丰富我们的设计。在整个设计过程中,我们充分发挥团队精神,分工合作,发挥人的主观能动性,自主学习,学到了许多没学到的知识,较好的完成了作品。相互学习、相互讨论研究,共同进步,完了最初的设想。在电路焊接时虽然没什么大问题,但从中也知道了焊接在整个作品中的重要性,电路工程量大,不能心急,一个个慢慢来不能急于求成。反而达到事半功倍的效果。对电路的设计、布局要先有一个好的构思,才显得电路板美观、大方。程序编写中,由于思路不清晰,开始时遇到了很多的问题,经过静下心来思考,和同组员的讨论,理清了思路,反而得心应手。在此次设计中,知道了做凡事要有一颗平常的心,不要想着走捷径,一步一个脚印。此次比赛也练就了我们的耐心,让我们认识到了学习基础知识的重要性,当设计完整的系统时,要考虑到硬件和软件两者的结合,有时硬件的不足,我们可以用软件程序来弥补,从而节约硬件成本,在设计软件程序时要模块化,可以提高程序的可读性。总之,通过此次单片机课程设计我们的能力得到了全方位的提高。

参考文献
[1]  柴钰.单片机原理及应用.西安:西安电子科技大学出版社,2009
[2]  魏芬.基于Proteus的单片机实验与.清华大学出版社,2015

心得体会

时光飞逝,转眼之间,一个学期又进尾声了。而本学期的单片机综合课程设计也完成了。

俗话说“好的开始是成功的一半”。说起课程设计,我认为最重要的就是做好设计的预习,研究课题,选一个自己有兴趣的题目。其次,要全方面的了解自己所做程序的各个部分。因为只有做到将一切都了然于胸,做起设计才能事半功倍。最后,要重视程序的模块化,以便修改方便,也要注重程序调试和硬件的焊接,掌握其方法和注意事项。

为期一周的单片机课程设计让我受益匪浅。此次课程设计将软件与硬件相结合,考察了我们对单片机的整体掌握程度以及硬件设计能力和软件编程能力。对于我们来说理论知识不成问题,但将理论付诸于实践却是一个很大的障碍。

在确定好我们课程设计的题目之后,我们通过去图书馆翻阅相关设计书籍,并且上网查阅各种资料,确定了基本方案,完成了大体的硬件设计思路。又通过对功能的设计完成了相应的软件设计。最后我们通过软件仿真验证了所设计方案的可行性,并且完成了实物的制作。虽然这其中的过程比较繁琐复杂,但却让我对设计一个完整的系统有了基本的经验。

单片机课是一门实践性很强的课程,仅有课堂上理论知识的学习,对运用好单片机是完全不够的,必须亲自做实验,从实验中吸取教训,总结经验,增加实战经验,加深对单片机的理解,才能更好的运用单片机。这次实训的目的就是为学生提供自己动手设计的机会,让我们能够从实践中学会单片机的开发过程和实际运用。

在设计过程中我们也遇到了许多困难。在进行电路仿真时我们未注意到节点的放置,导致初次仿真不成功。我们通过查找资料和向老师同学询问解决了这个问题。在焊接好电路并且调试之后,我们发现蜂鸣器声音过小,后经查阅资料,知道了是由于单片机I/O引脚输出的电流较小,单片机输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放大的电路,才能使蜂鸣器正常发声。

通过这次实习我学到了许多书本上学不到的知识,丰富了我的视野,也锻炼了我的动手能力并且培养了我的团队精神。通过这次单片机实习,不仅加深了我对单片机理论的理解,更教会我怎样更好地将理论应用到实际当中去。这次实习也将会成为我日后工作学习生活中很重要的经验。


心得体会

本次单片机课程设计,将理论知识与实践充分结合。不仅考察了我们对理论知识的掌握程度,对我们的实际动手能力也有很高的要求。经过这一周的学习,我们对知识的综合利用能力和创新思维都得到了很大的提升。

在确定8路抢答器为课程设计题目后,我们通过上网查阅各种资料,去图书馆翻阅相关设计书籍,确定了基本方案,又通过仿真软件验证了方案的可行性,虽然比较繁琐复杂,但却让我对设计一个电路有了基本的经验。8路抢答器的基本原理是:电源电路为单片机以及其他模块提供标准5V电源。晶振模块为单片机提供时钟标准,使系统各部分协调工作。复位电路模块为单片机系统提供复位功能。单片机作为主控制器,根据输入信号对系统进行相应的控制。选手按下相应的键,蜂鸣器发出提示音,直到按键释放。数码管显示最先按下选手的编号。选手回答完毕,主持人按下复位按钮,数码管清零,蜂鸣器停止发声,可以进入下一题的抢答。

通过此次课程设计,我深刻感受到完成一个电子产品不仅仅是完美的方案和设计思路,还需要熟练细致的动手能力。比如,进行焊接制作时必须精益求精,一丝不苟,必须严格按照事先准备好的电路图精确焊接,确保没有虚焊漏焊,一点的差错都可能导致实验结果的错误,因此必须准确无误还要工整,这样才能在调试中能比较轻松进行,也使得整个电路更好看美观。在焊接结束后,我们把程序导入继续进行调试。调试工作是个精细工作。调试时,我们发现由于蜂鸣器声音太小,发出的报警提示音不能达到预期的效果,所以我们决定修改程序,安装放大电路,是蜂鸣器报警声音变高。

在本次的课程设计过程中,我能运用已学的知识解决我在设计中遇到的问题,使我思考问题的能力得到了很大的提高。在做设计的过程中我查阅了很多的资料,并认真的阅读这些与我的设计相关的资料,从而我的专业涵养得到了提高知识的储备量也有所增加。在做设计时,我复习了很多专业课的知识,这使得我的专业知识也得到了巩固。我也发现自己的很多不足之处。在设计过程中我发现自己考虑问题很不全面,自己的专业知识掌握的很不牢固,所掌握的电路应用软件还不够多,我希望自己的这些不足之处能在今后的工作和学习中得到改善。而且,通过这次设计,我懂得了学习的重要性,学会了坚持和努力,这将为以后的学习做出了最好的榜样!我将会在以后的学习和生活中不断提升自己。


心得体会

为期两周的单片机课程设计结束了,我通过这次设计学到了很多知识。

刚开始开始学习单片机时我感觉很吃力,但在不断的学习过程中我慢慢的对单片机产生了兴趣,并且在编写程序过程中吃力的感觉也慢慢的淡了。我知道了基础知识掌握牢固是非常重要的,并且在学习过程中要学会提问题和自己解决问题。虽然在开始学习单片机时感觉很青涩,但只要坚定自己的学习信心,在付出持之以恒的努力,我相信自己能进一步加深对单片机的了解,在单片机的学习道路上越走越远。

这个学期,我除了在课堂上学习了理论知识以外,还通过试验将所学的知识运用到实践来,在实践中发现问题,强化理论知识。

通过这几天的实训,使我的感触很深,真实“条条大路通罗马”,要达到目的,不同的人就有不同的方法。只要你的方法不错怎样做都可以,而且是各有特色。走出来的结果都有各自的独到之处。实训中有苦有甜,当我们为一个很难攻破的程序找出路时,心情烦躁,感觉自己很不可理喻,当程序一点点的编好后,自己从心底感觉到一点小小的安慰,看着自己的成果。感觉很欣慰,有一丝丝的甜意,这几天的实训使自己的思维逻辑也有了小小的进步。

这次单片机实训让我懂得很多。首先,不管做什么事,计划是很重要的。没有一个完好的计划,做事情就会没有一个好的顺序,做事情会比较乱,很难成功。而有一个好的计划,不管做什么事都会事半功倍,做事心中有数,,明确重点和缓急,不会有疏漏。这样才能提高成功率。其次,做事要多动脑,选出最好的方法。一件事往往有多种解决方法,一个好的方法,不仅能使事情事半功倍,而且往往决定最后的成与败,所以做事时一定要多动一下脑筋,想出最好的方法。要注意细节。细节决定成败,这句话在这次课题中不仅一次得到了印证,特别是在软件的编程过程中,一点点的错误就会使你整个程序不能运行。因此我们不仅仅要有整体意识,也要注意细节,不要因一个关键地方的一个细节而导致满盘皆输。

这次实训的经历让我终身受益,我感受到了这次实训,是要真真正正用心去做一件事情,是真正的自己学习的过程和研究的过程,没有学习就不可能有研究的能力,没有了自己的研究就不会有突破,希望这次的经历能让我在以后的学习中激励我更大的进步。


附录一:总电路图

附录二:仿真

附录三程序清单
  1. #include<at89x51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. char s;
  5. uchar num=0;
  6. char time=20;              //抢答时间
  7. char datitime=30;              //答题限时时间
  8. uint tt,t1;
  9. bit flag,s_flag=1,b_flag,fall_flag,fw_flag;              //标志位
  10. bit K_startcountflag,K_timecountflag;              //时间调整标志位
  11. sbit K0=P3^0;
  12. sbit beep=P3^7;         //蜂鸣器输出口
  13. sbit rled=P3^1;                            //指示灯输出口
  14. sbit K1=P1^0;                            //按键输出口
  15. sbit K2=P1^1;
  16. sbit K3=P1^2;
  17. sbit K4=P1^3;
  18. sbit K5=P1^4;
  19. sbit K6=P1^5;
  20. sbit K7=P1^6;
  21. sbit K8=P1^7;
  22. sbit K_fw=P3^2;              //答题计时键
  23. sbit K_startcount=P3^3;              //开始抢答时间调整键
  24. sbit K_timecount=P3^4;              //答题计时时间调整键
  25. sbit K_Time=P3^5;
  26. void delay(uchar ms)
  27. {
  28.               uchar y;
  29.               for(;ms>0;ms--)
  30.                             for(y=120;y>0;y--);
  31. }
  32. uchar code tabledu[]={0x3f,0x06,0x5b,0x4f,
  33. 0x66,0x6d,0x7d,0x07,
  34. 0x7f,0x6f,0x77,0x7c,
  35. 0x39,0x5e,0x79,0x71
  36. };
  37. uchar code tablewe[]={0XFE,0XFD,0XFB,0XF7};
  38. void T0_Init(void)
  39. {
  40.               TMOD=0X01;
  41.               TH0=(65536-2000)/256;
  42.               TL0=(65536-2000)%256;
  43.               TH1=(65536-2000)/256;
  44.               TL1=(65536-2000)%256;
  45.               ET0=1;
  46.               ET1=1;
  47.               EX0=1;
  48.               EA=1;
  49.               IT0=1;
  50.               P0=0;
  51. }
  52. void Key_Scan(void)                            //开始键扫描
  53. {
  54.               if(K0==0)
  55.               {
  56.                             delay(10);
  57.                             if(K0==0)
  58.                             {
  59.                                           while(!K0);
  60.                                           TR0=1;
  61.                                           s=time;
  62.                                           tt=0;
  63.                                           flag=1;
  64.                                           s_flag=1;
  65.                                           b_flag=1;
  66.                                           num=0;
  67.                                           beep=1;
  68.                                           rled=1;
  69.                                           fall_flag=0;              //清除违规标志位
  70.                                           K_startcountflag=0;
  71.                                           K_timecountflag=0;
  72.                             }
  73.               }
  74. }
  75. void Scan(void)                            //八路热键扫描(哪个键先按下,哪个优先级最高)
  76. {
  77.               if(K1==0)
  78.               {
  79.                             delay(10);
  80.                             if(K1==0)
  81.                             {
  82.                                           while(!K1);
  83.                                           num=1;                            //数码管显示1号"1"
  84.                                           TR0=0;                            //关闭定时器0,时间停止
  85.                                           TR1=1;                            //打开定时器1,使扬声器响一声
  86.                                           s_flag=0;              //关闭开始键标志位,使再按其他七个键不会响应
  87.                             }
  88.               }
  89.               if(K2==0)                                          //下面七个键的处理同上
  90.               {
  91.                             delay(10);
  92.                             if(K2==0)
  93.                             {
  94.                                           while(!K2);
  95.                                           num=2;                           
  96.                                           TR0=0;
  97.                                           TR1=1;
  98.                                           s_flag=0;              //重要
  99.                             }
  100.               }
  101.               if(K3==0)
  102.               {
  103.                             delay(10);
  104.                             if(K3==0)
  105.                             {
  106.                                           while(!K3);
  107.                                           num=3;
  108.                                           TR0=0;
  109.                                           TR1=1;
  110.                                           s_flag=0;
  111.                             }
  112.               }
  113.               if(K4==0)
  114.               {
  115.                             delay(10);
  116.                             if(K4==0)
  117.                             {
  118.                                           while(!K4);
  119.                                           num=4;
  120.                                           TR0=0;
  121.                                           TR1=1;
  122.                                           s_flag=0;
  123.                             }
  124.               }
  125.               if(K5==0)
  126.               {
  127.                             delay(10);
  128.                             if(K5==0)
  129.                             {
  130.                                           while(!K5);
  131.                                           num=5;
  132.                                           TR0=0;
  133.                                           TR1=1;
  134.                                           s_flag=0;
  135.                             }
  136.               }
  137.               if(K6==0)
  138.               {
  139.                             delay(10);
  140.                             if(K6==0)
  141.                             {
  142.                                           while(!K6);
  143.                                           num=6;
  144.                                           TR0=0;
  145.                                           TR1=1;
  146.                                           s_flag=0;
  147.                             }
  148.               }
  149.               if(K7==0)
  150.               {
  151.                             delay(10);
  152.                             if(K7==0)
  153.                             {
  154.                                           while(!K7);
  155.                                           num=7;
  156.                                           TR0=0;
  157.                                           TR1=1;
  158.                                           s_flag=0;
  159.                             }
  160.               }
  161.               if(K8==0)
  162.               {
  163.                             delay(10);
  164.                             if(K8==0)
  165.                             {
  166.                                           while(!K8);
  167.                                           num=8;
  168.                                           TR0=0;                           
  169.                                           TR1=1;
  170.                                           s_flag=0;
  171.                             }
  172.               }
  173. }
  174. void display(void)
  175. {
  176.               if(flag==1)                            //开始键按下,开始计时抢答
  177.               {
  178.                             if(num!=0)              //如果有人抢答,则显示相应的几号
  179.                             {
  180.                                           P0=tabledu[num];              //显示几号抢到了
  181.                                           P2=tablewe[0];
  182.                                           delay(2);
  183.                                           P0=0;
  184.                                           P2=0XFF;
  185.                             }
  186.                             else                            //否则没人抢答,则前面不显示几号
  187.                             {
  188.                                           P0=0;                           
  189.                                           P2=0XFF;
  190.                             }
  191.                             P0=tabledu[s/10];                            //下面为显示抢答倒计时
  192.                             P2=tablewe[2];
  193.                             delay(2);
  194.                             P0=0;
  195.                             P2=0XFF;
  196.                             P0=tabledu[s%10];
  197.                             P2=tablewe[3];
  198.                             delay(2);
  199.                             P2=0XFF;
  200.                             P0=0;
  201.               }
  202.               else              //如果开始键没有按下,则显示F FF(若有违规者,则显示违规号码及 FF)或时间调整
  203.               {
  204.                             if(fall_flag==1)              //违规显示
  205.                             {
  206.                                           if(num!=0)
  207.                                           {
  208.                                                         P0=tabledu[num];              //显示几号违规了
  209.                                                         P2=tablewe[0];
  210.                                                         delay(2);
  211.                                                         P0=0;
  212.                                                         P2=0XFF;
  213.                                                         P0=tabledu[15];                            //下面显示 FF,表示违规了
  214.                                                         P2=tablewe[2];
  215.                                                         delay(2);
  216.                                                         P0=0;                            //消隐
  217.                                                         P2=0XFF;
  218.                                                         P0=tabledu[15];
  219.                                                         P2=tablewe[3];
  220.                                                         delay(2);
  221.                                                         P0=0;
  222.                                                         P2=0XFF;
  223.                                           }
  224.                                           else                           
  225.                                           {
  226.                                                         P0=0;                           
  227.                                                         P2=0XFF;
  228.                                           }
  229.                             }
  230.                             else              //没有人违规才显示调整时间
  231.                             {
  232.                                           if(K_startcountflag==1)
  233.                                           {
  234.                                                         P0=0X6D;                            //第一位数码管显示"5(S)"(表示抢答时间调整)
  235.                                                         P2=tablewe[0];
  236.                                                         delay(2);
  237.                                                         P0=0;
  238.                                                         P2=0XFF;
  239.                                                         P0=tabledu[time/10];              //下面显示调整的抢答时间
  240.                                                         P2=tablewe[2];
  241.                                                         delay(2);
  242.                                                         P0=0;
  243.                                                         P2=0XFF;
  244.                                                         P0=tabledu[time%10];
  245.                                                         P2=tablewe[3];
  246.                                                         delay(2);
  247.                                                         P0=0;
  248.                                                         P2=0XFF;
  249.                                           }
  250.                                           else if(K_timecountflag==1)
  251.                                           {
  252.                                                         P0=0X07;              //第一位与第二位数码管合起来显示"T",表示答题时间调整
  253.                                                         P2=tablewe[0];
  254.                                                         delay(2);
  255.                                                         P0=0;
  256.                                                         P2=0XFF;
  257.                                                         P0=0X31;
  258.                                                         P2=tablewe[1];
  259.                                                         delay(2);
  260.                                                         P0=0;
  261.                                                         P2=0XFF;
  262.                                                         P0=tabledu[datitime/10];
  263.                                                         P2=tablewe[2];
  264.                                                         delay(2);
  265.                                                         P0=0;
  266.                                                         P2=0XFF;
  267.                                                         P0=tabledu[datitime%10];
  268.                                                         P2=tablewe[3];
  269.                                                         delay(2);
  270.                                                         P0=0;
  271.                                                         P2=0XFF;
  272.                                           }
  273.                                           else                            //否则显示F FF
  274.                                           {
  275.                                                         P0=tabledu[15];
  276.                                                         P2=tablewe[0];
  277.                                                         delay(2);
  278.                                                         P0=0;
  279.                                                         P0=tabledu[15];
  280.                                                         P2=tablewe[2];
  281.                                                         delay(2);
  282.                                                         P0=0;                            //消隐
  283.                                                         P2=0XFF;
  284.                                                         P0=tabledu[15];
  285.                                                         P2=tablewe[3];
  286.                                                         delay(2);
  287.                                                         P0=0;
  288.                                                         P2=0XFF;
  289.                                           }            
  290.                             }            
  291.               }
  292. }
  293. void Time_Scan(void)                            //调整时间键扫描
  294. {
  295.               if(K_startcount==0)                            //抢答时间调整
  296.               {
  297.                             delay(10);
  298.                             if(K_startcount==0)            
  299.                             {
  300.                                           while(!K_startcount);
  301.                                           time++;                                         
  302.                                           if(time==50)
  303.                                           {
  304.                                                         time=20;
  305.                                           }
  306.                                           K_startcountflag=1;              //将抢答时间标志位置1
  307.                                           K_timecountflag=0;              //同时关闭答题时间标志位
  308.                             }
  309.               }
  310.               if(K_timecount==0)                            //答题时间调整
  311.               {
  312.                             delay(10);
  313.                             if(K_timecount==0)
  314.                             {
  315.                                           while(!K_timecount);
  316.                                           datitime++;
  317.                                           if(datitime==60)
  318.                                           {
  319.                                                         datitime=30;
  320.                                           }
  321.                                           K_timecountflag=1;
  322.                                           K_startcountflag=0;
  323.                             }
  324.               }
  325. }
  326. void main(void)
  327. {
  328.               T0_Init();
  329.               while(1)
  330.               {
  331.                             Key_Scan();                            //开始键扫描
  332.                             if((flag==0)&(s_flag==1))              //当开始键没按下及没有人违规时才可进行时间调整
  333.                             {
  334.                                           Time_Scan();
  335.                             }
  336.                             if((flag==1)&(s_flag==0))//当开始键按下及有人抢答才进行开始回答计时倒计时
  337.                             {
  338.                                           if(K_Time==0)
  339.                                           {
  340.                                                         delay(10);
  341.                                                         if(K_Time==0)
  342.                                                         {
  343.                                                                       while(!K_Time);
  344.                                                                       s=datitime;
  345.                                                                       TR0=1;
  346.                                                                       tt=0;
  347.                                                                       TR1=1;
  348.                                                         }
  349.                                           }
  350.                             }            
  351.                             if((flag==0)&(s_flag==1))              //违规
  352.                             {
  353.                                           Scan();
  354.                                           if(num!=0)                            //开始键没有按下时,有人按下了抢答器,则置违规标志位
  355.                                           {
  356.                                                         fall_flag=1;
  357.                                                         rled=0;
  358.                                           }
  359.                             }
  360.                             if((flag==1)&(s_flag==1))              //如果开始键按下且抢答键没有人按下,则进行八路抢答键扫描
  361.                             {
  362.                                           Scan();
  363.                             }            
  364.                             display();                            //显示到数码管上
  365.               }
  366. }

  367. void int0(void) interrupt 0
  368. {
  369.               if(K_fw==0)
  370.               {            
  371.               while(!K_fw)
  372.               {
  373.                                while(K0==1)
  374.                             {P0=tabledu[15];
  375.                             P2=tablewe[0];
  376.                             delay(2);
  377.                             P0=0;
  378.                             P0=tabledu[15];
  379.                             P2=tablewe[2];
  380.                             delay(2);
  381.                             P0=0;
  382.                             P2=0xFF;
  383.                             P0=tabledu[15];
  384.                             P2=tablewe[3];
  385.                             delay(2);
  386.                             P0=0;
  387.                             P2=0xFF;}            
  388.               }
  389.               }
  390. }
  391. void timer0(void) interrupt 1
  392. {
  393.               TH0=(65536-2000)/256;              //2ms
  394.               TL0=(65536-2000)%256;
  395.               if(b_flag)              //开始(START)键按下,嘟一声(长1秒),表示开始抢答
  396. ……………………

  397. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

全部资料51hei下载地址:
http://www.51hei.com/bbs/dpj-116725-1.html


回复

使用道具 举报

ID:438216 发表于 2018-12-12 11:50 来自手机 | 显示全部楼层
哇塞,谢谢大佬啊
回复

使用道具 举报

ID:560562 发表于 2019-6-14 15:46 | 显示全部楼层
兄弟剩下代码呢,这链接不对吧
回复

使用道具 举报

ID:644142 发表于 2019-11-18 11:05 | 显示全部楼层
这个剩下的代码咋办,链接不行啊
回复

使用道具 举报

ID:736988 发表于 2020-5-4 16:40 | 显示全部楼层

这个剩下的代码咋办,链接不行啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表