51交通灯

一、基本原理

利用51单片机控制各个路口红绿灯及时间显示。

设计的重点:

1、各个路口红绿灯亮灭的规则,暂不考虑左转方向;

2、倒计时的实现,利用单片机的定时器进行计数得到秒信号;

3、时间显示:东西南北四个方向的时间一致,当东西方向为60秒绿灯通行时间,同时南北方向为60秒红灯禁止时间,因此硬件连接时可考虑东西南北方向可采用同一接法;最后相当于2个数码管动态显示。

4、按键设置(扩展要求):设置键按一次,设置主干道通信时间(即次干道禁止时间),按第二次,设置主干道禁止时间(即次干道通信时间),按第三次,可作为紧急通信键。设置时间需要确定,可通过确定键实现,也可通过延时确定,如10秒。当然也可根据需要增加相应的按键。

仿真图

注意修改每个灯的管脚,位选管脚等。

cpp 复制代码
#include <REGX52.H>
#define ON 0 
#define OFF 1 
unsigned char tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
short EW_Time=60,NS_Time=60,EW_SetTime=60,NS_SetTime=60;
unsigned char Time_Mode=0,Flag_Blink=0;
sbit Switch_Time1=P3^3;//数码管位选
sbit Switch_Time2=P3^2;
sbit EW_Red=P2^0;	   				//东西向红灯
sbit EW_Green=P2^3;	   				//东西向绿灯
sbit EW_Yellow=P2^2;	   		    //东西向黄灯
sbit NS_Red=P2^5;	   				//南北向红灯
sbit NS_Green=P2^7;	   				//南北向绿灯
sbit NS_Yellow=P2^6;	   			//南北向黄灯
sbit Power=P2^4;void delay_ms(unsigned int ms)//ms延时函数
{
	unsigned int i,j;
	for(i=ms;i>0;i--)
		for(j=110;j>0;j--);
 
}

void Timer_Init()//定时器初始化
{
	TMOD=0x01; //设置为定时器0工作模式1
	TL0=(65536-50000)%256;//低八位
	TH0=(65536-50000)/256;//高八位
	TR0 = 1; //定时器0开始计时
	EA=1;//开启总中断
	ET0=1;//开启定时器0中断
}

void Nixie(unsigned char Data)//数码管显示
{
		Switch_Time1=1;
		Switch_Time2=0;
		P0=tab[Data%10];//显示个位
		delay_ms(1);
		Switch_Time2=1;
		Switch_Time1=0;
		P0=tab[Data/10];//显示十位
		delay_ms(1);
}

unsigned char Scan_Key()//获取按键键码
{
	unsigned char KeyNumber=0;
	if(P1_0==0){delay_ms(10);while(P1_0==0);delay_ms(10);KeyNumber=1;}
	if(P1_1==0){delay_ms(10);while(P1_1==0);delay_ms(10);KeyNumber=2;}
	if(P1_2==0){delay_ms(10);while(P1_2==0);delay_ms(10);KeyNumber=3;}
	if(P1_3==0){delay_ms(10);while(P1_3==0);delay_ms(10);KeyNumber=4;}
	if(P1_4==0){delay_ms(10);while(P1_4==0);delay_ms(10);KeyNumber=5;}
	if(P1_5==0){delay_ms(10);while(P1_5==0);delay_ms(10);KeyNumber=6;}
	if(P1_6==0){delay_ms(10);while(P1_6==0);delay_ms(10);KeyNumber=7;}
	if(P1_7==0){delay_ms(10);while(P1_7==0);delay_ms(10);KeyNumber=8;}
	return KeyNumber;
}


