基于单片机的八位抢答器课程设计报告.docx
《基于单片机的八位抢答器课程设计报告.docx》由会员分享,可在线阅读,更多相关《基于单片机的八位抢答器课程设计报告.docx(16页珍藏版)》请在冰豆网上搜索。
基于单片机的八位抢答器课程设计报告
单片机课程设计报告
题目:
电子抢答器系统设计
一、设计任务
设计一个八路的电子抢答器系统,实现功能为:
可供8个选手使用,可显示30s倒计时,并可显示出抢到的选手号,并伴有提示音。
要求:
(1)设计出硬件电路;
(2)设计出软件编程方法,并写出源代码;
(3)用PROTEUS进行仿真;
二、方案设计
1.设置一个定时开关,开关按下后开始30s倒计时,在定时开关按下之前进行抢答无效,使用两位数码管显示倒计时。
2.在30s内,等待八个按钮中任意一个按下,按下后使用一位数码管显示按下的选手号,同时蜂鸣器发出响声。
3.一旦有选手按下后,其他选手再按下均无效,同时30s倒计时停止计时,等待复位信号。
三、硬件设计
(一)选用AT89C51单片机芯片
单片机(SCM)是单片微型计算机(SingleChipMicrocomputer)的简称。
它是把中央处理器CPU、随机存储器RAM、只读存储器ROM、I/O接口电路、定时/计数器以及输入输出适配器都集成在一块芯片上,构成一个完整的微型计算机。
它的最大优点是体积小,可放在仪表内部。
但存储量小,输入输出适配器简单,功能较低。
目前,单片机在民用和工业测控领域得到最广泛的应用,早已深深地融入人们的生活中。
简单的说,用单片机系统来设计抢答器,实现两组的抢答时间即使是相差几微秒,也可分辨出哪组优先答题。
P0端口(P0.0-P0.7):
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1端口(P1.0-P1.7):
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高电平,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为第八位地址接收。
P2端口(P2.0-P2.7):
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3端口(P3.0-P3.7):
P3口管脚是一个带有内部上拉电阻的8位的双向I/O端口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,
并用作输入。
作为输入端时,由于外部下拉为低电平,P3口将输出电流(ILL)。
(二)关键电路
1.时钟电路
一般选用石英晶体振荡器。
此电路在加电大约延迟10ms后振荡器起振,在XTAL2引脚产生幅度为3V左右的正弦波时钟信号,其振荡频率主要由石英晶振的频率确定。
电路中两个电容C1,C2的作用有两个:
一是帮助振荡器起振;二是对振荡器的频率进行微调。
C1,C2的典型值为30PF。
单片机在工作时,由内部振荡器产生或由外直接输入的送至内部控制逻辑单元的时钟信号的周期称为时钟周期。
其大小是时钟信号频率的倒数,常用fosc表示。
如时钟频率为12MHz,即fosc=12MHz,则时钟周期为1/12µs。
2.复位电路
AT89C51的复位由外部的复位电路实现。
复位电路通常采用上电自动复位和按钮复位两种方式。
本次设计采用按钮复位方式。
单片机的第9脚RST为硬件复位端,只要持续4个机器周期的高电平即可实现复位,硬件复位后的各状态可知寄存器以及存储器的值都恢复到了初始值。
3.数码管显示电路
本次课程设计采用了7SEG-MPX2-CC的两位7段共阴极数码管,用来显示30s倒计时,和7SEG-MPX1-CC的一位7段共阴极数码管,用来显示抢答中的选手号码。
位选端分别与P2口的第七位,第六位以及第零位相接。
同时7段数码管线段通过上拉电阻接power,实现数码管的点亮。
4.报警电路
这里能利用程序来控制单片机P3.7口线反复输出高电平或低电平,即在该口线上产生一定频率的矩形波,接上扬声器就能发出一定频率的声音,再利用延时程序控制“高”“低”电平的持续时间,就能改变输出频率,从而改变音调,使扬声器发出不同的声音。
5.按钮输入电路
8个按钮接P1口,表示8个选手的抢答按钮,一个总开关接P3.0口负责启动定时程序。
(三)整体电路
四、软件设计
(一)系统原理图
数码管显示电路蜂鸣器报警电路
AT89C51单片机
八个抢答按钮定时开关
(二)软件流程图
在本设计中包括了以下四个主要的程序:
主程序;倒计时程序;正常抢答处理程序显示及发声程序。
主流程图如图所示:
程序开始
N
判断KEY1按下
Y
T0定时开始
N,继续计时
是否有选手按下
Y
显示选手号,停止计时,蜂鸣器响
程序结束
(三)关键程序
1.倒计时30s程序段
voidtimer0()interrupt1
{
TH0=(65536-50000)/256;//重新赋初值
TL0=(65536-50000)%256;
aa++;
if(aa==20)
{aa=0;
temp--;
if(temp==0)
{
temp=30;
}
}
利用计时器T0进行30s倒计时,T0工作在方式1下,该方式最大可计时65536us,利用计时公式THx=(65536-x)/256,TLx=(65536-x)%256,设置单次计数初值为50ms,再重复20次就可获得1s,1s完成后aa清零,temp减1,temp总数为30,即可完成30s的倒计时。
再利用七段数码管的动态扫描即可完成倒计时的显示。
2.显示选手号码程序段
if(n==1){
if(k1==0){delay(10);if(k1==0){while(!
k1)i=1;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k2==0){delay(10);if(k2==0){while(!
k2)i=2;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k3==0){delay(10);if(k3==0){while(!
k3)i=3;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k4==0){delay(10);if(k4==0){while(!
k4)i=4;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k5==0){delay(10);if(k5==0){while(!
k5)i=5;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k6==0){delay(10);if(k6==0){while(!
k6)i=6;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k7==0){delay(10);if(k7==0){while(!
k7)i=7;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k8==0){delay(10);if(k8==0){while(!
k8)i=8;TR0=0;n=0;beep=1;delay(500);beep=0;}}
}
变量n为检测信号,当TR0开始计时时置为1,此时才开始检测是否有键按下,程序中包括按键去抖与松手检测,i用来传递键值给一位七段数码管,通过调用共阴极编码数组显示选中的号数,切一旦有键按下后,TR0置0,停止计时。
n置0,之后按下无效。
蜂鸣器延时取反发出按键声。
五、调试过程及结果
(一)系统调试
系统调试包括硬件调试和软件调试,而且两者是密不可分的。
我们设计好的硬件电路和软件程序,只有经过联合调试,才能验证其正确性;软硬件的配人情况以及是否达到设计任务的要求,也只有经过调试,才能发现问题并加以解决、完善,最终开发成实用产品。
由于时间的限制,本次的课程设计只进行了软件调试与硬件仿真测试,利用keiluVision3进行软件调试,利用proteus进行硬件仿真测试。
对于51单片机而言,使用最广泛的软件编写语言主要是用C语言。
在实际工程中,除了一些小型的应用程序或对效率要求较高的关键部分,一般不会采用汇编语言作为系统开发的主语言,取而代之是高级语言,如C语言。
Keil内建了一个仿真CPU用来模拟执行程序,在调试状态下,该仿真CPU可以在没有硬件和仿真机的情况下进行程序的调试。
与真实的硬件执行最明显的就是时序,软件模拟是不可能和真实的硬件具有相同的时序的,具体的表现就是程序执行的速度和各人使用的计算机有关,计算机性能越好,运行速度越快。
将写好的程序编译成HEX文件,通过专用STC软件烧录到单片机当中。
HEX文件是直接能在单片机中运行的软件,实现对单片机的控制。
Proteus满足我们提出的单片机软件仿真系统的标准,并在同类产品中具有明显的优势。
具有模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统的仿真、RS232动态仿真、I2C调试器、SPI调试器、键盘和LCD系统仿真的功能;有各种虚拟仪器,如示波器、逻辑分析仪、信号发生器等。
目前支持的单片机类型有:
68000系列、8051系列、AVR系列、PIC12系列、PIC16系列、PIC18系列、Z80系列、HC11系列以及各种外围芯片。
支持大量的存储器和外围芯片。
该软件是一款集单片机和SPICE分析于一身的仿真软件,功能极其强大,是其他任何一款软件不能相比的。
ISIS是Preoteus系统的中心,具有控制原理图画图的超强的设计环境。
ISIS有下面的优势:
丰富的器件库:
超过27000种元器件,可方便地创建新元件;智能的器件搜索:
通过模糊搜索可以快速定位所需要的器件;智能化的连线功能:
自动连线功能使连接导线简单快捷,大大缩短绘图时间;支持总线结构:
使用总线器件和总线布线使电路设计简明清晰;可输出高质量图纸:
通过个性化设置,可以生成印刷质量的BMP图纸,可以方便地供WORD、POWERPOINT等多种文档使用
(二)具体调试过程
1.软件调试
问题1:
选手抢答后计时未停止。
解决办法:
在if语句判断按钮是否按下后,增加TR0=0语句,使计时器停止计时。
问题2:
倒计时开始之前,以及选手抢答后都可按下按钮。
解决办法:
增加检测变量n,当TR0为1是n为1,当n为1时才开始检测是否有键按下,一旦有键按下n置为0,此后按键均无效。
2.硬件仿真调试
问题1:
七段数码管不亮
解决办法:
开始采用Input作为数码管电源,改为power后显示正常。
问题2:
一位七段数码管管脚较密集无法正常画线
解决办法:
在走线困难的地方按住ctrl键即可。
(三)调试结果
1.keiluVision3
2.proteus
(1)开始计时
(2)7号选手抢答
六、总结
本文研究与设计的八路电子抢答器,采用了常用的电子元器件,利用AT89C51单片机及外围接口实现了抢答系统,利用单片机的定时器/计数器定时和计数的原理,结合了两位数码管动态扫描的方法实现了倒计时的显示,通过两个软件分别进行了软硬件的仿真,实现了抢答器的基本功能。
但在细节上还存在一些问题,如按下抢答按钮后,数码管的显示会存在一定的延时,不能立即显示出抢答到的选手,由于鼠标的限制,不能进行两组同时按下的情况模拟。
由于时间关系,没有对抢答器进行功能扩展。
七、心得体会
通过前期的单片机理论课学习,对单片机有了一定的了解。
在这次课程设计中,我利用了以前学到的利用定时器定时,并循环点亮数码管的方法,并在此基础上增加了8个按键的控制,结合网上的一些资料,完成了本次的课程设计题目。
通过实际的应用,可以巩固我们所学的知识,具体的去深入了解单片机的整个工作过程。
参考文献资料:
[1]张毅刚《单片机原理及应用》高等教育出版社2003年
[2]王章瑞《单片机课程实验及课程设计指导书》西南石油大学2013年
[3]李光飞《单片机课程设计实例指导》北京航天航空大学出版社2004年
[4]冯育长《单片机系统设计与实例指导》西安电子科技大学出版社2007年
[5]王冬梅等《基于单片机的八路抢答器设计与实现》佳木斯大学学报2009年
附录一
抢答器程序代码:
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitkey1=P3^0;//定义"启动"按钮
sbitk1=P1^0;
sbitk2=P1^1;
sbitk3=P1^2;
sbitk4=P1^3;
sbitk5=P1^4;
sbitk6=P1^5;
sbitk7=P1^6;
sbitk8=P1^7;//选手按键
sbitbeep=P3^7;//蜂鸣器
uchartemp;
ucharaa,shi,ge,i;
uintn;
ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77};//共阴极数码管编码
voiddisplay(ucharshi,ucharge);//声明显示子函数
voiddis(uchari);
voiddelay(uintz);//声明延时子函数
voidinit();//声明初始化函数
voidmain()
{
init();//调用初始化子程序
while
(1)
{
if(key1==0)//检测"启动"按钮是否按下
{
delay(10);//延时去抖动
if(key1==0)//再次检测"启动"按钮是否按下
{
while(!
key1);//松手检测,若按键没有释放,key1始终为0,那么!
key1始终为1,程序就一直停在此while语句处
TR0=1;//启动定时器开始工作
n=1;
}
}
display(shi,ge);//调用显示子函数
dis(i);//显示选手号数
if(n==1){
if(k1==0){delay(10);if(k1==0){while(!
k1)i=1;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k2==0){delay(10);if(k2==0){while(!
k2)i=2;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k3==0){delay(10);if(k3==0){while(!
k3)i=3;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k4==0){delay(10);if(k4==0){while(!
k4)i=4;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k5==0){delay(10);if(k5==0){while(!
k5)i=5;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k6==0){delay(10);if(k6==0){while(!
k6)i=6;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k7==0){delay(10);if(k7==0){while(!
k7)i=7;TR0=0;n=0;beep=1;delay(500);beep=0;}}
if(k8==0){delay(10);if(k8==0){while(!
k8)i=8;TR0=0;n=0;beep=1;delay(500);beep=0;}}
}
}
}
voiddelay(uintz)//延时子函数
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddisplay(ucharshi,ucharge)//显示子程序
{
P2=0xbf;
P0=table[shi];
delay(10);
P2=0x7f;
P0=table[ge];
delay(10);//使用动态扫描的方法实现数码管显示
}
voiddis(uchari)
{P2=0xfe;
P0=table[i];
delay(10);
}
voidinit()//初始化子程序
{
n=0;
temp=30;
TMOD=0x01;//使用定时器T0的方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;//定时50ms中断一次
EA=1;//中断总允许
ET0=1;//允许定时器T0中断
}
voidtimer0()interrupt1
{
TH0=(65536-50000)/256;//重新赋初值
TL0=(65536-50000)%256;
aa++;//中断一次变量aa的值加1
if(aa==20)//中断20次后,定时时间为20*50ms=1000ms=1s,将变量temp的值加1
{
aa=0;
temp--;
if(temp==0)
{temp=30;
}
shi=temp%100/10;
ge=temp%10;//分离个位和十位
}
}