51单片机 时间控制的不同时段交通灯控制设计(简单版)

这个交通灯的设计时简单版,只有一个路口(不是十字路口)的那种(想要实现十字路口可以对代码稍加修改)

  1. 使用的开发软件:Keil uVision5
  2. 单片机类型为:C51
  3. 语言类型:C语言
    在这里说一下实现的功能
    STC12C5A60S2(引脚排序及基本功能同AT89S51)作为主控芯片,设计格局时间选择不同红绿灯交替时间的交通灯控制电路。一是交通灯的正常指示设计;二是扩展DS12C887等相应的外围电路,利用LCD显示时间;三是设计2个交通灯交替间隔,根据时间不同自动选择,可以通过按键来选择3中不同的功能。
    先在这里附上几张实现的图片
    白天模式
    夜晚模式
    自动模式
    LED灯的图片
    在这里贴出代码
#include "reg51.h" 
#include"absacc.h"  
typedef unsigned char BYTE; 
typedef unsigned int  WORD; 
unsigned char Key_Value;  //读出的键值 
/*  液晶 1602 口地址  */ 
#define  wr_com  XBYTE[0xC000]     //写命令  
#define  wr_data  XBYTE[0xC100]    //写数据  
#define  rd_com  XBYTE[0xC200]     //读命令  
#define  rd_data  XBYTE[0xC300]    //读数据  
/*  DS12887 口地址  */  
#define  DS_A     XBYTE[0x100A]     //寄存器A  
#define  DS_B     XBYTE[0x100B]     //寄存器B  
#define  DS_C     XBYTE[0x100C]     //寄存器C  
#define  Years    XBYTE[0x1009]     //年  
#define  Month    XBYTE[0x1008]     //月  
#define  Day      XBYTE[0x1007]     //日  
#define  Week     XBYTE[0x1006]     //星期  
#define  Hour     XBYTE[0x1004]     //时  
#define  Minute   XBYTE[0x1002]     //分  
#define  Second   XBYTE[0x1000]     //秒  
BYTE ah,al,gao,di;
WORD d,e,a,DisplayTime,SD_DisplayTime,DModeStep,SD_DisplayTime1,WorkMode,SD_DisplayTime2,SD_DisplayTime3,ASD_DisplayTime,ASD_DisplayTime1,ASD_DisplayTime2,ASD_DisplayTime3;
sbit P22 = P2^2;//红灯
sbit P23 = P2^3;//黄灯
sbit P24 = P2^4;//绿灯
void IintUart(); 
void InitADC(); 
void SendData(BYTE dat); 
void GetADCResult(BYTE ch); 
void Delay(WORD n);
void Delay2(WORD n);
void ShowResult(BYTE ch); 
void lcd_init(void);                          // lcd初始化  
void write_cmd(BYTE cmd);                     // lcd写命令    
void write_data(BYTE dat) ;                   // 写数据  
void set_display_place(BYTE line,column); 
void write_string_lcd(BYTE line,column,unsigned char *string); 
void write_data_lcd(BYTE line,column,dat); 
void red_led(WORD c);
void green_led(WORD c);
void yellow_led(WORD c);
void nred_led(WORD c);
void ngreen_led(WORD c);
void nyellow_led(WORD c);
void Delay3(int Time_ms);
unsigned char Keyscan();
void bt_bt();
void Daytime_mode();
void Night_mode();
void automatic();
void LcdDisplay1(int a);
//void Timer0Interrupt(void) interrupt 1
void InitTimer0(void);
void timer_red();
void timer_green();
void DMode();
void bt_bt1();
void AMode();
void ADMode();
void ANMode();
/************************************************************* 
Function name:       write_cmd  
Descriptions:        向lcd 输入指令  
**************************************************************/ 
void write_cmd(BYTE cmd) 
{     
BYTE dl;  
do {   dl=rd_com;   
} while((dl&0x80)!=0); //判忙      
wr_com= cmd;     
Delay(1); } 
 
/********************************************************** 
Function name:       write_data  
Descriptions:        写入数据  
*********************************************************/ 
void write_data(BYTE dat)  
{  
BYTE dl;  
do {   dl=rd_com;   } while((dl&0x80)!=0); //判忙      
wr_data= dat;       
Delay(1); }   
 /********************************************************** 
Function name:       read_data  
Descriptions:        读出数据  
*********************************************************/ 
void read_data(BYTE dat)  
{  
BYTE dl;  
do {   dl=rd_com;   } while((dl&0x80)!=0); //判忙      
rd_data= dat;       
Delay(1); } 
/************************************************************ 
Function name:       write_string  
Descriptions:        写入字符串  
*************************************************************/ 
void write_string(BYTE *s)              
{     while(*s != '\0')            //'\0'为字符串结束标志      
{         write_data(*s);         
s++;     } } 
/*********************************************************** 
Function name:       set_display_place 
Descriptions:        设置字符的显示位置  
***********************************************************/ 
void set_display_place(BYTE line,column) 
{     BYTE address;     
if(line == 1)     
{         
address = 0x80 + column;     
}     
else if(line == 2)     
{         
address = 0xc0 + column;     
}    
 write_cmd(address);        
  } 
