@点赞、关注、评论获取更多经典案例 ;&评论留言获取源文件定制更多功能

前言

本课题基于STC89C51/52单片机实现十字路口交通灯的控制原理,四个方向均由数码管显示时间,并设有9个按键,分别为:复位按键、夜间模式、紧急模式、东西通行、南北通行、设置时间模式、时间加、时间减、确认调整。

一、功能说明

1、复位按键:

恢复系统初始化

2、夜间模式:

所有数码管显示“--”,黄灯闪烁,其他灯熄灭

3、紧急模式:

所有数码管显示“8.”全亮,红灯常亮

4、东西通行:

所有数码管熄灭,东西方向绿灯常亮,南北方向红灯常亮

5、南北通行:

所有数码管熄灭,南北方向绿灯常亮,东西方向红灯常亮

6、切换、设置时间:

1)非正常模式下,按下恢复到正常工作模式

2)正常模式下(自动运行模式),按下切换到东西方向时间设置,南北方向数码管熄灭,西向显示“--”,东西显示当前时间;再次按下切换到南北方向时间设置,东西方向数码管熄灭,北向显示“--”,南向显示当前时间; 后续按下往复切换设置方向。

3)时间+/-:设置时间模式下时间+1或-1、

4)确认:确认设置完毕,返回正常工作模式

二、系统原理图

1.器件清单

1)AT89C51/52单片机 (仿真忽略时钟系统) 1片

2)10k排阻  1只

3)电阻   若干

4)微动开关  9只

5)10uf铝电解电容  1只

6)两位共阴数码管   4只

7)红黄绿Led灯  各4只

2.绘制原理图

三、程序编写

main.c 源码

#include "STC89.H"
#include "Delay.h"
#include "Seg.h"
#include "Key.h"
#include "Led.h"
#include "Timer.h"

#define uint8_t  unsigned char
#define uint16_t  unsigned int

uint16_t count,count_Y; //1000 times counter
bit flag_Y; //1 黄灯闪烁
bit flag_R; //1 红灯全亮
bit flag_SN_GO;
bit flag_EW_GO;


uint8_t SN_Go_Time=6; //南北通行时间
uint8_t EW_Go_Time=7; //南北通行时间

void Run_State(void);

void main(void)
{
  Timer0_Init();
  flag_SN_GO=1;
  flag_EW_GO=0;	
  count = 0;    //initial counte
  while(1)
  {
	Run_State();
	Key_Return();//按键扫描  	  
  }
}
void Run_State(void)
{
	  while(Run==0) //调时模式
	  {Set_SN_Tim();}	
	  if(Run==1)//运行模式
	  {
		Night_Mode();//夜间模式
		SOS_Mode();//SOS模式
		GO_Mode();//GO模式	  
	  }
	  else if(Run==2) //东西
	  {
		P0=0x00;
		SN_G=1;EW_G=0;
		SN_R=0;EW_R=1;
	  }
	  else if(Run==3) //南北
	  {
		P0=0x00;
		SN_G=0;EW_G=1;
		SN_R=1;EW_R=0;
	  }
}
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
    TL0 = T1MS;        //reload timer0 low byte
    TH0 = T1MS >> 8;   //reload timer0 high byte
	count++;
	count_Y++;
	if(count_Y==500)
	{LED_Y();count_Y=0;}//夜间模式
    if (count == 1000)               //1ms * 1000 -> 1s
    {
		if(GO==0)
		{SN_Go_Time--;}
		if(GO==1)
		{EW_Go_Time--;}
		count = 0;
		if(SN_Go_Time==0)
		{
			GO=1;
			SN_Go_Time=Set_SN_time;
		}
		
		if(EW_Go_Time==0)
		{
			GO=0;
			EW_Go_Time=Set_EW_time;
		}	               
    }
}

数码管驱动Seg.c

#include "Seg.h"
#include "Delay.h"
#include "Led.h"
#include "Key.h"

uint8_t code Dis[]=  {0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F,0X40,0XFF};
                     /*0,   1,   2,   3,   4,   5,   6,   7,   8,   9,   -,   ALL*/