void traffic()//红绿灯主要逻辑
{
	
	if(Time_Mode==0)//东西南北转换
	{
		Nixie(EW_Time);
		if(EW_Time>5)
		{
			EW_Red=OFF;//东西红灯灭
			NS_Yellow=OFF;//南北黄灯灭
			NS_Green=OFF;//南北绿灯灭
			
			EW_Green=ON;//东西绿灯亮
			NS_Red=ON;//南北红灯亮
		}else if(Flag_Blink==0&&EW_Time<=5&&EW_Time>0)//闪烁
		{
			EW_Green=OFF;//东西绿灯灭
			EW_Yellow=ON;//东西黄灯亮
		}else
		{
			EW_Green=OFF;//东西绿灯灭
			EW_Yellow=OFF;//东西黄灯灭
		}
	}
	if(Time_Mode==1)//东西南北转换
	{
		Nixie(NS_Time);
		if(NS_Time>5)
		{
			
			NS_Red=OFF;//南北红灯灭
			EW_Yellow=OFF;//东西黄灯灭
			EW_Green=OFF;//东西绿灯灭
			
			EW_Red=ON;//东西红灯亮
			NS_Green=ON;//南北绿灯亮
		}else if(Flag_Blink==0&&NS_Time<=5&&NS_Time>0)//闪烁
		{
			NS_Green=OFF;//南北绿灯灭
			NS_Yellow=ON;//南北黄灯亮
		}
		else
		{
			NS_Green=OFF;//南北绿灯灭
			NS_Yellow=OFF;//南北黄灯灭
		}
	}
}

void Set_Time()
{
	char Key_Num=0,Key_Value=0,mode=1;
	while(1)
	{
		Key_Value=Scan_Key();//获取键值
		if(Key_Value!=0)Key_Num=Key_Value;
		if(Key_Num==1)
		{
			mode++;
			if(mode>3)break;
			Key_Num=0;
		}
		if(mode==1)//按下第二次显示东西通讯时间,可加减设置
		{
			Nixie(EW_SetTime);
			if(Key_Num==2){EW_SetTime++;Key_Num=0;}
			if(Key_Num==3){EW_SetTime--;Key_Num=0;}
		}
		if(mode==2)//按下第二次显示南北通讯时间,可加减设置
		{
			Nixie(NS_SetTime);
			if(Key_Num==2){NS_SetTime++;Key_Num=0;}
			if(Key_Num==3){NS_SetTime--;Key_Num=0;}
		}
		if(mode==3)//按下第三次时显示00,红灯亮,紧急通行
		{
			P2=0xFF;
			Nixie(0);
			NS_Red=ON;
			EW_Red=ON;
		}
		if(Key_Num==4)//确认键,上传主副干道通行时间
		{
			EW_Time=EW_SetTime;
			NS_Time=NS_SetTime;
			break;
		}
			
	}
}
void Yellow_Blink()//黄灯闪烁
{
	char Key_Num=0,Key_Value=0,Mode=1;
	while(1)
	{
		Key_Value=Scan_Key();//获取键值
		if(Key_Value!=0)Mode=Key_Value;
		P2=0xFF;
		Nixie(0);
		if(Flag_Blink)
		{
			EW_Yellow=ON;
			NS_Yellow=ON;		
		}else
		{
			EW_Yellow=OFF;
			NS_Yellow=OFF;	
		}
		
		if(Mode==5){break;}
	}
}

void main()
{
	char Key_Mode=0,Key_Value=0;
	
	P2=0xFF;
	Power=1;
	Timer_Init();//初始化定时器
//	NS_Green=OFF;
  while(1)	
  { 
		Key_Value=Scan_Key();
		if(Key_Value!=0)Key_Mode=Key_Value;
		switch(Key_Mode)
		{
			case 0:traffic();
				break;
			case 1:Set_Time();
						Key_Mode=0;
				break;
			case 5:Yellow_Blink();
							Key_Mode=0;
				break;
			default:
				Key_Mode=0;
		}
		
  }
}

void Timer0() interrupt 1
{
	static unsigned char count=0,count1=0;
	TL0=(65536-50000)%256;//低八位
	TH0=(65536-50000)/256;//高八位
	if(count>=10)
	{
		count=0;
		if(Time_Mode==0)//东西时间减
		{
			EW_Time--;
			if(EW_Time<0){EW_Time=EW_SetTime;Time_Mode=!Time_Mode;}
		}
		if(Time_Mode==1)//南北时间减
		{
			NS_Time--;
			if(NS_Time<0){NS_Time=NS_SetTime;Time_Mode=!Time_Mode;}
		}
		
	}
	if(count1>=5)//闪烁标志位
	{
		count1=0;
		Flag_Blink=!Flag_Blink;
	}
	count++;
	count1++;
}
 
相关推荐
yutian06066 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程9 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉13 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名67713 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式大圣13 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室14 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费14 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_3975623116 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo201716 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
艺术家天选16 小时前
STM32点亮LED灯
stm32·单片机·嵌入式硬件