/************************************************************** 
Function name:       将字符串写到指定的位置  
Descriptions:        将字符串显示在 lcd 的特定位置  
***************************************************************/ 
void write_string_lcd(BYTE line,column,unsigned char *string)
 {     
set_display_place(line,column);     
write_string(string);
Delay(1); 
} 
/***************************************************************
 Function name:       将字符写到指定的位置  
Descriptions:        将字符串显示在 lcd 的特定位置  
****************************************************************/ 
void write_data_lcd(BYTE line,column,dat) 
{    
 set_display_place(line,column);     
write_data(dat);     
Delay(1); 
} 
/*************************************************** 
液晶模块初始化
****************************** *********************/ 
void lcd_init(void)       
{ 
 
  write_cmd(0x38);   
  write_cmd(0x38); 
  write_cmd(0x06); 
  write_cmd(0x0c); 
  write_cmd(0x01);
} 
 /*************************************************** 
DS12887 初始化程序
****************************************************/ 
void DS_init()
{     
DS_A=0x20;  
DS_B=0x12; 
}  
 
void write_time()  {    
DS_A=0x2f;          //寄存器A  
DS_B|=0x80;     
Years=0x19;         //年     
Month=0x12;         //月     
Day=0x26;           //日     
Week=0x02;          //星期     
Hour=0x14;          //时     
Minute=0x04;        //分     
Second=0x00;        //秒     
DS_B &=0x7f;        //寄存器A  
} 
 /***************************************************************  
显示时间  
***************************** ************************************/ 
void crt_time(BYTE line)  
{  
BYTE dhi,dli;  
set_display_place(1,0);  
dli=Years;  
dhi=dli & 0xf0;     
dhi>>=4;  
dhi+=0x30;  
dli &=0x0f;  
dli +=0x30;  
write_data(dhi); 
write_data(dli);  
dli=0x2d;  
write_data(dli); 
dli=Month;  
dhi=dli & 0xf0;     
dhi>>=4;  
dhi+=0x30;  
dli &=0x0f;  
dli +=0x30;  
write_data(dhi); 
write_data(dli);  
dli=0x2d;  
write_data(dli);  
dli=Day;  
dhi=dli & 0xf0;     
dhi>>=4;  
dhi+=0x30;  
dli &=0x0f;  
dli +=0x30;  
write_data(dhi);  
write_data(dli);    
dli=0x20;  
write_data(dli);  
write_data(dli);  
write_data(dli);    
set_display_place(2,0);
dli=Hour;  //0x15
dhi=dli & 0xf0;    
 dhi>>=4;  
dhi+=0x30;  
dli &=0x0f;  
dli +=0x30;  
write_data(dhi);  
write_data(dli);
gao=dhi;
di=dli;
dli=0x3a; //- 
write_data(dli);  
dli=Minute;  
dhi=dli & 0xf0;     
dhi>>=4;  
dhi+=0x30;  
dli &=0x0f;  
dli +=0x30;  
write_data(dhi);  
write_data(dli);  
dli=0x3a;  
write_data(dli);  
dli=Second;  
dhi=dli & 0xf0;     
dhi>>=4;  
dhi+=0x30;  
dli &=0x0f; 
dli +=0x30; 
write_data(dhi); 
write_data(dli); }  
void Delay(WORD n)
 {     
WORD x;  while(n--) 
 {     
 x=500;   
while(x--);
  } } 
 
void Delay2(WORD n) 
{     
WORD x;  
while(n--) 
{     
 x=5000;   
while(x--);
  } } 
