路灯控制系统设计.docx
《路灯控制系统设计.docx》由会员分享,可在线阅读,更多相关《路灯控制系统设计.docx(19页珍藏版)》请在冰豆网上搜索。
路灯控制系统设计
第一章总体设计
我们在设计路灯系统控制器之前,先了解系统所要实现的各个功能情况。
在设计的过程中,除了要让硬件电路简洁外,还要兼顾软件不能过于复杂。
这样才能达到设计的实际要求,硬件支持软件,软件带动硬件。
本电路设计的主要思路是:
对路灯实现实时控制,最基本的程序是时钟显示程序,之后的设定开灯和关灯时间并能对路灯进行实时控制都是在基本程序上扩展而得到的。
时钟显示程序中最关健是否对数码管进行动态扫描的子程序放在哪里,本课设中把动态扫描程序放在T0中断里,中断的时间是非1MS,也就是说每1MS扫描一次,扫描频率非常快,利用了人眼的视觉残留特性,使程序更加简洁.
调时程序和对路灯的单路控制程序都是按键进行控制的.所以对对按键的控制显得尤为重要了.本课设主程序中一直在对所有的按键进行扫描,当按键一有动作,在第一时间就执行相应的程序,达到实时控制的目的.
根据任务书上的要求进行综合分析,总设计方案分为以下几个步骤:
根据路灯控制系统的功能,选用合理元器件并画出总体原理图。
(见附录Ⅰ)
画出各个程序流程图的各模块。
根据流程图编写出各模块的程序。
完成主程序及实现模块调用。
硬件电路的焊接及调试。
硬件软件的综合调试及程序烧制。
制作PCB版
根据上述步骤,设计总体方案的流程图可简化为如下:
第二章硬件设计
2.1硬件设计原则
一般对于大型的硬件设计的主要思路如下:
一个大型的单片机应用系统的硬件电路设计包含两部分内容:
一是系统扩展,二是系统的配置,即按照系统功能要求配置外围设备,要设计合适的接口电路。
系统的扩展和配置应遵循以下原则:
1、尽可能选择典型电路,为硬件系统的标准化、模块化打下良好的基础。
2、系统扩展与外围设备的配置水平应充分满足应用系统的功能要求。
3、硬件结构应结合程序设计方案一并考虑。
考虑的原则是:
软件能实现的功能尽可能由软件实现,以简化硬件结构。
4、系统中的相关元器件要尽可能做到性能匹配。
5、可靠性及抗干扰设计是硬件设计必不可少的一部分。
6、尽量减少外围。
系统器件越多,器件之间相互干扰也越强,功耗也增大,也不可避免地降低了系统的稳定性[1]。
因而在选择器件上尽量的简洁。
由于本次的毕业设计是一个单片机的小型系统,所以对于上述需要注意的事项在这次设计中并不需要面面具到,我总结了一下,在这次设计中需要注意的问题有:
1)注意硬件方案和软件方案的结合.
2)电路的抗干扰性能.
3)对元器件的保护能力,要在电路中对电流敏感元器件进行限流控制.
硬件设计是本次设计的基础,它的成功与否关系到本次毕业设计的成败。
首先我们依然是对系统进行分析,分析它有些什么功能,用什么样的器件才能实现。
根据任务书的要求,分析出需要的功能有:
具备时钟功能、时间调节的调节、二极管(模拟路灯)的显示功能、定时开灯关灯的时间调整功能、按键控制功能。
基于以上功能要求,我们决定使用AT89C51芯片,显示器件选用数码管(4个),通过电阻驱动,驱动数码管的显示。
数码管采用动态显示。
最终确定的结构框图为:
图2-1结构框图
2.2硬件设计思路
通过硬件电路的分析,当开机后,经过上电复位,时钟显示为17:
59:
50,这时可以调整时、分、秒按钮进行精确调整到当前时间,进行正常走时。
开机后系统内部自定义开路灯时间为18:
00:
00,关路灯时间为6:
00:
00,如果不做调整的话,时间就是下午六点钟开灯,早晨6点钟关灯,但春、夏、秋、冬四季的昼夜并不相等,为了更好的节省资源(电力)。
本设计中可以进行手动调整,根据四季的变化来调整开路灯和关路灯的时间,更有效的节省资源。
本设计中另外的一大特点就是在夜晚12:
00的时候,路灯会熄灭一半,这种设计也是为了节省资源,因为夜深人静的时候,并不需要太多的路灯照明整个路面,只需要点点灯光就行。
然后到早晨六点钟或自己重新设定的时间的时候在关闭其它的路灯。
本次设计中共用到了五个按钮,和四个发光二极管,用来控制路灯和调整时间。
按钮上到下编号为①、②、③、④、⑤。
①为进入调整开灯、关灯的时间按钮,和为退出调整开灯和关灯的按钮,只有通过它才能有效的退出定义开灯和关灯的调整状态,②为调整加一小时的按钮,③为调整减一小时的按钮,④为调加一分钟的按钮,⑤为调整减一分钟的按钮。
发光二极管从上至下的标号是1,2,3……20。
1—10为路灯的左边一排。
11—20为路灯的右边一排。
2.3时钟电路
时钟电路是计算机的心脏,它控制着计算机的工作节奏。
MCS-51单片机允许的时钟频率是因型号而异的。
晶振的选择:
6MHz的晶振,其机器周期是2us。
12MHz的晶振,其机器周期是1us,也就是说在执行同一条指令时用6MHz的晶振所用的时间是12MHz晶振的两倍。
为了提高整个系统的性能我选择了12MHz的晶振。
振荡方式的选择:
内部振荡方式,MCS-51内部都有一个反相放大器,XTAL1、XTAL2分别为反相放大器输入和输出端,外接定时反馈元件以后就组成振荡器,产生时钟送至单片机内部的各个部件,这样就构成了内部振荡方式。
外部振荡方式是把已有的时钟信号引入单片机内。
这种方式适合用来使单片机的时钟与外部信号一致。
在我的这个设计中没有也无需与外部时钟信号一致,所以我选择了内部振荡方式,由于单片机内部有一个高增益反相放大器,当外接晶振后,就构成了自激振荡器并产生振荡时钟脉冲。
晶振我选择了12MHz,相对于6MHz的晶振,整个系统的运行速度更快了。
电容器C1、C2起稳定振荡频率、快速起振的作用,电容值我选择了30pF。
内部振荡方式所得的时钟信号稳定性高。
2.4复位电路
2.4.1可靠性
计算机在启动运行是都需要复位,使中央处理器CPU和系统中的其它部件都处于一个确定的初始状态,并从这个状态开始工作。
MCS-51单片机有一个复位引脚RST,它是施密特触发输入,当振荡器起振后,该引脚上出现2个机器周期(即24个时钟周期)以上的高电平。
使器件复位,只要RST保持高电平,MCS-51保持复位状态。
此时ALE、/PSEN、P0、P1、P2、P3口都输出高电平。
RST变为低电平后,退出复位,CPU从初始状态开始工作。
复位以后内部寄存器的初始状态为(SP=07,P0、P1、P2、P3为0FFH外,其它寄存器都为0。
对于NMOS型单片机,在RST复位端接一个电容至VccHE一个电阻至Vss,就能实现上电自动复位,对于CMOS单片机只要接一个电容至Vcc即可。
如图,在加电瞬间,电容通过电阻充电,就在RST端出现一定时间的高电平,只要高电平时间足够长,就可以使MCS-51有效地复位。
RST端在加电时应保持的高电平时间包括Vcc的上升时间和振荡器起振时间,Vcc上升时间若为10ms,振荡器起振时间和频率有关。
10MHz时间约为1ms,1MHz时约为10ms,所以一般为了可靠地复位,RST在上电时应保持20ms以上的高电平。
图2.5中,RC时间常数越大,上电时RST端保持高电平的时间越长。
振荡频率为12MHZ时,典型值为C=10uF,R=8.2kΩ。
若复位电路失效,加电后CPU从一个随机的状态开始工作,系统就不能正常运转。
图2-2上电复位电路
2.4.2人工复位
除上电自动复位以外,常常需要人工复位,将一个按钮开关并联于上电自动复位电路,按一下开关就RST端出现一段时间的高电平,即使器件复位。
如图所示
图2-3上电和开关复位
而在这次的毕业设计中运用的上电复位电路.即只要一接+5V电压,系统就会自动的复位.出于可靠性和适时性的考虑,我选择了简单实用的上电复位电路上电后,由于电容充电,使RST持续一段高电平时间。
从而实现上电复位操作。
我选择的C=10uF,R=1kΩ。
2.5按键电路
在单片机系统中,通常有且仅有一键按下才视为按键有效。
有效的确认方式通常又可以分为两类。
第一类为按下-释放键方式,系统要求从按下倒释放键才算一次有效按键。
另一类为连击方式,就是一次按键可以产生多次击键效果,其连击频率可自己设定,如3次/秒、4次/秒等。
根据设计的需要,我选择了按下-释放方式,电路如下图9所示。
电路为低电平有效输出方式,当按键按下时输出为低电平。
图2-4开关电路图
在按下-释放键方式时,系统先判断是否有键按下,若不用硬件去抖,则同时进行软件去抖,确认有键按下,然后等待至该按键释放才算依次按键,注意释放键判断同样要进行去抖处理。
2.6显示电路
2.6.1显示方式选择
LED数码显示器时常用的显示器之一,我用的是单片机并口设计的LED数码显示电路。
LED有着显示亮度高、响应速度快的特点,最常用的是七段式LED显示器,又称数码管。
七段式LED显示器内部由7个条形发光二极管和1个小圆点发光二极管组成,根据各管的亮暗组合成字符。
从各发光段电极连接方式分有共阳极和共阴极两种。
所谓共阳方式是指笔画显示器各段发光管的阳极(即P区)是公共的,而阴极互相隔离。
所谓共阴方式是笔画显示器各段发光管的阴极(即N区)是公共的,而阳极是互相隔离的。
显示方式的论证:
方案一:
静态显示方式,就是把共阴极或共阳极的公共端(位选端)连接在一起接地或接5V电源,形成位控端;每一位的段选线(a~dp)作为段控端。
方案二:
动态显示方式,是单片机应用系统中最常用的显示方式,把所有的显示器的同名段选端选线相互并接在一起,由同一个8位并行输出口控制;而各显示器的位选线则分别由不同输出口线控制端。
这样各显示位不能同时显示不同的数字或字符。
因此要选择扫描的方法,即从左到右(或从右到左)依次轮流使每位显示器显示数字或字符并保留一段时间(通常位1ms),由于LED的余辉特性以及人眼视觉的惰性,尽管各位显示器实际上使分时断续地显示,但只要适当选取扫描频率,给人眼的视察印象就会是在连续地显示,而察觉不到闪烁现象。
相对与静态显示动态显示方式虽然占用的CPU空间较多,但使用的硬件少,所占用的端口也较静态显示方式少,可以大大的节约系统的端口资源,所以根据我设计中没有扩展端口,端口资源比较紧张,因此我才用的是动态显示,能节约线路板空间,而且效果也不亚于静态显示。
2.6.2LED的驱动和显示
在电路设计的过程中,单片机的的P0.0-P0.7作为段选输出口,经上拉电阻加到数码管的A-G和DP上,P2.0-P2.5作为位选输出口,经电阻驱动分别加到数码管的COM端。
LED的驱动问题是显示设计中的一个非常重要的环节。
如果驱动能力差,显示器高度就低;且驱动器长期在超负荷下运行很容易损坏。
下面就简单介绍选择LED驱动器时应注意的问题。
显示分为静态显示和动态显示两种方式,由于这两种方式有本质的不同,因此在选择LED驱动器时,一定要分清显示方式。
如果是静态显示,则LED驱动器的选择较为简单,只要驱动器的驱动能力与显示器的工作电流相匹配即可,而且只需要考虑段的驱动,因为,共阳极接+5V,而共阴极接地,所以位的驱动无须考虑。
动态显示则不同,由于一位数据的表示是由段和位选信号共同配合完成的,因此必须同时考虑段与位的驱动能力和位的驱动能力,而且段的驱动能力决定位的驱动能力。
段的驱动能力是由驱动能力决定位的驱动能力。
段的驱动能力是由显示器的亮度决定的,通过发光的二极管的电流较大,其亮度也就越多,对于静态显示器,当某位电量时,此位中点亮的段通过恒定的电流;而对于动态显示器,此电流却是以一定脉冲方式出现的,其峰值电流来考虑。
我采用的是三个数码管集成在一起的管子,这种管子的好处是在接线的时候比较简单,三个COM端接位选接口,非常适合用于动态显示。
我们所采用的是动态显示,虽然有闪烁感,占用的CPU空间较多,但使用的硬件少,能节约线路板空间。
下图为数码显示的硬件电路设计:
图2-5数码显示的硬件电路
说明:
8个上拉电阻是增加[D0-D8]的驱动能力的。
使其更清楚的显示。
六个电阻也是增加驱动能力的。
2.7路灯电路
本设计中用的是四个发光二极管模拟两路路灯控制,每两个二极管用来代替一条街或一个干道的路灯,在加上键盘的点动控制,实现路灯的多路实时控制。
原理图如下:
图2-6路灯电路
附录一元器件清单
电阻:
1K十二只(R1-R12)
5.1K八只
10K五只
排阻:
1K一只
瓷片电容:
20μF两只(C1、C2)
电解电容:
10μF一只(C3)
集成块:
AT89C52
按键:
五只(S1、S2、S3、S4、S5)
数码显示管:
六只(LED1-LED6)
发光二极管:
8只(D1-D8)
石英晶振:
一只(12MHZ)
硬制电路版一块
附录二主程序清单
#include
//作为功能切换键按一下为设置现在时间,再按一下为设置开灯时间,再按一下为设置关灯时间,再按一下显示当前时间
sbitfunction=P1^0;
sbithour_add=P1^1;
sbithour_sub=P1^2;
sbitminute_add=P1^3;
sbitminute_sub=P1^4;
sbitlamp1=P3^0;
sbitlamp2=P3^1;
sbitlamp3=P3^2;
sbitlamp4=P3^3;
bitEN_COCLK=1;
bitBEGIN=0;
unsignedcharcnt;
unsignedcharhour;
unsignedcharminute;
unsignedcharsecond;
unsignedcharhalf_second;
unsignedintms50;
structtime{
unsignedcharhour;
unsignedcharminute;
unsignedcharsecond;
}ds[2];
unsignedcharcodetab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//CA
//unsignedcharcodechoose_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsignedcharcodechoose_bit[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsignedcharidatadisdata[7];
unsignedcharidatadissetup[7];
unsignedcharturnon[4]={0x01,0x02,0x04,0x08};
unsignedcharkey_min_hour=0;//分或秒闪烁
unsignedchardisp_type=0;//记录时间组
unsignedcharrn;//按定时开关键次数
/****************************************
延时1毫秒
*****************************************/
voiddelay1ms(unsignedinti)
{
unsignedinta,b;
for(a=0;a
for(b=0;b<120;b++);
}
/*******************************
显示时钟
*******************************/
voiddisp_clock(void)
{
unsignedchardisplay;
unsignedchari;
disdata[0]=hour/10;
disdata[1]=hour%10;
disdata[2]=minute/10;
disdata[3]=minute%10;
disdata[4]=second/10;
disdata[5]=second%10;
for(i=0;i<6;i++)
{
P0=0xff;
display=tab[disdata[i]];
if(half_second&&(i==3))
{
display&=0x7f;
}
P2=choose_bit[i];
P0=display;
delay1ms
(1);
}
P0=0xff;//关灯
}
/*******************************
显示设置时间值
*******************************/
voiddisp_init(void)
{
unsignedchardisplay;
unsignedchari;
dissetup[0]=ds[disp_type-1].hour/10;
dissetup[1]=ds[disp_type-1].hour%10;
dissetup[2]=ds[disp_type-1].minute/10;
dissetup[3]=ds[disp_type-1].minute%10;
dissetup[4]=ds[disp_type-1].second/10;
dissetup[5]=ds[disp_type-1].second%10;
for(i=0;i<6;i++)
{
P0=0xff;
display=tab[dissetup[i]];
if(i==3||i==1)
{
display&=0x7f;
}
if(++ds[1].hour>=24)
ds[1].hour=0;
break;
default:
break;
}
}
}
if(!
hour_sub)
{
delay1ms(20);
if(hour_sub==0)
{
while(hour_sub==0);
switch(disp_type){
case0:
if(--hour==0xff)
hour=23;
break;
case1:
if(--ds[0].hour==0xff)
ds[0].hour=23;
break;
case2:
if(--ds[1].hour==0xff)
ds[1].hour=23;
break;
default:
break;
}
}
}
if(!
minute_add)
{
delay1ms(20);
if(minute_add==0)
{
while(minute_add==0);
switch(disp_type)
{
case0:
if(++minute>=60)
minute=0;
break;
P2=choose_bit[i];
P0=display;
delay1ms
(1);
}
P0=0xff;
}
/******************************
键盘扫描子程序
******************************/
voidkeyscan(void)
{
unsignedcharhouradd=1;
unsignedcharminadd=1;
if(!
function)
{
delay1ms(20);
if(function==0){
while(function==0);
EN_COCLK=0;
if(++disp_type==3)
{
disp_type=0;
EN_COCLK=1;
}
}
}
if(!
hour_add)
{
delay1ms(20);
if(hour_add==0){
while(hour_add==0);
switch(disp_type)
{
case0:
if(++hour>=24)
hour=0;
break;
case1:
if(++ds[0].hour>=24)
ds[0].hour=0;
break;
case2:
case1:
if(++ds[0].minute>=60)
ds[0].minute=0;
break;
case2:
if(++ds[1].minute>=60)
ds[1].minute=0;
break;
default:
break;
}
}
}
if(!
minute_sub)
{
delay1ms(20);
if(minute_sub==0)
{
while(minute_sub==0);
switch(disp_type)
{
case0:
if(--minute==0xff)
minute=59;
break;
case1:
if(--ds[0].minute==0xff)
ds[0].minute=59;
break;
case2:
if(--ds[1].minute==0xff)
ds[1].minute=59;
break;
default:
break;
}
}
}
}
/**************************************
conctrl_lamp()控制路灯
**************************************/
voidconctrl_lamp(void)
{
//默认状态下设置,晚上6点开灯,早上6点关灯
if((ds[0].hour==0)&&(ds[0].minute==0)||ds[1].hour==0&&(ds[1].minute==0))
{
if((hour==18)&&(minute==0))
P3|=0x0f;
if((hour==0)&&(minute==0))
P3&=~0x05;
if((hour==6)&&(minute==0))
P3&=~0x0f;
}
//如果有设置路灯的开关时间,则按照设定的开关时间开关路灯、
else
{
if((ds[0].hour==hour)&&(ds[0].minute==minute))
{
P3|=0x0f;//控制P3.0--P3.4的二级管分别亮
}
if((ds[1].hour==hour)&&(ds[1].minute==minute))
{
P3&=~0x0f;//控制P3.0--P3.4的二级管分别亮
}
}
}
/************************************
main()主函数
***********************