B003 - 基于51单片机的蓝牙交通灯车流量控制系统

摘要

十字路口车辆穿梭,行人熙攘,车行车道,人行人道,有条不紊。那么靠什么来实现这井然秩序呢?靠的就是交通信号灯的自动指挥系统。交通信号灯控制方式很多。本系统采用STC89C52单片机以及单片机最小系统和74HC245电路以及外围的按键和数码管显示等部件,设计一个基于单片机的交通灯设计。设计通过两位一体共阴极数码管显示,并能通过按键对定时进行设置。本系统配置了蓝牙模块用于和手机连接,通过手机可控制交通灯的时间;系统处于自动时可通过光电二极管检测车流量,根据车流量智能化调整交通灯时长。本系统实用性强、操作简单、扩展功能强。

效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完成任务列表

在这里插入图片描述

元器件列表

  1. 9*15万用板
  2. STC89C52RC单片机
  3. 40脚 IC座
  4. 11.0592M晶振
  5. 30pf瓷片电容*2
  6. 10k电阻
  7. 103排阻
  8. 102排阻
  9. 10uf电容
  10. 0.36寸两位一体共阴数码管*4
  11. 发光二极管 红 绿 黄 各*4
  12. 20脚IC座
  13. 74hc245
  14. DC电源插口
  15. 按键*9
  16. 自锁开关
  17. 导线若干*2
  18. 焊锡若干
  19. USB电源线(DC接头+电池盒)
  20. 红外传感器*2
  21. 蓝牙模块

源程序

/*******************************************************************************

* 文件名称:基于51单片机的蓝牙交通灯车流量控制系统

* 实验目的:1.

* 2.

* 程序说明:完整程序Q:2772272579;@: itworkstation@hotmail.com

* 日期版本:主要逻辑为下,可定制。2022年8月1日。

*******************************************************************************/
#include "config.h"


uchar data buf[4];					//秒显示的变量
uchar data sec_dx=30;  			//东西数默认
uchar data sec_nb=30;			//南北默认值
uchar data set_timedx=30;		//设置东西方向的时间
uchar data set_timenb=30;		//设置南北方向的时间
uint dx_liuliang=0,nb_liuliang=0;	  //流量监测
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=P1^6;		//紧急
sbit  k6=P1^5;		//夜间模式

sbit nb_jiance=P1^4;
sbit dx_jiance=P1^7;


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;		//东西绿灯标志
		
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);			//延时子程序
uchar key();					//按键扫描子程序
void display();				//显示子程序
void logo();   				//开机LOGO

