plc四路抢答器课程设计Word格式文档下载.docx
《plc四路抢答器课程设计Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《plc四路抢答器课程设计Word格式文档下载.docx(26页珍藏版)》请在冰豆网上搜索。
进入下次抢答计时。
4、如果主持人未按"
键,而有人按了抢答按键,犯规抢答,LED上不断闪烁FF和犯规号数并响个不停,直到按下"
键为止。
5、P3.0为开始抢答,P3.1为停止,p1.0-p1.7为八路抢答输入数码管段选P0口,位选P2口低3位,蜂鸣器输出为P3.6口。
P3.2抢答时间调整结,P3.3回答时间调整,P3.4为时间加1调整,P3.5为时间减1调整。
1.3设计方案
1.3.1原理图的确定
在设计开始,我们查了不少关于抢答器的资料,其大体分为2种,一种是纯硬件实现,另一种是单片机实现。
本次课程设计采用单片机实现。
单片机实现抢答的原理图:
1.3.2抢答器的工作原理
抢答器的工作原理是利用单片机的定时器T0、T1中断完成,其余状态循环调用显示子程序,用4个共阴极LED数码管来显示,用P0口作为数码管的八个段选,用P2口中的P2.0、P2.1、P2.2、作为4个数码管其中3个位选,P1口接8个按键,提供选手抢答,P3.0-P3.5四个接四个按键,提供开始、结束、答题时间调整、抢答时间调整,加1、减1调整之用。
1.4抢答器的总体设计
倒计时方案方面利用MCS-51的内部的定时/计时器进行中断计时,配合软件延时实现倒计时。
该方案节省硬件成本,并且能够在定时器/计数器的使用、中断及程序设计方案方面得到锻炼与提高,显示方面采用穿行传输实现动态显示,该方案的硬件连接简单,但动态扫描的显示方式需占用CPU较多的时间,适用于单片机没有太多实时测控的任务场合。
抢答功能:
通过八路按键配合程序来实现抢答功能。
当主持人按下抢答键开始抢答后,此时任一路按下按钮均闭锁其它各路,由程序对键盘译码并显示最先按下抢答键的路数及其当前时间。
抢答限时:
主持人按下抢答键后,设置5秒为抢答时间(此时间可在1-99秒之间修改)。
若5秒内无人抢答,倒计时为0时发出报警,说明该抢答题目作废。
此时闭锁所有抢答按键,只有当主持人再次按下抢答键开始下一次抢答方可抢答。
答题限时:
当选手按下按钮时,启动倒计时(此倒计时时间可在1~99秒之间修改),,倒计时为0时发出报警,说明答题时间到。
第二节硬件电路详细设计
2.1硬件的选择与电路设计
2.1.1芯片的选择
抢答器电路的核心是89C51单片机,其内部带有4KB的FLASHROM,无需外扩程序存储器;
抢答器没有大量的运算和暂存数据现有的128B篇内RAM已经能满足容量需求,故不需外扩片外RAM,系统配有8位8段数码显示管,管采用共阴数码管,作为时钟的显示输出。
2.1.2复位电路的设计
复位电路的设计如图2-1所示:
图2-1复位电路原理图
该复位电路采用上电自动复位和手动复位两种复位方式,图中网络标号所指9连接到单片机的复位引脚。
要实现复位只需在,51系列单片机的RESET引脚上加上5ms的高电平就可以了。
上电复位是利用电容的充电来实现的,即上电瞬间RESET端的电位与Vcc相同,随着电容上储能增加,电容电压也逐渐增大,充电电流减小,RESET端的电位。
这样就会建立一个脉冲电压,调节电容与电阻的大小可对脉冲的持续时间进行调节。
通常若采用12MHz的晶振时,复位元件参数为22μF的电解电容和10kΩ的电阻。
按钮复位电路是通过按下复位按钮时,电源对RESET端维持两个机器周期的高电平实现复位的。
2.1.3晶振电路的设计
MSC-51单片机的定时控制功能是用时钟电路和振荡器完成的,而根据硬件电路的不同,连接方式分为内部时钟方式和外部时钟方式。
本设计中采用内部时钟方式。
单片机内部有一个反相放大器,XTAL1、XTAL2分别为反相放大器的输入端和输出端,外接定时反馈元件组成振荡器(内部时钟方式),产生时钟送至单片机内部各元件。
时钟频率越高,单片机控制器的控制节拍就越快,运算速度也就越快。
一般来说单片机内部有一个带反馈的线性反相放大器,外界晶振(或接陶瓷振荡器)和电容就可组成振荡器,如图2-2所示。
加电以后延时一段时间(约10ms)振荡器产生时钟,不受软件控制,图中Y1为晶振,震荡产生的时钟频率主要由Y1确定。
电容C1,C2的作用有两个:
一是帮助振荡器起振,二是对振荡器的频率起微调作用,典型值为30pF。
晶振电路的设计如图2-2所示:
图2-2晶振电路原理图
2.2数码显示管的选择
数码显示管用来作为时间的显示输出,一般用7段数码显示管。
本次设计中采用7段共阴数码显示管应用简单、可靠性高、成本低,作为显示输出。
连接时段选信号接在P0口的P0.0~P0.6七个I/O口上,P1口是准双向I/O接口在输出驱动部分具有驱动4个TTL负载的能力,即输出电流不大于400μA,所以在接电阻时选择接510Ω限流电阻。
而在位选方面采用单片机P2口的P2.0~P2.2三个I/O口作为位选信号的输出口。
第三节软件详细设计
3.1主程序的设计
此程序的及时采用定时器T0和T1中断完成,其余状态循环调用显示子程序。
系统主程序流程图如图3-1所示。
图3-1系统主程序流程图
3.2显示子程序的设计
由于采用软件动态扫描实现数据显示,显示用十进制BCD码的数据对应段码存放在ROM表中。
显示时,先取出70H~75H某一地址中的数据,然后查得对应的显示段码从P0口输出。
P2口将对应的数码管选中,就能显示该地址单元的数据值。
3.3定时器T0、T1中断服务程序的设计
定时器T0用于响铃程序,定时器T1用于计时程序。
当答题剩余5秒种时P3.6口不断取反使喇叭发出一定频率的声音,提示选手。
中断服务程序流程图如图3-2所示。
图3-2中断服务程序流程图
3.4抢答处理程序的设计
当有选手第一个按下抢答器按扭时数码管显示选手号码,开始倒计时,并锁定抢答。
当在此选手之后再有选手按下按扭时无效,数码管不变。
第四节试验结果及结论
试验的程序通过Keil软件编译,产生HEX文件如图4-1所示:
图4-1程序在Keil软件上编译结果
通过Proteus进行仿真,如仿真结果所示,按下开始后,数码管开始倒计时,仿真结果如图4-2所示。
图4-2仿真的结果
当有选手按下按扭时,数码管显示选手号码并开始倒计时,如图4-3所示
图4-3仿真的结果
通过仿真结果证实,该方案可行。
该设计方案同过51系列单片机的P0口作为段选输出,用P2口作为位选输出,动态扫描LED显示管,显示时间。
并通过接在P3.0-P3.6口的按键开关控制开始、结束、喇叭提示等功能。
P1口接选手按键,控制抢答。
本设计实现简单,成本较低很适合我们大学生动手实践。
第五节PCB板的制作及产品的焊接调试
5.1PCB板的设计
所有准备就绪就开始制做PCB板了,由于PROTEUS软件中元件的封装有很多没有或者和购买的元件不同,所有不少元件都要自己画封装,由于这软件没有上过专门的课程,画封装遇到了很多的问题,开始不知道怎么画,网上的教程很笼统,看得不是很明白,后来自己慢慢摸索知道大体怎么画了,但总是导不到PCB板图中去,就由于这个卡住了个把星期,最后在网上买了一本《基于PROTEUS的电路及单片机系统的设计与仿真》才学会了封装,最后做好了PCB图,如图5.1所示。
。
图5.1PCB板图
5.2制板
PCB板图做好之后就到实验室开始了制板,制板的流程还是比较简单的,首先把图5.1的PCB板图打印到半透明的菲林纸上,然后把裁好的感光板盖在菲林纸上放在暴光机中暴光一分钟,再把暴光好了的感光板在显影水中显影,最后把显完影的感光板放到Fecl3中腐刻,大概等待半个小时左右就可以得到PCB板了。
腐刻好的PCB板经冲洗就可以按照上面的焊盘打孔了。
在制板过程中一共浪费了2块板,第一块是由于实验室帮我们制板的同学放多了显影粉导致很多线路被洗断,然后又紧接着做第二块,第二块做的还是蛮好,结果拿回来后发现数码管的封装画错了,两排针脚的距离太近,完全不能焊接,第二块板宣布报废。
回寝室后仔细查对每个元件的封装,确定没有任何错误后才做好PCB板图到实验室做了第三块板,这次做得很成功,也就是最终使用的PCB板。
5.3焊接与调试
PCB板做好了,孔也打好了,接下来的工作就是焊接。
由于以前没有焊接经验,怕焊坏了板子,中午时候在寝室拿废板子练习了一段时间,总算找到了诀窍,先把烙铁靠近焊盘,紧接着把锡丝往烙铁上送,等锡丝熔了轻轻一提,一个又圆又亮的焊点就做好了。
下午板子做好后就很熟练的在一个小时左右把元件都焊上去了,总体还是蛮好的。
焊接后的板子如图5.2和5.3所示。
图5.2
图5.3
焊接好后的调试就是最激动人心的时候,插上电源,发现数码管不亮,心里一凉,但当按下复位键时数码管就亮了,并且所有功能都能正常运行,于是赶紧到实验室重新打了个拨动开关的孔,用跳线把复位按纽接到了拨动开关,这样抢答器功能基本实现了,心里很是高兴。
高兴完后认真分析开始复位开关的失败才发现复位我在原理图时就画错了,把地和电源接反了,幸好经过我拨动开关的接上能实现功能。
总之这次设计还是比较成功的。
第六节心得体会及成员分工
这样的课程设计真的很有意义,第一次自己真真切切的动手设计制作产品,感觉自己学会了很多,成长了很多,让我找回了往日奋斗的激情,也许这样的机会在大学不会再有了,我会深深的记住这次,记住这次饱含我汗水的综合课程设计。
这次也发现了自身很多的不足,许多的基本电路都不是很熟悉,在画原理图的时候就不停的找以前的教材,以后还得多看看教材,牢记一些基本的电路。
最后在这里忠心的感谢在教学大纲中安排了这次综合课程设计,感谢指导老师的辛勤付出。
第七节附录(源程序)
#include"
reg52.h"
#include<
intrins.h>
absacc.h"
#defineucharunsignedchar
#defineuintunsignedint
#defineulongunsignedlong
/*定义定时器TO时间常数和方式控制字*/
#definev_th00x3c
#definev_tl00xb0
#definev_tmod0x01
ucharbiaozhi,keyzhiii;
/*使用的标志位*/
bitbiaozhi0;
//s2按下标志位
bitbiaozhi1;
//s3按下标志位
bitbiaozhi2;
//抢答器再次按下标志位
bitbiaozhi3;
//s4按下标志位
bitbiaozhi4;
//20s时间到标志位
bitbiaozhi5;
//s5按下标志位
bitbiaozhi6;
//s6按下标志位
bitbiaozhi7;
//s7按下标志位
bitbiaozhi8;
//违规标志位
bitbiaozhi9;
//超时标志位
bitbiaozhi10;
//抢答结束标志位
bitbiaozhi11;
//s2再次按下标志位
ucharled_buf[8];
/*定义LED显示字符段码*/
staticstruct{
ucharascii;
/*查代码的序号*/
ucharstroke;
/*数码管显示段码*/
}codeled_strokes[]={{'
0'
0xc0},{'
1'
0xf9},{'
2'
0xa4},{'
3'
0xb0},{'
4'
0x99},
{'
5'
0x92},{'
6'
0x82},{'
7'
0xf8},{'
8'
0x80},{'
9'
0x90},
{'
-'
0xbf},{'
p'
0x0c},{'
q'
0xff}};
//延时程序
voiddelay()
{
inta=100;
while(a--);
}
//延时程序1
voiddelay1()
intb=1000;
while(b--);
structqiangdaqi/*定义时间结构*/
{
ucharhao;
//号码
ucharjishi;
//计时
};
structqiangdaqitime;
/********************显示缓冲区更新函数*****************************/
voidled_buf_auto_flush(void)reentrant
{//30h--48为ASCII里的0。
led_buf[0]=time.hao/10+0x30;
//获得秒个位
led_buf[1]=time.hao%10+0x30;
//获得秒十位
led_buf[2]='
;
led_buf[3]='
//获得分个位
led_buf[4]='
//获得分十位
led_buf[5]='
led_buf[6]=time.jishi/10+0x30;
//获得时十位
led_buf[7]=time.jishi%10+0x30;
//获得时个位
/****************************段码查找函数*****************************/
ucharget_strokes(ucharc)
uchari=0;
while(led_strokes[i].ascii!
=c)//根据显示信息(序号)查到相应的段控代码
i++;
return(led_strokes[i].stroke);
/***************************显示输出函数******************************/
voidput_on_leds(void)
uchardmask=0xfe;
//位控码初始化
ucharpos;
for(pos=0;
pos<
8;
pos++)
P0=get_strokes(led_buf[pos]);
//取显示段码并输出到段控口
P2=dmask;
//位控码输出到位控口
delay();
//延时
dmask=_crol_(dmask,1);
//修改位控码
/************************************************************************
*函数原型:
voidinit_sys(void);
*功能:
对系统进行初始化并接受用户的初始化时间设置。
************************************************************************/
voidinit_sys(void)
TMOD=v_tmod;
TH0=v_th0;
TL0=v_tl0;
//设置时间初值
TR0=0;
EA=1;
ET0=1;
//开启中断,关闭定时器
}
/************************************************************************
keychuli();
处理与键盘相连的P1口的内容,作为键值。
ucharkeychuli()
uchark;
k=P1;
//P1口内容送K
k=~k;
//取反
k=(k&
0xff);
return(k);
//返回键值
key();
键盘扫描函数,函数返回值即键值。
ucharkey()
ucharkeyzhi,keyzhii;
//抢答器键盘按键键值临时存放
keyzhi=keychuli();
//调P1口处理函数
if(keyzhi!
=0)//有键动作延时去抖动,否则函数返回
put_on_leds();
//再次调P1口处理函数
=0)//真正有键按下,取键值并暂存
keyzhii=keyzhi;
while(keyzhi!
=0)//判按键是否释放,没有释放延时去抖动等待释放
put_on_leds();
}
keyzhi=keyzhii;
//按键释放后恢复按键键值
return(keyzhi);
//返回按键键值
/*复原函数fuyuan;
*/
voidfuwei(void)
{init_sys();
//中断初始化
P3=0xff;
//指示灯灭
led_buf[0]='
//抢答器复位显示p.
led_buf[1]='
led_buf[6]='
led_buf[7]='
biaozhi0=0;
biaozhi1=0;
biaozhi2=0;
biaozhi3=0;
biaozhi4=0;
biaozhi5=0;
biaozhi6=0;
biaozhi7=0;
biaozhi8=0;
biaozhi9=0;
biaozhi10=0;
biaozhi11=0;
time.jishi=0;
time.hao=0;
//标志位清零
/**************************定时器t0中断服务函数***********************************/
voidtimer0(void)interrupt1using2//选用定时器0工作方式为1
{staticucharclick=0;
//定时器0定时中断次数
TL0=v_tl0;
//设置初始值50ms为循环20次为1s,12MHz
++click;
if(click>
=20)//是否到1秒,到1秒,秒加1,否则函数返回
{click=0;
if(time.jishi!
=0)//加到20秒,
{--time.jishi;
if(biaozhi1==1)
TR0=0;
else
{biaozhi4=1;
//20s时间到标志位
if(biaozhi3==1|biaozhi5==1|biaozhi6==1|biaozhi7==1)
{P3=0x77;
//超时亮led3并蜂鸣
biaozhi9=1;
}//超时标志位
else
{P3=0x7d;
//抢答结束亮led1并蜂鸣
biaozhi10=1;
}//抢答结束标志位
}
led_buf_auto_flush();
//LED显示缓冲区时间值更新
/*主函数*/
voidmain()
biaozhi4=0;
biaozhi5=0;
biaozhi8=0;
biaozhi10=0;
init_sys();
//定时器初始化函数,定时器0关闭
//抢答器初始化显示P点
while
(1)
//调显示函数
//调延时函数
keyzhiii=key();
//调键盘扫描函数得到按键键码
switch(keyzhiii)//按键功能控制
{
ca