基于51单片机十字路口红绿灯管理系统

设计要求

基本要求
①单片机外接多个七段数码管和红黄绿LED;
② 实现基本的十字路口红绿灯管理;
③在每种颜色的灯在结束的10s内,显示倒计时时间;
④能够调节每种颜色灯闪烁的时间。

方案论证

方案一:采用STC89C51单片机作为电路核心部分。选择驱动芯片(74HC245)提高2位7段数码管的驱动能力。通过对外围按键电路的设置调节定时,并且具有蜂鸣器提示。
方案二:采用STC89C51单片机作为电路核心部分。选择驱动芯片(74HC245)与译码器(74LS138)来驱动和译码7位一体数码管,用程序进行动态扫描。通过对外围矩阵按键电路的设置调节定时,并且具有蜂鸣器提示。

电路设计原理

工作原理:在十字路口,分为东西向和南北向,在任一时刻只有一个方向通行,另一方向禁行,持续一定时间,经过短暂的过渡时间,将通行禁行方向对换。
(1)东西方向红灯灭,同时绿灯亮,南北方向黄灯灭,同时红灯亮,倒计时20秒。此状态下,东西向禁止通行,南北向允许通行。
(2)东西方向绿灯灭,同时黄灯亮,南北方向红灯亮,倒计时5秒。此状态下,除了已经正在通行中的其他所以车辆都需等待状态转换。
(3)南北方向红灯灭,同时绿灯亮,东西方向黄灯灭,同时红灯亮,倒计时30秒。此状态下,东西向允许通行,南北向禁止通行。
(4)南北方向绿灯灭,同时黄灯亮,东西方向红灯亮,倒计时5秒。此状态下,除了已经正在通行中的其他所以车辆都需等待状态转换。

系统总体方案设计框图

基于51单片机十字路口红绿灯管理系统_第1张图片
电路组成:该系统控制电路主要由STC89C51单片机和驱动芯片(74HC245)组成。外围电路由按键,数码管,LED灯组成。键盘设置模块对系统输入模式选择及具体通行时间设置的信号,系统进入正常工作状态,执行交通灯状态显示控制,同时将时间数据倒计时输入到LED数码管上实时显示。

数码管与LED显示电路

基于51单片机十字路口红绿灯管理系统_第2张图片
电路组成:该电路由LED发光二极管和2位7段数码管组成。
LED发光二极管的特点:寿命长,光效高,辐射低与低功耗。LED因其高亮度、低热量、长寿命、无毒、可回收再利用等优点,被称为是21世纪最有发展前景的绿色照明光源。
数码管的工作原理:按发光二极管单元连接方式分为共阳极数码管和共阴极数码管。
(1)共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。
(2)共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。

信号显示驱动电路

基于51单片机十字路口红绿灯管理系统_第3张图片
电路设计:将1脚接VCC,19脚接地,整个芯片是输入端输入高则输出端输出高,输入端输入低则输出端输出地,只是相当于驱动作用。
电路特性:74HC245译码器可接受3位二进制加权地址输入(A0, A1和A2),并当使能时,提供8个互斥的低有效输出(Y0至Y7)。74HC245特有3个使能输入端:两个低有效(E1和E2)和一个高有效(E3)。

总体设计图

基于51单片机十字路口红绿灯管理系统_第4张图片

代码

#include 				//头文件
#define uchar unsigned char
#define uint  unsigned int		//宏定义

uchar data buf[4];					//秒显示的变量
uchar data sec_dx=20;  			//东西数默认
uchar data sec_nb=30;			//南北默认值
uchar data set_timedx=20;		//设置东西方向的时间
uchar data set_timenb=30;		//设置南北方向的时间
int n;
uchar data countt0,countt1;//定时器0中断次数
//定义6组开关
sbit  k4=P3^7;      //切换方向
sbit  k1=P3^5;		//时间加
sbit  k2=P3^6;		//时间减
sbit  k3=P3^4;		//确认
sbit  k5=P3^1;		//禁止
sbit  k6=P1^5;		//夜间模式


sbit Red_nb=P2^6;		//南北红灯标志
sbit Yellow_nb=P2^5;	//南北黄灯标志
sbit Green_nb=P2^4;     //南北绿灯标志

