Proteus仿真51单片机交通灯控制系统
本文基于STC89C51/52单片机设计了一种多功能交通灯控制系统。系统通过4个两位数码管显示倒计时,采用9个独立按键实现复位、夜间模式(黄灯闪烁)、紧急模式(全红灯)、强制通行、时间设置等功能。硬件部分包含单片机、数码管、LED灯组等元件,软件采用定时器中断实现1ms基准计时,通过状态机处理不同模式切换。系统支持南北/东西方向通行时间独立设置(0-99秒可调),并在最后5秒切换为黄灯闪烁提醒。仿
@点赞、关注、评论获取更多经典案例 ;&评论留言获取源文件定制更多功能
前言
本课题基于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模型

总结:
评论留言获取源文件定制更多功能,关注后续更多实用案例。
以上内容除原理图未经实物验证,其余均已验证,如果对你有帮助请不要吝啬你的点赞、关注、评论。
更多推荐



所有评论(0)