uint8_t code Add[]={0X00,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
                  // ALL 
extern bit flag_Y;
extern bit flag_R;
extern bit flag_SN_GO;
extern bit flag_EW_GO;
extern uint8_t SN_Go_Time,EW_Go_Time;
extern uint16_t count;
uint8_t GO=0;
void DIS_Play(uint8_t addr,uint8_t dat)
{
	P0=0x00;  
	P2=Add[addr]; 
	P0=Dis[dat];		
}
//夜晚模式 全部黄灯 - 闪烁
void Night_Mode(void)
{
    if(flag_Y==1)
	DIS_Play(0,10); //all seg show -
}
//SOS模式 全部红灯 亮
void SOS_Mode(void)
{
    if(flag_R==1)
	{
		DIS_Play(0,11); //all seg show -
		LED_R();
	}
}
//GO模式 
void GO_Mode(void)
{
	if(GO==1)
	{DIS_EW_GO_Mode();}//南北通行   	  
	if(GO==0)
	 {DIS_SN_GO_Mode();}//南北通行 
}

//SN模式
void DIS_SN_GO_Mode(void)
{
	if(SN_Go_Time>5)
	{
	   DIS_Play(1,(SN_Go_Time-5)/10); //北
	   DIS_Play(2,(SN_Go_Time-5)%10);
	
	   DIS_Play(5,(SN_Go_Time-5)/10); //南
	   DIS_Play(6,(SN_Go_Time-5)%10);	
	}
	else
	{
	   DIS_Play(1,SN_Go_Time/10); //北
	   DIS_Play(2,SN_Go_Time%10);
	
	   DIS_Play(5,SN_Go_Time/10); //南
	   DIS_Play(6,SN_Go_Time%10);	
	}		
	DIS_Play(3,SN_Go_Time/10); //东
	DIS_Play(4,SN_Go_Time%10);
	DIS_Play(7,SN_Go_Time/10); //西
	DIS_Play(8,SN_Go_Time%10);	
	
	if(SN_Go_Time<=5)//通行时间即将结束
	{	
		SN_G=1;EW_G=1;
		SN_R=1;EW_R=0;
		if(count==500)
		{SN_Y=0;}
		if(count==1000)
		{SN_Y=1;}	
	}
	else
	{SN_G=0;EW_G=1;EW_R=0;SN_R=1;}	
	
}
//EW模式
void DIS_EW_GO_Mode(void)
{
	if(EW_Go_Time>5)
	{
	   DIS_Play(3,(EW_Go_Time-5)/10); //
	   DIS_Play(4,(EW_Go_Time-5)%10);
	
	   DIS_Play(7,(EW_Go_Time-5)/10); //
	   DIS_Play(8,(EW_Go_Time-5)%10);	
	}
	else
	{
	   DIS_Play(3,EW_Go_Time/10); //
	   DIS_Play(4,EW_Go_Time%10);
	
	   DIS_Play(7,EW_Go_Time/10); //
	   DIS_Play(8,EW_Go_Time%10);	
	}
	
	DIS_Play(1,EW_Go_Time/10); //
	DIS_Play(2,EW_Go_Time%10);
	DIS_Play(5,EW_Go_Time/10); //
	DIS_Play(6,EW_Go_Time%10);	
	
	if(EW_Go_Time<=5)//通行时间即将结束
	{	
		EW_G=1;SN_G=1;
		EW_R=1;SN_R=0;
		if(count==500)
		{EW_Y=0;}
		if(count==1000)
		{EW_Y=1;}	
	}
	else
	{EW_G=0;SN_G=1;SN_R=0;EW_R=1;}
}

void Set_SN_Tim(void)
{
	Set_Time();
	if(Key_ch==0) //NS
	{
		DIS_Play(1,10); //北
		DIS_Play(2,10);
		
		DIS_Play(5,Set_SN_time/10); //北
		DIS_Play(6,Set_SN_time%10);	
	}
	if(Key_ch==1) //EW
	{
		DIS_Play(7,10); //
		DIS_Play(8,10);
		
		DIS_Play(3,Set_EW_time/10); //
		DIS_Play(4,Set_EW_time%10);	
	}
}

按键 Key.c

#include "Key.h"
#include "Delay.h"
#include "Led.h"
#include "Timer.h"

extern bit flag_Y;
extern bit flag_R;
extern uint8_t GO;
extern uint8_t SN_Go_Time,EW_Go_Time;
//extern flag_EW_GO,flag_SN_GO;


bit Key_ch; //切换位 0=SN 1=EW
uint8_t Run=1; //运行状态
uint8_t Set_SN_time=25;
uint8_t Set_EW_time=20;
/******************************************************************************************
函数名:key
功能:  独立键盘函数
参数:  无
返回值:unsigned char
******************************************************************************************/
uint8_t key()//独立键盘按键函数
{
	static unsigned char temp=0;
	
	if(key3==0||key4==0||key5==0||key6==0)
	{
		Delay10ms();
		if(key3==0||key4==0||key5==0||key6==0)
		{
//			if(key1==0)
//				temp=1;
//			else if(key2==0)
//				temp=2;
			if(key3==0)
				temp=3;
			else if(key4==0)
				temp=4;
			else if(key5==0)
				temp=5;
			else if(key6==0)
				temp=6;
//			else if(key7==0)
//				temp=7;							
//			else if(key8==0)
//				temp=8;	
		}while(key3==0||key4==0||key5==0||key6==0);
	}
	else
		temp=10;
	return temp;//返回中间值
}
void Key_Return()
{
	switch(key())
	  {
		  case 0:break;
///*时++*/  case 1:{}break;
///*时--*/  case 2:{}break;  
/*夜间*/  case 3:{flag_Y=1;flag_R=0;GO=3;SN_R=1;SN_G=1;EW_R=1;EW_G=1;Run=1;}break;
/*紧急*/  case 4:{flag_R=1;flag_Y=0;GO=3;Run=1;}break;
 /*东西*/ case 5:{GO=1;flag_R=0;flag_Y=0;EW_Go_Time=Set_EW_time;Run=2;}break;
 /*南北*/ case 6:{GO=0;flag_R=0;flag_Y=0;SN_Go_Time=Set_SN_time;Run=3;}break;
// /*切换*/ case 7:{GO=3;Run=0;}break;
// /*确认*/ case 8:{Run=1;SN_Go_Time=Set_SN_time;EW_Go_Time=Set_EW_time;}break;
		  default:break;
	  }
	  
	if(key7==0) //切换
	{
		Delay10ms();
		if(key7==0&&Run==1)
		{
			ET0 = 0;
			GO=3;Run=0;
			Key_ch=~Key_ch;
		}
		if(key7==0&&(Run==2||Run==3))
		{
			Run=1;
			EW_Go_Time=Set_EW_time;
			SN_Go_Time=Set_SN_time;
		}
		while(key7==0);
	}	
}
void Set_Time(void)
{	
	if(key1==0) //Time++
	{
		Delay10ms();
		if(key1==0&&Key_ch==0)//Set_SN_time
		{
			Set_SN_time++;
			if(Set_SN_time ==100)
			{Set_SN_time = 0;}
		}
		if(key1==0&&Key_ch==1)//Set_EW_time ++
		{
			Set_EW_time++;
			if(Set_EW_time ==100)
			{Set_EW_time = 0;}
		}	
		while(!key1);
	}
	
	if(key2==0) //Time--
	{
		Delay10ms();
		if(key2==0&&Key_ch==0)//Set_SN_time
		{
			Set_SN_time--;
			if(Set_SN_time ==0)
			{Set_SN_time = 99;}
		}
		if(key2==0&&Key_ch==1)//Set_EW_time ++
		{
			Set_EW_time--;
			if(Set_EW_time ==0)
			{Set_EW_time =99;}
		}	
		while(!key2);
	}

	if(key7==0) //切换
	{
		Delay10ms();
		if(key7==0)
		{
			ET0 = 0;
			GO=3;Run=0;
			Key_ch=~Key_ch;
		}
		while(key7==0);
	}	
	if(key8==0) //确认
	{
		Delay10ms();
		if(key8==0)
		{
			SN_Go_Time=Set_SN_time;
			EW_Go_Time=Set_EW_time;
			Run=1;ET0 = 1;GO=1;
			
		}
		while(!key8);
	}	
}

Led驱动 Led.c

#include "Led.h"
#include "Delay.h"

extern bit flag_Y;
extern bit flag_R; 
extern bit flag_SN_GO;
extern bit flag_EW_GO;
extern uint8_t SN_Go_Time,EW_Go_Time;
void LED_Y()
{
    if(flag_Y==1)
	{
		SN_Y = !SN_Y;
		EW_Y = !EW_Y;
	}
	else
	{
		SN_Y = 1;
		EW_Y = 1;
	}
}
void LED_R()
{
    if(flag_R==1)
	{
		SN_R = 0;
		EW_R = 0;
	}
	else
	{
		SN_R = 1;
		EW_R = 1;	
	}
}

定时器 Time.c

#include "Timer.h"

/* define constants */

//-----------------------------------------------
void Timer0_Init(void)		//1毫秒@12.000MHz
{
    TMOD = 0x01;                    //set timer0 as mode1 (16-bit)
    TL0 = T1MS;                     //initial timer0 low byte
    TH0 = T1MS >> 8;                //initial timer0 high byte
    TR0 = 1;                        //timer0 start running
    ET0 = 1;                        //enable timer0 interrupt
    EA = 1;                         //open global interrupt switch
}

四、仿真结果(展示部分)

1、夜间模式

2、紧急模式

3、南北通行

4、设置模式

五、实物原理图绘制

1、原理图

2、PCB

3、3D模型

总结:

评论留言获取源文件定制更多功能,关注后续更多实用案例。

以上内容除原理图未经实物验证,其余均已验证,如果对你有帮助请不要吝啬你的点赞、关注、评论。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