sbit Red_dx=P2^3;		//东西红灯标志
sbit Yellow_dx=P2^2;	//东西黄灯标志
sbit Green_dx=P2^1;		//东西绿灯标志
	
sbit Buzz=P3^0;		
bit set=0;				//调时方向切换键标志 =1时,南北,=0时,东西
bit dx_nb=0;			//东西南北控制位
bit shanruo=0;			//闪烁标志位
bit yejian=0;			//夜间黄灯闪烁标志位

uchar code table[11]={	//共阴极字型码
	0x3f,  //--0
	0x06,  //--1
	0x5b,  //--2
	0x4f,  //--3
	0x66,  //--4
	0x6d,  //--5
	0x7d,  //--6
	0x07,  //--7
	0x7f,  //--8
	0x6f,  //--9
	0x00   //--NULL
};

//函数的声明部分
void delay(int ms);			//延时子程序
void key();					//按键扫描子程序
void key_to1();				//键处理子程序
void key_to2();
void key_to3();
void display();				//显示子程序
void logo();   				//开机LOGO
void Buzzer();
//主程序
void main()
{
	TMOD=0X11;	   				//定时器设置
	TH1=0X3C;		
	TL1=0XB0;
	TH0=0X3C;					//定时器0置初值 0.05S
	TL0=0XB0;
	EA=1;						//开总中断
	ET0=1;						//定时器0中断开启
	ET1=1;					   //定时器1中断开启
	TR0=1;						//启动定时0
	TR1=0;						 	//关闭定时1
	EX0=1;						//开外部中断0
	EX1=1;						//开外部中断1
    logo();						//开机初始化
	P2=0Xc3;					// 开始默认状态,东西绿灯,南北黄灯   
    sec_nb=sec_dx+5; 			//默认南北通行时间比东西多5秒
	while(1)					  //主循环
	{	 
		key(); 					//调用按键扫描程序
		display(); 				//调用显示程序
	}	
}
//函数的定义部分
void key(void)	//按键扫描子程序
{	 
	if(k1!=1)							//当K1(时间加)按下时
	{
		display();       				//调用显示,用于延时消抖
		if(k1!=1)							//如果确定按下
		{
		  	TR0=0;	       				//关定时器	
			shanruo=0;					//闪烁标志位关
			P2=0x00;					//灭显示
			TR1=0;							//启动定时1
			if(set==0)					//设置键按下
				set_timedx++;   		//南北加1S
			else
				set_timenb++;    		//东西加1S
			if(set_timenb==100)
				set_timenb=1;
			if(	set_timedx==100)
				set_timedx=1;   		//加到100置1
			sec_nb=set_timenb ; 		//设置的数值赋给东西南北
			sec_dx=set_timedx;			
		  	do
		 	{ 
				display();				 //调用显示,用于延时
			}
			while(k1!=1);			 //等待按键释放
		}
	}

	if(k2!=1)							//当K2(时间减)按键按下时
	{		
		display();       				//调用显示,用于延时消抖  
		if(k2!=1)						//如果确定按下
		{	
		 	TR0=0;         				//关定时器0	
			shanruo=0;					//闪烁标志位关
			P2=0x00;					//灭显示
			TR1=0;						//关定时器1	
			if(set==0)
				set_timedx--;  			//南北减1S
			else
				set_timenb--;  			//东西减1S
			if(set_timenb==0)
				set_timenb=99;	
			if(	set_timedx==0 )
				set_timedx=99;   		//减到1重置99
			sec_nb=set_timenb ;	 		//设置的数值赋给东西南北
			sec_dx=set_timedx;
		  	do	
		    { 
				display();       		//调用显示,用于延时
			}
			while(k2!=1);			   //等待按键释放
		}
	}

	if(k3!=1)							//当K3(确认)键按下时
	{	
		display();       				//调用显示,用于延时消抖
		if(k3!=1)						//如果确定按下
		{
			TR0=1;  						//启动定时器0
			sec_nb=set_timenb;				//从中断回复,仍显示设置过的数值
			sec_dx=set_timedx;				//显示设置过的时间
			TR1=0;							//关定时器1	
			if(set==0)						//时间倒时到0时
			{ 
				P2=0X00;					 //灭显示
				Green_dx=1;						//东西绿灯亮
				Red_nb=1;					//南北红灯亮
				sec_nb=sec_dx+5; 			//回到初值
			}
			else 
			{ 
				P2=0x00;					//南北绿灯,东西红灯
				Green_nb=1;
				Red_dx=1;
				sec_dx=sec_nb+5; 
			}
		}
	}
	 
	if(k4!=1)							//当K4(切换)键按下
    {
		display();       				//调用显示,用于延时消抖
		if(k4!=1)						//如果确定按下
		{  
		 	TR0=0;						//关定时器0	
			set=!set;					//取反set标志位,以切换调节方向
			TR1=0;						//关定时器1
			dx_nb=set;
			do
			{
				display(); 			   //调用显示,用于延时
			}				
			while(k4!=1);			  //等待按键释放
		}
	}	

	if(k5!=1)							//当K5(禁止)键按下时
	{
	   	display();       				//调用显示,用于延时消抖
	   	if(k5!=1)						//如果确定按下
	   	{ 	
	    	TR0=0;						//关定时器
			P2=0x00;					//灭显示
			Red_dx=1;
			Red_nb=1;					//全部置红灯
			TR1=0;
			sec_dx=00;					//四个方向的时间都为00
			sec_nb=00;
			do
			{
				display(); 				//调用显示,用于延时
			}	
			while(k5!=1);			//等待按键释放	
	   	}
	}
	if(k6!=1)							//当K6(夜间模式)按下 
	{
	   	display();       				//调用显示,用于延时消抖 
	   	if(k6!=1)						//如果确定按下
	   	{ 	
	    	TR0=0;						//关定时器
			P2=0x00;
			TR1=1;
			sec_dx=00;					//四个方向的时间都为00
			sec_nb=00;
			do
			{
				display(); 			  //调用显示,用于延时
			}	
			while(k6!=1);			//等待按键释放	
	   	}
	}
}
void display(void) //显示子程序
{		
	buf[1]=sec_nb/10; 		//第1位 东西秒十位
	buf[2]=sec_nb%10; 		//第2位 东西秒个位
	buf[3]=sec_dx/10; 		//第3位 南北秒十位
	buf[0]=sec_dx%10; 		//第4位 南北秒个位		
	P1=0xff;          		// 初始灯为灭的
	P0=0x00;				 灭显示
	P1=0xfe;           		//片选LED1
	P0=table[buf[1]];		//送东西时间十位的数码管编码			
	delay(1);				//延时
	P1=0xff;				//关显示
	P0=0x00;				//灭显示
						   
	P1=0xfd;             	//片选LED2
	P0=table[buf[2]];		 //送东西时间个位的数码管编码
	delay(1);				 //延时
	P1=0xff;				//关显示
	P0=0x00;				//关显示
	P1=0Xfb;		  		//片选LED3
	P0=table[buf[3]];		//送南北时间十位的数码管编码
	delay(1);				//延时
	P1=0xff;				 //关显示
	P0=0x00;				 //关显示
	P1=0Xf7;				 //片选LED4	
	P0=table[buf[0]];		//送南北时间个位的数码管编码
	delay(1);				//延时
}

