本文是基于80C51所作的交通灯显示系统,为本人单片机课程设计,内容如下:
- 东西方向、南北方向均有红、黄、绿三种信号灯;
- 带紧急制动按钮,按钮按下,所有方向亮红灯;再次按下,恢复正常显示;
- 夜间模式按钮按下,所有方向显示黄灯闪烁;
- 实时提醒绿灯亮的剩余时间(用两位数码管显示,使用共阳极数码管)。
🚦基于C51单片机的交通灯显示系统仓库(Github)
😉本人Github
Traffic-Light-Display-System-Based-on-C51
本项目为本人课程设计备份(基于C51单片机的交通灯显示系统)
交通灯功能特点
为对十字路口交通进行合理而有效的控制,本设计的数显交通灯系统需具备以下几种功能:
- 在十字路口进行控制时,能够实现红、绿、黄3种颜色信号灯的颜色切换显示,以此来提示汽车进行直道通行、停止通行或转弯;
- 两干道交替允许通行,每次放行30秒,黄灯亮5秒;
- 当按下紧急制动按钮后,对系统进行中断,东西南北均显示红灯,再次按下时恢复正常状态;
- 当按下夜间模式按钮后,对系统进行中断,所有方向均闪烁黄灯;
- 将倒计时使用两位共阳极七段数码管进行时间显示,对直道通行、停止通行或转弯时间进行倒计时显示,提示各路口汽车通行时间。
设计思路
为实现上文列出的十字路口交通控制三项基本功能,系统采用AT89C51单片机作为交通灯控制设计的核心模块,使用16位计时器进行倒计时、共阳极数码管进行倒计时显示、红黄绿三种颜色的LED作为交通灯、利用外部中断0来进入紧急模式及夜间模式。在系统设计的过程中,需要对系统进行硬件和软件两个方面的设计,设计完成后,为使人工管理控制更加方便快捷,还需对设计好的系统进行仿真,以便于程序的调整管控。
Proteus仿真
为了更直观看到交通灯工作过程,本项目采用了Proteus软件进行模拟仿真,通过调试仿真结果基本能满足使用要求,可以根据实际需要调整不同方向灯亮的时间。
keil 5的应用
与大多数集成开发环境类似,Keil 5集成开发环境也是用工程的方法来管理文件,在一个工程文件中源程序(C51程序、汇编程序)、头文件等都可以进行统一管理。
安装运行KEIL 5,使用KEIL的开发工具进行项目开发过程,与其他软件开发项目的过程基本上相同:
- 创建C 语言或汇编语言的源程序。
- 编译或汇编源文件。
- 纠正源文件中的错误。
- 从编译器和汇编器连接目标文件。
- 测试连接的应用程序。
程序代码(C语言)
#include <reg51.h>
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 dx_nb=0; //东西南北控制位
bit Yellow_status=0; //黄灯闪烁标志位
unsigned char sec_dx; //东西方向时间存储变量
unsigned char sec_nb; //南北方向时间存储变量
float set_timedx=30; //东西方向的通行单次时间
float set_timenb=30; //南北方向的通行单次时间
unsigned char buf[4]; //秒显示的变量
unsigned char data countt0; //定时器0中断计数器
unsigned char data countt1; //定时器1中断计数器
unsigned char flag_option=0; //功能选择位:1 紧急模式;2 夜间模式
sbit key_EP=P3^2; //紧急模式
unsigned char conut_ER; //紧急状态
sbit key_night=P3^3; //夜间模式
unsigned char flag_Night; //夜间状态
unsigned char conut_night; //夜间模式
unsigned char code led[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 time)
{
unsigned int j,k;
for(j=0;j<time;j++)
for(k=0;k<124;k++);
}
/*显示函数*/
void display(void)
{
buf[0]=sec_nb/10; //第1位 东西十位
buf[1]=sec_nb%10; //第2位 东西个位
buf[2]=sec_dx/10; //第3位 南北十位
buf[3]=sec_dx%10; //第4位 南北个位
P1=~0xfe; //LED1
P0=~led[buf[0]]; //东西十位
delay(1);
P1=~0xfd; //LED2
P0=~led[buf[1]]; //东西个位
delay(1);
P1=~0Xfb; //LED3
P0=~led[buf[2]]; //南北十位
delay(1);
P1=~0Xf7; //LED4
P0=~led[buf[3]]; //南北个位
delay(1);
}
/*功能函数*/
void function(void)
{
switch (flag_option)
{
case 1:
{
conut_ER=1-conut_ER;
if(conut_ER==1)
{
TR0=0; //关交通灯定时器
P2=0x00; //关全部信号灯
Red_dx=1; //全部置红灯
Red_nb=1;
}
if(conut_ER==0)
{
TR0=1; //开交通灯定时器
P2=0X00; //关全部信号灯
Green_dx=1; //东西绿灯亮
Red_nb=1; //南北红灯亮
sec_dx=set_timedx; //回到初值
sec_nb=sec_dx+5;
}
flag_option=0;
break;
}
case 2:
{
conut_night=1-conut_night;
if(conut_night==1)
{
TR0=0; //关交通灯定时器
P2=0x00; //关全部信号灯
flag_Night=1; //打开夜间模式
sec_dx=00; //四个方向的时间都为00
sec_nb=00;
}
if(conut_night==0)
{
TR0=1; //开交通灯定时器
P2=0x00; //关全部信号灯
Green_dx=1; //东西绿灯亮
Red_nb=1; //南北红灯亮
flag_Night=0; //打开夜间模式
sec_dx=set_timedx; //回到初值
sec_nb=sec_dx+5;
}
flag_option=0;
break;
}
default:
break;
}
}
/*处理整个交通灯计时*/
void time0(void) interrupt 1 using 1 //定时中断子程序
{
TH0=0x4C; //重赋初值;11.0592m晶振50ms
TL0=0X00;
TR0=1; //开交通灯定时器
countt0++; //计数器数加1(用于计算时间)
if(countt0==20) //定时器中断次数=20时(即1秒时)
{
countt0=0; //清零计数器
sec_dx--; //东西时间减1
sec_nb--; //南北时间减1
if(sec_nb==0&&sec_dx==5&&(Yellow_status==0)) //当南北倒计时到0时,重置5秒,用于黄灯闪烁时间
{
sec_nb=5;
Yellow_status=1;
}
if(sec_dx==0&&sec_nb==5&&(Yellow_status==0)) //当东西倒计时到0时,重置5秒,用于黄灯闪烁时间
{
sec_dx=5;
Yellow_status=1; //启动黄灯开始倒计时
}
if((sec_nb<=5)&&(dx_nb==0)&&(Yellow_status==1)) //东西黄灯闪
{
Green_dx=0;
Yellow_dx=~Yellow_dx;
}
if((sec_dx<=5)&&(dx_nb==1)&&(Yellow_status==1)) //南北黄灯闪
{
Green_nb=0;
Yellow_nb=~Yellow_nb;
}
if(dx_nb==0&&sec_nb==0&&sec_dx==0) //东西通行:当黄灯时间、通行方向倒计时到0时
{
P2=0x00; //重置东西南背方向的红绿灯
Green_nb=1; //南北绿灯亮
Red_dx=1; //东西红灯亮
dx_nb=!dx_nb; //交换通行方向
Yellow_status=0; //关闭黄灯闪烁
sec_dx=set_timedx+5; //重赋东西方向的起始值
sec_nb=set_timenb; //重赋南北方向的起始值
}
if(dx_nb==1&&sec_dx==0&&sec_nb==0) //南北通行:当黄灯时间、通行方向倒计时到0时
{
P2=0X00; //重置东西南北的红绿灯状态
Green_dx=1; //东西绿灯亮
Red_nb=1; //南北红灯亮
dx_nb=!dx_nb; //交换通行方向
Yellow_status=0; //关闭黄灯闪烁
sec_dx=set_timedx; //重赋东西方向的起始值
sec_nb=set_timenb+5; //重赋南北方向的起始值
}
}
}
/*用来处理夜间黄灯闪烁*/
void time1(void) interrupt 3 //定时中断子程序
{
TH1=0x4C; //重赋初值;11.0592m晶振50ms
TL1=0X00;
countt1++; //计数器数加1(用于计算时间)
if(countt1==10) //定时器中断次数=10时(即0.5秒)
{
if(flag_Night==1)
{
Yellow_nb=~Yellow_nb; //南北黄灯
Yellow_dx=~Yellow_nb; //东西黄灯
}
}
if(countt1==20) //定时器中断次数=20时(即1秒时)
{
countt1=0; //清零计数器
if(flag_Night==1)
{
Yellow_nb=~Yellow_nb; //南北黄灯
Yellow_dx=~Yellow_nb; //东西黄灯
}
}
}
//外部中断0
void int0(void) interrupt 0 using 1 //紧急模式
{
while(!key_EP)display();
flag_option=1;
}
//外部中断1
void int1(void) interrupt 2 using 1 //夜间模式
{
while(!key_night)display();
flag_option=2;
}
/*初始化函数*/
void init()
{
TMOD=0X11; //定时器设置
TH1=0x4C; //TH1重赋初值;11.0592m晶振50ms
TL1=0X00;
TH0=0x4C; //TH0重赋初值;11.0592m晶振50ms
TL0=0X00;
TCON=0X50; //启动定时0、定时1
IE=0x8F; //开总中断;定时器1中断开启;开外部中断1;定时器0中断开启;开外部中断
P2=0Xc3; //开始默认状态,东西绿灯,南北黄灯
sec_nb=35; //南北方向初始时间
sec_dx=30; //东西方向初始时间
}
//主程序
void main()
{
init(); //初始化定时器、中断服务
while(1)
{
if(flag_option!=0)function(); //调用功能函数
display(); //调用显示函数
}
}