51单片机的仿真实验——交通灯(十字路口演示)

  • Post author:
  • Post category:其他




学习目标:


1、了解交通灯的基本工作原理;

2、用multisim模拟实现交通灯控制;

3、用Keil C51编程实现上述功能;

4、用Keil与multisim联调




学习内容:

通过AT89C51实现对交通灯(十字路口)的管理。除了日常的计时与三色灯交换外还能够通过按键对相应道路进行控制(可控制东北通信、东南通信、全部禁行、南北时间的加减、东西时间的加减与时间的恢复)。大幅度地提高了产品可靠性并降低了制造成本。




学习产出:

项目工程及仿真资料

链接:https://pan.baidu.com/s/1bwVjGAM5-JaNJOPo1lsOJQ 提取码:bhug



原理图设计:

本实验主要有单片机、8个按键、4组三色灯及电阻、4组二位数码管组成,实现电路如下:

在这里插入图片描述




项目代码:

主函数代码:

#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit P1_0 =P1^0;
sbit P1_1 =P1^1;
sbit P1_2 =P1^2;
sbit P1_3 =P1^3;
sbit sn_red=P0^0;
sbit sn__yellow=P0^1;
sbit sn__green=P0^2; 
sbit ew_red=P0^3;
sbit ew__yellow=P0^4;
sbit ew_green=P0^5;

sbit key_sourth_north=P3^2;
sbit key_earth_west=P3^3;
sbit all_not=P3^4;
sbit key_sn_add=P3^0;
sbit key_sn_sub=P3^1;
sbit key_ew_add=P3^5;
sbit key_ew_sub=P3^6;
sbit key_reset=P3^7;

uchar code s7_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar time=30;
uchar timex=33;
uchar time_flag;
uchar timex_flag;
uchar led_change;
uchar led_change1;
uchar yellow_led_flag;
void delay_ms(uchar z) 
{
    uchar i,j;
	for(i=z;i>0;i--)
	    for(j=110;j>0;j--);
}
void display_time()
{
	
	P1_0=0;P1_1=1;P1_2=1;P1_3=1;
	P2=s7_table[timex/10];
	delay_ms(2);
	P2=0;
	P1_0=1;
   	
	P1_1=0;
	P2=s7_table[timex%10];
	delay_ms(2);
	P2=0;
	P1_1=1;

	P1_2=0;
	P2=s7_table[time/10];
	delay_ms(2);
	P2=0;
	P1_2=1;

	P1_3=0;
	P2=s7_table[time%10];
	delay_ms(2);
	P2=0;
	P1_3=1;
}	   /*
void display_time1()
{
	if(key_sn_add==0||key_sn_sub==1||key_ew_add==1||key_ew_sub==1)
	{
		P1_0=0;P1_1=1;P1_2=1;P1_3=1;
		P2=s7_table[time/10];
		delay_ms(2);
		P2=0;
		P1_0=1;
   	
		P1_1=0;
		P2=s7_table[time%10];
		delay_ms(2);
		P2=0;
		P1_1=1;

		P1_2=0;
		P2=s7_table[timex/10];
		delay_ms(2);
		P2=0;
		P1_2=1;

		P1_3=0;
		P2=s7_table[timex%10];
		delay_ms(2);
		P2=0;
		P1_3=1;
	}
}		   */
void init0_timer()
{
	TMOD=0X01;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	ET0=1;
	EA=1;
	TR0=1;
}
void south_north_allow()
{
	ew_red=0;
	ew_green=1;
	ew__yellow=1;
	sn_red=1;
	sn__green=0;
	sn__yellow=1;
}
void earth_west_allow()
{
	ew_red=1;
	ew_green=0;
	ew__yellow=1;
	sn_red=0;
	sn__green=1;
	sn__yellow=1;
}  



