(不想花积分的可以在附录里找到完整的Proteus布线图以及源程序)
文章目录
1、设计要求
设计十字路口红绿灯控制电路,假设东西路和南北路路口,要求:
- 控制规律:
绿灯->绿灯闪烁(最后1秒,闪烁周期0.2s)->黄灯(1s)->红灯->绿灯……
缺省值:绿灯亮GT=5秒(亮4s+闪1s),黄灯亮1秒,红灯亮RT=4秒 - 东西路方向亮绿灯和黄灯时,南北路方向亮红灯,反之亦然。
扩展:
可修改绿灯时间GT和红灯RT时间,时间修改范围3~9秒。
在两路口用1位数码管动态显示绿灯和红灯亮时的剩余时间。
2、设计具体体现
1、系统概述
通过P1口控制六个交通灯的状态,定时器T0实现精确延时,外部中断0、外部中断1实现对红灯和绿灯的时间调整,P0口、P2口接四位数码管实现南北路倒计时、东西路倒计时、绿灯时长,红灯时长的动态显示。
1、交通灯设计
交通灯实际上有六个状态,即东西绿灯亮南北红灯亮、东西绿灯闪南北红灯亮、东西黄灯亮南北红灯亮、东西红灯亮南北绿灯亮、东西红灯亮南北绿灯闪、东西红灯亮南北黄灯亮。通过不断改变P1口的状态来控制六个状态的循环。
2、绿灯(红灯)时长调节
绿灯时长调节要求范围是3到9秒,思路是利用外部中断0,每来回拨动一次开关,产生一次下降沿,使绿灯时长延长一秒。当绿灯时长为九秒时,再次拨动开关,绿灯时间变为最小值3秒,然后再延长。
红灯时长的调节同理,只是改为利用外部中断1.
3、两路口倒计时及绿灯时长红灯时长的显示
P0口输出段码,P2口实现片选,完成动态显示。
4、拓展(实现路口的单向及双向交通管制)
通过P2-5、P2-6、P2-7的状态改变实现对路口的交通管制。P2-5口为低电平时,路口交通正常运行,P2-5口为高电平时,两方向交通灯红灯闪烁,禁止通行。
P2-6南北交通管制,P2-7东西交通管制,同理。
2、软件设计
主要包括主程序,延时程序,数码管动态显示程序
1、主程序
主程序主要功能是实现交通灯的六个状态的循环,等待绿灯(红灯)时间调节中断,等待路口交通管制中断。
2、 延时程序
延时程序主要功能是通过设置定时器T0延时10ms。调用显示函数。每跑一次,改变P2口的片选,实现四位数码管动态显示。
3、数码管显示程序
数码管显示程序主要是通过查表给P1赋值,点亮数码管。
3、系统的调试及性能分析
通过Proteus和Keil的仿真,该程序可以正常运行,实现设计要求和拓展功能。
4、附录
1、完整电路原理图
2、源程序
/*
*程序:十字路口红绿灯控制
*功能:按要求实现十字路口的红绿灯转换,可以调节红灯时长和绿灯时长,动态显示红灯(绿灯)剩余时间,显示红灯绿灯的时长
*,实现对路口的双向(单向)交通管制
*调节说明:每来回拨动SW1一次,绿灯延长一秒,当绿灯时间为九秒时,再拨动一次,绿灯时间变为三秒(红灯调节方式相同,SW2)
SW3初始状态为接地,当把SW2拨向+5V时,东西向和南北向红灯闪烁,实现双向交通管制,当把SW2拨回初始状态,系统正常运行
(SW4、SW5调节方式相同)
*/
#include<stdio.h>
#include<reg51.h>
void delay10ms(); //延时50ms
void display(int a) ; //显示函数
unsigned int data a1=0; //定时器0中断跳出标志
unsigned int data a2=0; //外部中断0跳出标志
unsigned int data a3=0; // 外部中断1跳出标志
unsigned int data a4=0;
unsigned int data i=0;
unsigned char chashu[11]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77} ; //数码管段码
signed long p=0; //绿灯调整标志
signed long q=0; //红灯调整标志
unsigned long b=80; //各状态时长初值
unsigned long c=20;
unsigned long d=20;
unsigned long e=40;
unsigned long f=20;
unsigned long g=20;
unsigned long s=0;
unsigned long t=0;
unsigned long x=0;
unsigned long y=0;
sbit P1_2=P1^2;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P1_0=P1^0;
sbit P1_3=P1^3;
sbit P2_5=P2^5;
sbit P2_6=P2^6;
sbit P2_7=P2^7;
timer0()interrupt 1
{
a1=1;
}
int0()interrupt 0
{
if(p>=-200&&p<=300) //绿灯调整3-9s
p=p+100;
else if(p==400)
{
p=p-600;
}
a2=1;
}
int1()interrupt 2
{
if(q>=-100&&q<=400) //红灯调整3-9s
q=q+100;
else if(q==500)
q=q-600;
a3=1;
}
void main()
{
EA=1; //开中断总开关
EX0=1; //允许外部中断0中断
IT0=1;
EX1=1; //启动中断
IT1=1;
PX1=1;
PX0=1;
p=0;
q=0;
while(1)
{
while(P2_5==1) //(拓展)实现双向交通管制
{
P0=0x3f;
P1=0xf6;
for(i=10;i>0;i--)
{
delay10ms();
}
P1_0=!P1_0;
P1_3=!P1_3;
for(i=10;i>0;i--)
{
delay10ms();
}
}
while(P2_6==1) //(拓展)实现南北方向交通管制
{
P0=0x3f;
P1=0x33;
}
while(P2_7==1) //(拓展)实现东西方向交通管制
{
P0=0x3f;
P1=0x1e;
}
a2=0;
a3=0;
P1=0x33;
for(b=400+p;b>0;b--) //东西路绿灯亮四秒
{
s=b/100+3;
t=b/100+2;
x=(200+q)/100+2;
y=(400+p)/100+1;
delay10ms();
}
if(a2==0&&a3==0&&P2_5==0&&P2_6==0&&P2_7==0)
{
for(c=100;c>0;c=c-10) //东西路绿灯闪一秒
{
s=2;
t=1;
P1_2=!P1_2; //0.1秒闪一次
for(i=10;i>0;i--)
{
delay10ms();
}
}
if(a2==0&&a3==0&&P2_5==0&&P2_6==0&&P2_7==0) //东西路黄灯亮一秒
{
P1=0x35;
for(d=100;d>0;d--)
{
s=1;
t=0;
delay10ms();
}
if(a2==0&&a3==0&&P2_5==0&&P2_6==0&&P2_7==0) // 南北路绿灯亮两秒
{
P1=0x1e;
for(e=200+q;e>0;e--)
{
s=e/100+2;
t=e/100+3;
delay10ms();
}
if(a2==0&&a3==0&&P2_5==0&&P2_6==0&&P2_7==0)
{
for(f=100;f>0;f=f-10) //南北路绿灯闪一秒
{
s=1;
t=2;
P1_5=!P1_5;
for(i=10;i>0;i--)
{
delay10ms();
}
}
if(a2==0&&a3==0&&P2_5==0&&P2_6==0&&P2_7==0) //南北路黄灯亮一秒
{
P1=0x2e;
for(g=100;g>0;g--)
{
s=0;
t=1;
delay10ms();
}
}
}
}
}
}
}
}
void delay10ms() //延时10ms函数
{
if(a4==0&&P2_5==0&&P2_6==0&&P2_7==0) //显示南北路倒计时
{
P2=0xfd;
display(s);
a4=1;
}
else if(a4==1&&P2_5==0&&P2_6==0&&P2_7==0) //显示东西路倒计时
{
P2=0xfb;
display(t) ;
a4=2;
}
else if(a4==2&&P2_5==0&&P2_6==0&&P2_7==0) //显示东西路红灯时长
{
P2=0xf7;
display(x);
a4=3;
}
else if(a4==3&&P2_5==0&&P2_6==0&&P2_7==0) //显示东西路绿灯时长
{
P2=0xef;
display(y);
a4=0;
}
TMOD=0x01;
TH0=-10000/256;
TL0=-10000%256;
EA=1;
ET0=1;
TR0=1;
while(a1==0);
a1=0;
}
void display(int a) //显示函数
{
a=chashu[a];
P0=a;
}