void Delay3(int Time_ms)//延时 
{
  int i;  
unsigned char j;  
for(i=0;i<Time_ms;i++)    
{      
for(j=0;j<=150;j++)         
{     
}    
} 
} 	
void InitTimer0(void)		   //初始化定时器0
{
    TMOD = 0x01;			 //模式1
    TH0 = 0x3C;				 //定时器装载值
    TL0 = 0xB0;
    EA = 1;					 //使能总中断
    ET0 = 1;				 //使能定时器0中断
    TR0 = 1;				 //启动定时器0
}
void Timer0Interrupt(void) interrupt 1		 //定时器0中断处理函数
{
	static unsigned char TimeOutNum = 0;
	int i=0;
	d=DisplayTime;
    TH0 = 0x3C;								//重新装载值
    TL0 = 0xB0;
	TimeOutNum++;						//中断次数++, 即50ms的次数
	if(TimeOutNum>=20)            	    //达到50ms * 20 = 1s条件
	{
		TimeOutNum = 0;					 //中断次数清0
		SD_DisplayTime--;     //白天的红灯及绿灯15S
		SD_DisplayTime1--;    //夜晚的黄灯
		SD_DisplayTime2--;    //白天的黄灯
		SD_DisplayTime3--;    //夜晚的红灯及绿灯10S
	  ASD_DisplayTime--;     //白天的红灯及绿灯15S
		ASD_DisplayTime1--;    //夜晚的黄灯
		ASD_DisplayTime2--;    //白天的黄灯
		ASD_DisplayTime3--;    //夜晚的红灯及绿灯10S
	}
}
void LcdDisplay1(int a) 	 //lcd显示
{

	 set_display_place(2,14);		 
	 write_data('0'+a/10);
	 set_display_place(2,15);	  
	 write_data('0'+a%10);	

}
unsigned char Keyscan()         //行列式键盘扫描 
	{  unsigned char i,j, temp, Buffer[4] = {0xef, 0xdf, 0xbf, 0x7f};   //让矩阵键 盘的每行分别为低电平  
	for(j=0; j<4; j++)  
	{   
		P1 = Buffer[j];   
		temp = 0x01;                                                                     
		for(i=0; i<4; i++)   
		{    
			if(!(P1 & temp))   //判断 P1 口高 4 位某一行为低电平    
				{     
					return (j+i*4);  //返回键码    
					}    
	temp <<= 1;   
	}  
	}  
	return 0; 
	} 
void bt_bt1()
{
			 P1 = 0xf0;       
		 if(P1 != 0xf0)   //判断有无按键按下   
			 {    
				 Delay3(15);  //按键消抖    
				 if(P1 != 0xf0)     
	{     Key_Value = Keyscan();      
  
		if(Key_Value==0)
    {
			SD_DisplayTime=15;     //白天的红灯及绿灯15S
			SD_DisplayTime2=8;    //白天的黄灯8S

			WorkMode=1;
		}	
    else if(Key_Value==1)			
		{

		SD_DisplayTime1=5;    //夜晚的黄灯

		SD_DisplayTime3=10;    //夜晚的红灯及绿灯10S

			WorkMode=2;
		}
		else if(Key_Value==2)			
		{
			ASD_DisplayTime=15;     //白天的红灯及绿灯15S
			ASD_DisplayTime2=8;    //白天的黄灯8S
			ASD_DisplayTime1=5;    //夜晚的黄灯
		  ASD_DisplayTime3=10;    //夜晚的红灯及绿灯10S
			WorkMode=3;
		}

	}    
	}
}	
void DMode()				//白天工作模式
{
  
	 write_string_lcd(1,9,"Dmode");
	switch(DModeStep)			  
	{
		case 1:		
			write_string_lcd(2,9,"Red :");
		  P22=0;
		 LcdDisplay1(SD_DisplayTime);
			if(SD_DisplayTime ==0 )	   //如果通行时间走完,即等于0
			{
				P22=1;
				DModeStep = 2;
				SD_DisplayTime2=8;  
        
			}	
			break;
		case 2:		
			write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(SD_DisplayTime2);
			if(SD_DisplayTime2 == 0)		//如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 3;	  
				SD_DisplayTime=15; 
			}	
			break;
		case 3:		   
			write_string_lcd(2,9,"Gre :");
		  P24=0;
		 LcdDisplay1(SD_DisplayTime);
			if(SD_DisplayTime == 0)			//如果通行时间走完,即等于0
			{
				P24=1;
				DModeStep = 4;	  
				SD_DisplayTime2=8;  
			}	
			break;
		case 4:			
      write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(SD_DisplayTime2);
			if(SD_DisplayTime2 == 0)			   //如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 1;	 
				SD_DisplayTime=15;	 
			break;
	}
}
}
void NMode()				//夜晚工作模式
{
   
	write_string_lcd(1,9,"Nmode");
	switch(DModeStep)			  
	{
		case 1:		
			write_string_lcd(2,9,"Red :");
		  P22=0;
		 LcdDisplay1(SD_DisplayTime3);
			if(SD_DisplayTime3 ==0 )	   //如果通行时间走完,即等于0
			{
				P22=1;
				DModeStep = 2;
				SD_DisplayTime1=5;
        
			}	
			break;
		case 2:		
			write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(SD_DisplayTime1);
			if(SD_DisplayTime1 == 0)		//如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 3;	  
				SD_DisplayTime3=10; 
			}	
			break;
		case 3:		   
			write_string_lcd(2,9,"Gre :");
		  P24=0;
		 LcdDisplay1(SD_DisplayTime3);
			if(SD_DisplayTime3 == 0)			//如果通行时间走完,即等于0
			{
				P24=1;
				DModeStep = 4;	  
				SD_DisplayTime1=5;   
			}	
			break;
		case 4:			
      write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(SD_DisplayTime1);
			if(SD_DisplayTime1 == 0)			   //如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 1;	 
				SD_DisplayTime3=10; 
			break;
	}
}
}