void Key_Set(uchar keycode);
bit flag_send=0;
uchar senddx_liuliang=0,sendnb_liuliang=0,sendtimenb=0,sendtimedx=0;
//主程序
void main()
{
	uchar key_value=0,Blooth_code=0;
	int wait_time=0;
	UartInit();
	TMOD=0X11;	   				//定时器设置
	TL0 = 0x00;		//设置定时初值	//50毫秒@11.0592MHz
	TH0 = 0x4C;		//设置定时初值
	TL1 = 0x00;		//设置定时初值	 //50毫秒@11.0592MHz
	TH1 = 0x4C;		//设置定时初值
	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秒
	sendtimenb=30,sendtimedx=30;
	while(1)					  //主循环
	{	 
		key_value=key(); 					//调用按键扫描程序
		if (key_value!=0)
		{		
			 Key_Set(key_value);
//			 printf("key:%bu",key_value);
		}
		display(); 				//调用显示程序
		if(flag_send)			 //uchar senddx_liuliang=0,sendnb_liuliang=0,sendtimenb=0,sendtimedx=0;
		{
		   flag_send=0;
//		   printf("Traffic volume:EW:%bu,NS:%bu;\r\n",senddx_liuliang,sendnb_liuliang);
//
//		   printf("Traffic time:EW:%buS,NS:%buS;\r\n",sendtimedx,sendtimenb);
			
		   printf("T-V:EW:%bu,NS:%bu;T-T:EW:%buS,NS:%buS;\r\n",senddx_liuliang,sendnb_liuliang,sendtimedx,sendtimenb);
		}
		if(Flag_BloothReceive)	   //接收到指令
		{			
			wait_time=10;		  //500mS  100*4
			do
		 	{ 
				display();				 //调用显示,用于延时
			}while(wait_time--);			 //等待 500ms
//			Flag_BloothReceive=0;
//			printf("rec:%bu",1);
		    Blooth_code=Check_Commend();
			if (Blooth_code!=0)
			{		
				 Key_Set(Blooth_code);
			}
		}
		if(nb_jiance==0)
		{
			display();       				//调用显示,用于延时消抖
			if(nb_jiance==0)
			{
				nb_liuliang++;
			}
			do
		 	{ 
				display();				 //调用显示,用于延时
			}
			while(nb_jiance!=1);			 //等待按键释放
		}
		if(dx_jiance==0)
		{
			display();       				//调用显示,用于延时消抖
			if(dx_jiance==0)
			{
				dx_liuliang++;
			}
			do
		 	{ 
				display();				 //调用显示,用于延时
			}
			while(dx_jiance!=1);			 //等待按键释放
		}
	}	
}
void Key_Set(uchar keycode)
{
	switch (keycode)
	{
	   case 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;
	   		break;
		case 2:	
			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;
	   		break;
		case 3:	
			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; 
			}
	   		break;
		case 4:	
			TR0=0;						//关定时器0	
			set=!set;					//取反set标志位,以切换调节方向
			TR1=0;						//关定时器1
			dx_nb=set;
	   		break;
		case 5:	
			TR0=0;						//关定时器
			P2=0x00;					//灭显示
			Red_dx=1;
			Red_nb=1;					//全部置红灯
			TR1=0;
			sec_dx=00;					//四个方向的时间都为00
			sec_nb=00;
	   		break;
		case 6:	
			TR0=0;						//关定时器
			P2=0x00;
			TR1=1;
			sec_dx=00;					//四个方向的时间都为00
			sec_nb=00;
	   		break;
		default:break;
	}
}
//函数的定义部分
uchar key(void)	//按键扫描子程序
{	 
	uchar key_num=0;
	if(k1!=1)							//当K1(时间加)按下时
	{
		display();       				//调用显示,用于延时消抖
		if(k1!=1)							//如果确定按下
		{
		  	key_num=1;			
		  	do
		 	{ 
				display();				 //调用显示,用于延时
			}
			while(k1!=1);			 //等待按键释放
		}
	}

	if(k2!=1)							//当K2(时间减)按键按下时
	{		
		display();       				//调用显示,用于延时消抖  
		if(k2!=1)						//如果确定按下
		{	
			key_num=2;			 	
		  	do	
		    { 
				display();       		//调用显示,用于延时
			}
			while(k2!=1);			   //等待按键释放
		}
	}

	if(k3!=1)							//当K3(确认)键按下时
	{	
		display();       				//调用显示,用于延时消抖
		if(k3!=1)						//如果确定按下
		{
			key_num=3;
			do
			{
				display(); 			   //调用显示,用于延时
			}				
			while(k3!=1);			  //等待按键释放				
		}
	}	 
	if(k4!=1)							//当K4(切换)键按下
    {
		display();       				//调用显示,用于延时消抖
		if(k4!=1)						//如果确定按下
		{  
		 	key_num=4;	
			do
			{
				display(); 			   //调用显示,用于延时
			}				
			while(k4!=1);			  //等待按键释放
		}
	}	

	if(k5!=1)							//当K5(紧急)键按下时
	{
	   	display();       				//调用显示,用于延时消抖
	   	if(k5!=1)						//如果确定按下
	   	{ 	
	    	key_num=5;	
			do
			{
				display(); 				//调用显示,用于延时
			}	
			while(k5!=1);			//等待按键释放	
	   	}
	}
	if(k6!=1)							//当K6(夜间模式)按下 
	{
	   	display();       				//调用显示,用于延时消抖 
	   	if(k6!=1)						//如果确定按下
	   	{ 	
			key_num=6;	
	    	
			do
			{
				display(); 			  //调用显示,用于延时
			}	
			while(k6!=1);			//等待按键释放	
	   	}
	}
	return key_num;
}
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);				//延时
}
  • 2
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值