void time0(void) interrupt 1 using 1  	//定时中断子程序
{
	TH0=0X3C;							//重赋初值
	TL0=0XB0;							//12m晶振50ms//重赋初值
	TR0=1;								//重新启动定时器
	countt0++;							//软件计数加1
	if(countt0==10)						//加到10也就是半秒
	{
		if((sec_nb<=5)&&(dx_nb==0)&&(shanruo==1))  		//东西黄灯闪		
        {
			Green_dx=0;
			Yellow_dx=0;
			Buzz=0;						//蜂鸣器关
		}		   				
	    if((sec_dx<=5)&&(dx_nb==1)&&(shanruo==1))  		//南北黄灯闪		
        {  
			Green_nb=0;
			Yellow_nb=0;
			Buzz=0;					   //蜂鸣器关
		}	
	}
		
	if(countt0==20)	                  	// 定时器中断次数=20时(即1秒时)
	{	countt0=0;						//清零计数器
		sec_dx--;						//东西时间减1
		sec_nb--;						//南北时间减1

		if((sec_nb<=5)&&(dx_nb==0)&&(shanruo==1))  		//东西黄灯闪		
        {
			Green_dx=0;
			Yellow_dx=1;
			Buzz=1;						 //蜂鸣器关
		}		   				
	    if((sec_dx<=5)&&(dx_nb==1)&&(shanruo==1))  		//南北黄灯闪		
        {  
			Green_nb=0;
			Yellow_nb=1;
			Buzz=1;						 //蜂鸣器关
		}		 						
		if(sec_dx==0&&sec_nb==5) 		//当东西倒计时到0时,重置5秒,用于黄灯闪烁时间   
		{
			sec_dx=5;
			shanruo=1;
		}
		if(sec_nb==0&&sec_dx==5)		//当南北倒计时到0时,重置5秒,用于黄灯闪烁时间   
		{
			sec_nb=5;
			shanruo=1;
		}
		if(dx_nb==0&&sec_nb==0)			//当黄灯闪烁时间倒计时到0时,
		{
 	    	Buzz=1;						//蜂鸣器开
			P2=0x00;					//重置东西南背方向的红绿灯
			Green_nb=1;
			Red_dx=1;
			dx_nb=!dx_nb;
			shanruo=0;
			sec_nb=set_timenb;			//重赋南北方向的起始值
			sec_dx=set_timenb+5;		//重赋东西方向的起始值
		}		
		if(dx_nb==1&&sec_dx==0)			//当黄灯闪烁时间到
		{
			P2=0X00;					//重置东西南北的红绿灯状态
			Green_dx=1;					 //东西绿灯亮
			Red_nb=1;					 //南北红灯亮
			dx_nb=!dx_nb;				 //取反
			shanruo=0;					//闪烁
			sec_dx=set_timedx;			//重赋东西方向的起始值
			sec_nb=set_timedx+5;		//重赋南北方向的起始值
		}
	}	
}
void time1(void) interrupt 3 	//定时中断子程序
{
	TH1=0X3C;							//重赋初值
	TL1=0XB0;							//12m晶振50ms//重赋初值
	countt1++;							//软件计数加1
	if(countt1==10)					   // 定时器中断次数=10时(即0.5秒)
	{
			Yellow_nb=0;				//南北黄灯灭
			Yellow_dx=0;				//东西黄灯灭
	}
	if(countt1==20)	                  	// 定时器中断次数=20时(即1秒时)
	{	countt1=0;						//清零计数器
			Yellow_nb=1;					//南北黄灯亮
			Yellow_dx=1;			  	//东西黄灯亮
	}	
}