void ADMode()				//自动白天工作模式
{
  
	 
	switch(DModeStep)			  
	{
		case 1:		
			write_string_lcd(2,9,"Red :");
		  P22=0;
		 LcdDisplay1(ASD_DisplayTime);
			if(ASD_DisplayTime ==0 )	   //如果通行时间走完,即等于0
			{
				P22=1;
				DModeStep = 2;
				ASD_DisplayTime2=8;  
        
			}	
			break;
		case 2:		
			write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(ASD_DisplayTime2);
			if(ASD_DisplayTime2 == 0)		//如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 3;	  
				ASD_DisplayTime=15; 
			}	
			break;
		case 3:		   
			write_string_lcd(2,9,"Gre :");
		  P24=0;
		 LcdDisplay1(ASD_DisplayTime);
			if(ASD_DisplayTime == 0)			//如果通行时间走完,即等于0
			{
				P24=1;
				DModeStep = 4;	  
				ASD_DisplayTime2=8;  
			}	
			break;
		case 4:			
      write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(ASD_DisplayTime2);
			if(ASD_DisplayTime2 == 0)			   //如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 1;	 
				ASD_DisplayTime=15;	 
			break;
	}
}
}

void ANMode()				//自动夜晚工作模式
{
   
	
	switch(DModeStep)			  
	{
		case 1:		
			write_string_lcd(2,9,"Red :");
		  P22=0;
		  LcdDisplay1(ASD_DisplayTime3);
			if(ASD_DisplayTime3 ==0 )	   //如果通行时间走完,即等于0
			{
				P22=1;
				DModeStep = 2;
				ASD_DisplayTime1=5;
        
			}	
			break;
		case 2:		
			write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(ASD_DisplayTime1);
			if(ASD_DisplayTime1 == 0)		//如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 3;	  
				ASD_DisplayTime3=10; 
			}	
			break;
		case 3:		   
			write_string_lcd(2,9,"Gre :");
		  P24=0;
			 LcdDisplay1(ASD_DisplayTime3);
		if(ASD_DisplayTime3 == 0)			//如果通行时间走完,即等于0
			{
				P24=1;
				DModeStep = 4;	  
				ASD_DisplayTime1=5;   
			}	
			break;
		case 4:			
      write_string_lcd(2,9,"Yel :");
		  P23=0;
		  Delay(50);
		  P23=1;
		  Delay(50);
		 LcdDisplay1(ASD_DisplayTime1);
			if(ASD_DisplayTime1 == 0)			   //如果通行时间走完,即等于0
			{
				P23=1;
				DModeStep = 1;	 
				ASD_DisplayTime3=10; 
			break;
	}
}
}

void AMode()				//自动工作模式
{
	write_string_lcd(1,9,"Amode");
  if((gao=='0'&&di=='1')||(gao=='0'&&di=='2')||(gao=='0'&&di=='3')||(gao=='0'&&di=='4')||(gao=='0'&&di=='5')||(gao=='0'&&di=='0'))
{
ANmode();
}
else
{
 ADmode();
}
}

void if_workmode()
{
switch(WorkMode)								 //工作模式判断
		{
			case 1:	  //白天模式
				DMode();
				break;
			
			case 2:	//夜间模式
				NMode();
				break;
			
			case 3:	 //自动模式
				AMode();
				break;
		}
}

void main() 
{ 
int a=0;
SP=0x60;    
SD_DisplayTime = 15;
SD_DisplayTime1=5;
SD_DisplayTime2=8;
SD_DisplayTime3=10;
ASD_DisplayTime=15;    //白天的红灯及绿灯15S
ASD_DisplayTime2=8;    //白天的黄灯8S
ASD_DisplayTime1=5;    //夜晚的黄灯5S
ASD_DisplayTime3=10;   //夜晚的红灯及绿灯10S
DModeStep = 1;
WorkMode = 3;
InitTimer0();
lcd_init();    
DS_init();    
write_time();//DS12C887 时间设置
while(1)          
{ 
bt_bt1();	
if_workmode();	
if ((DS_C & 0x10) != 0)//显示时间      
{        
crt_time(1);      
}     
Delay2(1);
}
}

代码直接可以使用,如有不懂之处可以评论,我看到之后会回复哦

发布了4 篇原创文章 · 获赞 1 · 访问量 172

猜你喜欢

转载自blog.csdn.net/qq_42455308/article/details/104551534