单片机交通灯控制器方案设计书.docx
《单片机交通灯控制器方案设计书.docx》由会员分享,可在线阅读,更多相关《单片机交通灯控制器方案设计书.docx(19页珍藏版)》请在冰豆网上搜索。
单片机交通灯控制器方案设计书
重庆科技学院
课程设计报告
院(系):
电气与信息工程学院专业班级:
电自专09级2班
学生姓名:
贾瑞楠学号:
2009630943
设计地点(单位)___I506________设计题目:
________《单片机交通灯控制器设计》
完成日期:
2011年9月12日
指导教师评语:
____________________________________________________________________________________________________________________________________________________________________________________________________________________
成绩(五级记分制):
________________指导教师(签字):
________________
摘要
随着生活水平的提高,汽车越来越普及。
因此,红绿灯安装在各个道口上,也渐渐成为了疏导交通车辆最常见和最有效的手段。
信号灯的出现,使交通得以有效管制,对于疏导交通流量、提高道路通行能力,减少交通事故有明显效果。
本系统采用80C51单片机为中心器件来设计交通灯控制器,实现了实时显示当前通行剩余时间;按东西道红灯和南北道绿灯亮22秒后东西道、南北道黄灯闪烁3秒,再东西道绿灯和南北道红灯亮27秒,之后黄灯闪烁3秒的规律控制东西和南北方向的交通灯;能手动设置通行方向3种功能。
4位数码管显示剩余通行时间,2位显示东西方向通行剩余时间,2位显示南北方向通行剩余时间。
本系统实用性强、操作简单、扩展功能强。
关键词:
单片机交通灯动态扫描自动控制手动设置
1交通灯控制器的功能规划
本次设计的交通灯控制器有2种工作模式,分别是正常状态下的自动控制模式和紧急情况下的手动控制模式。
自动控制模式是在单片机的控制下实现东西道与南北道红绿灯循环点亮,倒计时剩3秒时黄灯闪烁警示,并且实时显示当前通行剩余时间。
手动控制模式是在有按键按下的时候相应的通道置于绿灯,另外一个通道置于红灯,直到有返回键按下之后自动返回到自动控制模式。
2方案设计
2.1硬件方案设计
本次课程设计所使用的单片机为STC89C51,STC89C51是一个低电压,高性能CMOS8位单片机,片内含4kbytes的可反复擦写的Flash只读程序存储器和128bytes的随机存取数据存储器(RAM),器件采用STCMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,内置功能强大的微型计算机的STC89C51提供了高性价比的解决方案。
STC89C51主要功能特性:
1、兼容MCS—51指令系统,4k可反复擦写(>1000次)FlashROM
2、32个双向I/O口,可编程UARL通道
3、两个16位可编程定时/计数器,全静态操作0-24MHz
4、1个串行中断,128x8bit内部RAM
5、两个外部中断源,共6个中断源
6、可直接驱动LED,3级加密位
7、低功耗空闲和掉电模式
晶振采用11.0592MHZ提供定时脉冲。
复位电路:
上电复位,按键复位。
本次设计的交通灯控制器涉及的硬件主要有按键、数码管、单片机、LED、、串口,等其它附加设备,其连接关系图如下(由于硬件的原因,黄灯的连接省略):
P0.0-P0.7
数码管
P1.0P1.1P1.2P1.3
图1交通灯硬件连接图
2.2软件方案设计
2.2.1程序实现的基本功能
1)实时显示当前通行剩余时间(4位数码管显示,2位显示东西方向通行剩余时间,2位显示南北方向通行剩余时间);
2)按以下规律控制东西和南北方向的交通灯
22S
3S
27S
3S
……
东西道(EW)
红灯亮
黄灯亮
绿灯亮
黄灯亮
……
南北道(SN)
绿灯亮
黄灯亮
红灯亮
黄灯亮
……
3)能手动设置通行方向。
2.2.2程序结构
本程序主要分为2大块,主程序和定时器0的中断程序。
主程序包括了定时器0和串口的初始化程序。
定时器0的中断程序包括了LED灯的控制,剩余时间的计算以及按键的扫描,计时和刷新显示程序,在定时器0的中断程序中每50ms调用一次。
图2控制程序的结构图
3硬件电路设计与分析
3.1CPU时钟与复位电路
图3单片机复位电路
单片机在正常工作时,RST应保持低电平。
当RST为高电平并且保持10ms以上时间就能实现复位。
当手动复位按下K1时,电容瞬间充电,使RST为高电平,而放电要经历一定时间,这段时间大于10ms,从而实现复位操作。
3.2数码管显示电路
数码管主要是用于数字的显示。
数码管有共阴和共阳的区分,单片机都可以进行驱动,但是驱动的方法却不同。
四位数码管循环电路是由1K的电阻、IN4148二极管和数码管组成,电源+5V通过560的电阻直接给数码管的7个段位供电,P0.0-P0.7对应了接数码管的A,B,C,D,E,F,G和小数点位,P1.0,P1.1,P1.2,P1.3接位选码。
03FH56DH
106H67DH
25BH707H
34FH87FH
466H96FH
图48段LED外形及引脚
本设计采用四位共阴极的七段数码管,显示当前通行剩余时间。
采用动态显示方式,P0口送段选码,P1口的低四位送位选码。
当相应的端口变成高电平时,驱动相应的PNPS8550三极管会导通,+5V通过IN4148二极管和驱动三极管给数码管相应的位供电,这时只要P0口送出数字的显示代码,数码管就能正常显示需要的数字。
图5数码管电路图
3.3按键接口电路
因为本设计能手动设置成东西道(EW)通行或南北道(SN)通行以及返回自动控制模式,故共需要3个按键。
主要是注意按键的去抖动处理,软件法去抖动的实质是软件延时,即检测到某一键状态变化后延时一段时间,再检测该按键的状态是否保持着,如是则作为按键处理,否则,视为抖动,不予理睬。
去抖动的延时时间一般参考资料多描述为20ms左右,在实际应用中应大于20ms。
否则,会导致按一次多处理,影响程序正常执行。
图6按键接口电
3.4LED指示电路
因为所采用的板子共有8个六个共阳极的发光二极管,而2个方向只需要6个发光二极管来分别代表红绿灯。
故选择左边三个从左到右依次为东西道(EW)的红、黄、绿灯,右边三个从右到左依次为南北道(SN)的绿、黄、红灯。
中间2个废弃不用。
图7LED指示灯电路
4软件设计
4.1控制程序的结构及模块划分
本程序主要分为2块,主程序和定时器0的中断程序。
4.2主程序
主程序是主体部分。
包括了定时器0和串口的初始化程序。
图8主程序流程图
对变量、数组、端口的初始化有段码的赋值,数码管显示初值以及各标志位的初始化。
函数的初始化包括了定时器T0的触发方式,中断的打开。
定时器的计数初值为TH0=0xee,TL0=0x00,即定时器定时5ms产生一次中断,200次中断即为1秒,方便计算。
4.3定时器0中断服务程序
定时器0中断服务程序主要是数码管刷新显示程序,用来倒计时显示。
进入中断后,程序又把初值设置成系统初始化时所设定的值,数码管位选标志位自加1,当标志位等于4时,位选标志位又重新赋值0。
数码管采用动态扫描原理,采用switch()语句编写,在每次扫描以前要先关闭所有的位选,然后再送由剩余时间计算函数所计算出的剩余时间值的对应的段码,最后再开由位选标志位所对应的位码,如此便实现了数码管的动态扫描。
因为动态扫描程序是写在定时器内的,而定时器定时为5ms,即每5ms扫描一位数码管,4位数码管,故20ms循环一次。
图9定时器0流程图
4.4LED显示程序
采用的为共阴极LED,本设计将LED的显示程序写在了定时器0中断程序内,采用是的switch()语句,用operation_type来作标志,程序未涉及到黄灯的闪烁,只设计的先是南北道通60s,后是东西道通60s,所以在南北道和东西道分别通的时候只需要case语句就可以了,即
case1:
{R_EW=0。
G_EW=1。
R_SN=1。
G_SN=0。
if(++time_count==12000){
time_count=0。
operation_type=2。
return。
}
i=1。
j=0。
}break。
case2:
{R_EW=1。
G_EW=0。
R_SN=0。
G_SN=1。
if(++time_count==12000){
time_count=0。
operation_type=1。
return。
}
i=0。
j=1。
}break。
4.5数码管显示程序
在程序开头定义了一个数组:
unsignedcharData_Buffer[4]={0,0,0,0}。
前2位分别用来存放南北方向剩余通行时间的十位和个位,后2位分别用来存放东西方向剩余通行时间的十位和个位。
为了便于计算,利用(count-5)的值来计算剩余通行时间,算出十位与个位即可,可写成
Data_Buffer[0]=(count-5)/10。
Data_Buffer[1]=(count-5)%10。
Data_Buffer[2]=(count-5)/10。
Data_Buffer[3]=(count-5)%10。
再由动态扫描程序输出对应的段码,数码管就能实时的显示当前通行剩余时间了。
LED显示程序和数码管显示程序都应该写到while
(1)死循环内。
4.6按键扫描及处理程序
手动模式可以设置为南北通和东西通以及返回到自动模式,所以共需3个按键。
本设计将南北通(SN)和东西通(EW)2个按键分别接P2.0和P2.1,返回按键(BACK)接到了P2.2口,采用扫描法来检测键盘是否按下。
因为按键采用的是扫描法,故需要注意消抖的处理,在此用软件法去抖动即可。
软件法去抖动的实质是软件延时,即检测到某一键状态变化后延时一段时间,再检测该按键的状态是否保持着,如是则作为按键处理,否则,视为抖动,不予理睬。
去抖动的延时时间一般参考资料多描述为20ms左右,在实际应用中应大于20ms。
否则,会导致按一次多处理,影响程序正常执行。
5调试与测试
在程序的最初编写中,由于对time_count的值计算混乱,从而导致了LED的点亮与数码管倒计时不一致,经过仔细的验算,调整对time_count的算法,终于使LED的点亮、黄灯的闪烁能够与倒计时一致了。
在定时器的运用上,由于开始没有对TR0和EA置1,虽然启动了定时器,但是CPU并没有响应中断,导致不能正常计数,从而使程序不能正常运行。
在发现问题并对TR0和EA进行置1后,问题便迎刃而解。
动态扫描过程因为是写在定时器内的,所以是每5ms扫描一个数码管,20ms循环1次,因此时间很短暂,由于数码管的余晖和人眼的视觉暂留作用,造成4位同时亮的假象,达到同时显示的效果。
在对TR0和EA置1后数码管扫描便正常显示了。
在按键上,EW按键、SN按键和BACK按键采用的是扫描法,之前并没有进行去抖动处理,所以导致对按键的扫描不准确。
发现这一错误后,在检测到某一键状态变化后加上一个延时程序,再次检测该按键的状态是否保持着,如是则作为按键处理,否则,视为抖动,不予理睬,即软件法去抖动。
在添加了延时程序后按键便能正常的工作了。
6技术小结
本次设计以STC89C51单片机平台采用C语言编写交通灯控制程序,运用到了LED、数码管、按键等基本元件。
在主程序的循环扫描中,包含了LED灯循环点亮程序、数码管示值计算程序以及键盘扫描程序等。
使用定时器0来定时计数,为数码管的扫描以及总的程序提供时间基础。
2个外部中断分别用来接收按键产生的信号,使程序进入相应的模式。
设计主要包括了交通灯各方向通行状态的显示和数码管对当前通行剩余时间的实时显示,以及手动操作南北或东西方向的通行。
而在程序设计和编写的过程中也遇到许许多多的问题,例如LED灯与数码管数值显示的不一致,按键因为没消抖而产生的混乱等等。
经过不断查找和修改,这些问题也都得到了很好的解决,最终实现了题目要求的功能。
7交通灯控制器使用说明
本交通灯控制器分为自动控制模式和手动控制模式。
按下电源开关后,系统进入自动控制模式,南北方向与东西方向在通行时间结束后自动切换,同时数码管实时显示当前通行剩余时间。
东西方向和南北方向交通灯是切换规律控如下表所示,其中的黄灯为闪烁效果。
22S
3S
27S
3S
……
东西道(EW)
红灯亮
黄灯亮
绿灯亮
黄灯亮
……
南北道(SN)
绿灯亮
黄灯亮
红灯亮
黄灯亮
……
手动控制模式:
上电后,只要按下EW键或是SN键便进入到手动控制模式。
EW键:
东西方向绿灯亮,南北方向红灯亮,即东西方向通行;SN键:
南北方向绿灯亮,东西方向红灯亮,即南北方向通行,无论是按下EW键还是SN键,数码管显示的通行剩余时间均停止。
BACK键:
按下之后返回到自动控制模式,数码管继续计时。
参考文献
[1]张毅刚.新编MSC-51单片机应用设计.哈尔滨:
哈尔滨工业大学出版社,2003
[2]李广弟.单片机基础.北京:
北京航空航天大学出版社,1992
[3]何立民.MCS—51单片机应用系统设计.北京:
北京航空航天大学出版社,1990
[4]何立民.单片机应用技术选编.北京:
北京航空航天大学出版社,1996
[5]王毅.单片机器件应用手册.北京:
人民邮电出版社,1995
[6]房小翠.单片机使用系统设计技术.北京:
国防工业出版社,1999
[7]张毅刚.单片机原理及应用.北京:
高等教育出版社,2009
附录1原理图
附录2源程序
#include
#defineTHC00xee
#defineTLC00x00
unsignedcharcodeDuan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}。
unsignedcharData_Buffer[4]={0,0,0,0}。
staticintcount=0,a=0,b=0,c=0,d=0,i=0。
sbitP10=P1^0。
//四个数码管的位码口定义
sbitP11=P1^1。
sbitP12=P1^2。
sbitP13=P1^3。
sbitkey=P3^4。
staticunsignedcharwei=0。
voiddelay(inti)
{
while(i)
i--。
}
voidmain()
{
IT0=1。
EX0=1。
//使能外部中断0
IT1=1。
EX1=1。
//使能外部中断1
TMOD=0x01。
TH0=THC0。
TL0=TLC0。
TR0=1。
ET0=1。
EA=1。
while
(1)
{
if(count>=100)
{
count=0。
if(d==0)
{
switch(a)
{
case0:
P2=0x7e。
break。
case44:
P2=0xbd。
break。
case45:
P2=0xff。
break。
case46:
P2=0xbd。
break。
case47:
P2=0xff。
break。
case48:
P2=0xbd。
break。
case49:
P2=0xff。
break。
case50:
P2=0xbd。
break。
case51:
P2=0xff。
break。
case52:
P2=0xdb。
break。
case106:
P2=0xbd。
break。
case107:
P2=0xff。
break。
case108:
P2=0xbd。
break。
case109:
P2=0xff。
break。
case110:
P2=0xbd。
break。
case111:
P2=0xff。
break。
case112:
P2=0xbd。
break。
case113:
P2=0xff。
break。
default:
break。
}
}
c=a/2。
if(c>=26)b=56-c。
elseb=25-c。
a++。
if(a==114)
{
a=0。
b=0。
}
if(d==1)
{
P2=0x7e。
a--。
}
if(d==2)
{
P2=0xdb。
a--。
}
if(key==0)
{
delay(5)。
if(key==0)
d=0。
}
Data_Buffer[0]=b/10。
Data_Buffer[1]=b%10。
Data_Buffer[2]=b/10。
Data_Buffer[3]=b%10。
}
}
}
voidtimer0_ISR(void)interrupt1
{
TL0=TLC0。
TH0=THC0。
count++。
wei++。
if(wei>=4)wei=0。
P1|=0xff。
//先关位码
P0=Duan[Data_Buffer[wei]]。
//开段码
//if(wei==1)P0=Duan[Data_Buffer[wei]]|0x80。
switch(wei)//送位码
{
case0:
P10=0。
break。
case1:
P11=0。
break。
case2:
P12=0。
break。
case3:
P13=0。
break。
}
}
voidint0()interrupt0//外部中断0程序入口
{
d=1。
}
voidint1()interrupt2//外部中断1程序入口
{
d=2。
}