void key_scan()
{	
	if(key_sourth_north==0)
	{
		delay_ms(2);
		if(key_sourth_north==0)
		{
			south_north_allow();
			while(!key_sourth_north)display_time();
			TR0=0;
		}
	}
	if(key_earth_west==0)
	{
		delay_ms(2);
		if(key_earth_west==0)
		{
			earth_west_allow();
			while(!key_earth_west)display_time();	
			TR0=0;
		}
	}
	if(all_not==0)
	{
		delay_ms(2);
		if(all_not==0)
		{
			TR0=0;
			ew_red=0;
			ew_green=1;
			ew__yellow=1;
			sn_red=0;
			sn__green=1;
			sn__yellow=1;
		}
	}
	if(key_sn_add==0)
	{
	    delay_ms(2);
		if(key_sn_add==0)
	  {
		time=time+2;
		while(!key_sn_add)display_time();
	      
	  }
	}
	if(key_sn_sub==0)
	{
		delay_ms(2);
		if(key_sn_sub==0)
	  {
		time=time-2;
		while(!key_sn_sub)display_time();
	      
	  }
	}
	if(key_ew_add==0)
	{
		delay_ms(2);
		if(key_ew_add==0)
	  {
		timex=timex+2;
		while(!key_ew_add)display_time();
	      
	  }
	}
	if(key_ew_sub==0)
	{
		delay_ms(2);
		if(key_ew_sub==0)
	  {
	 	timex=timex-2;
		while(!key_ew_sub)display_time();
	      
	  }
	}
	if(key_reset==0)
	{
		delay_ms(2);
		 TR0=1;

	}
}

void main()
{
    init0_timer();
	ew_red=1;
	ew_green=0;
	ew__yellow=1;
	sn_red=0;
	sn__green=1;
	sn__yellow=1;
	yellow_led_flag=2;
	while(1)
	{
		display_time();
		key_scan();
	}
}
void_int0_isr() interrupt 1
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	time_flag++;
	timex_flag++;
	if(time_flag==20||timex_flag==20)
	{
		time_flag=0;
		timex_flag=0;
		if(time==0)
		{
			time=30;
			if(key_sn_add==0)
			{
				time++;
			}
			if(key_sn_sub==0)
			{
				time--;
			}
			led_change++;
			if(led_change==1)
			{
				sn_red=0;
				sn__green=1;
				ew_red=0;
				ew_green=1;
				ew__yellow=1;
				sn__yellow=1;
				yellow_led_flag=1;
			}
			if(led_change==2)
			{
				led_change=0;
				ew_red=1;
				ew_green=0;
				sn_red=1;
				sn__green=1;
				ew__yellow=1;
				sn__yellow=0;
				yellow_led_flag=2;
			}	  
		}
		else
		{
			time--;
		}
	if(time==8)
		{
			if(yellow_led_flag==2)
			{
				ew_red=1;
				ew_green=1;
				sn_red=0;
				sn__green=1;
				ew__yellow=0;
				sn__yellow=1;
			}  
		}	


		if(timex==0)
		{
			timex=30;
			if(key_ew_add==0)
			{
				timex++;
			}
			if(key_ew_sub==0)
			{
				timex--;
			}
		 	led_change1++;
			if(led_change1==1)
			{	
				sn_red=1;
				sn__green=0;
				ew_red=0;
				ew_green=1;
				ew__yellow=1;
				sn__yellow=1;
				yellow_led_flag=1;	 
			}	
			if(led_change1==2)
			{
				led_change1=0;
				ew_red=1;
				ew_green=0;
				ew__yellow=1;
				sn_red=0;
				sn__green=1;
				sn__yellow=1;
				yellow_led_flag=2;
			}	 
		}
		else
		{
			timex--;
		}
		if(timex==8)
		{
		    if(yellow_led_flag==1)
			{
			    ew_red=0;
				ew_green=1;
				sn_red=1;
				sn__green=1;
				ew__yellow=1;
				sn__yellow=0;
			}
		}
	}
}



实验总结

本实验通过51单片机实现了交通灯的显示与时间调节系统。设置南北初始时间为30秒绿灯,东西初始时间为33秒红灯。当绿灯时间剩下8秒时转为红灯。当红灯时间结束时才变绿(注意:红灯转绿灯时不需要先转黄灯)。若烧录时路径有问题,需双击AT89C51单片机重新选择.OBJ文件的路径进行重新模拟烧录代码。

当时写这个实验的时候还是个新手,对于交通灯的变化是强制将所有灯按指定的颜色进行转化的。可能多了很多不必需要的代码。



最后:

希望本博客能在51单片机上给读者一定的帮助,省下找各种解决方案的时间成本。感谢各位观看,如有不足,欢迎在评论内留言与讨论。如果觉得写得好的,可以给我点赞+收藏+关注哦,再次感谢各位!

在这里插入图片描述



版权声明:本文为weixin_47390133原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。