//外部中断0
void int0(void) interrupt 0 using 1	   //只允许东西通行
{
	TR0=0;								//关定时器0
	TR1=0;								//关定时器1
	P2=0x00;							//灭显示
	Green_dx=1;							//东西方向置绿灯
	Red_nb=1;							//南北方向为红灯
	sec_dx=00;							//四个方向的时间都为00
	sec_nb=00;	
}

//外部中断1
void int1(void) interrupt 2 using 1	  	 //只允许南北通行 
{
	TR0=0;								//关定时器0
	TR1=0;							   //关定时器1
	P2=0x00;							//灭显示
	Green_nb=1;							//置南北方向为绿灯
	Red_dx=1;							//东西方向为红灯
	sec_nb=00;							//四个方向的时间都为00
	sec_dx=00;
}
void logo()//开机的Logo  "- - - -"
{ 
	for(n=0;n<50;n++)	//循环显示----50次
   	{
	    P0=0x40;  //送形“-”
	    P1=0xfe;	//第一位显示
		delay(1);	//延时
	    P1=0xfd;	//第二位显示
		delay(1);	//延时
		P1=0Xfb;	//第三位显示
		delay(1);	//延时
		P1=0Xf7;	//第四位显示
		delay(1);	//延时
	    P1 = 0xff;	//灭显示
	}
}

void delay(int ms)		//延时子程序
{
	uint j,k;
	for(j=0;j<ms;j++)			//延时ms
	   for(k=0;k<124;k++);		//大约1毫秒的延时
}

你可能感兴趣的:(硬件工程,硬件架构,pcb工艺,设计模式)