前言
本设计主要介绍十字路口红绿灯路口的单片机程序设计思路与电路设计
电路设计
交通灯的电路设计总体来说还是比较简单的,主要看设计者本人是否想要实现功能性比较多的智能交通灯,如果是简易的那只需要一个AT89C52单片机和相对应的LED灯和数码管显示模块。
本人所设计的这个简单的电路只用到了一个74LS138译码器,四个两位共阴极的八段数码管,分别显示四个方向的延时时间,一个共阴极的八段数码管,用来显示所选择的功能,红黄蓝LED灯各4个再加上一个AT89C52单片机。
电路最终实现的功能有十字路口正常通行,南北方向通行,东西方向通行,禁行通行四个功能。
电路设计图纸如下所示:
程序设计思路
此程序总体来说还比较简单的,主要可以分三个模块来写
1、数码管显示模块,显示模块通过74LS138译码器进行控制,也就是说只要写一个74LS138译码器的驱动程序即可。
2、LED灯的交替变化显示程序。
3、功能实现程序。这里用的是外部中断1来达到目的的。
工作原理
当系统上电后东西方向为绿灯25s,南北方向为红灯30s,东西方向绿灯25s后变为黄灯5s,东西方向黄灯5s后变换为东西方向红灯30s,南北方向绿灯25s,南北方向绿灯25s后变换为黄灯5s,然后循环回到东西方向绿灯25s,南北方向30s,依次进行循环。延时时间通过数码管进行显示。
功能选择:通过按键触发外部中断1改变中断变量实现相应的功能,中断变量为0的时候是正常显示,中断变量为1的时候只有南北通行,东西禁止通行,中断变量为2的时候只有东西通行,南北方向禁止通行,中断变量为3的时候东南西北四个方向都禁止通行,为保证安全在变换功能之前都要执行完正在执行的正常周期后才能进行变换。
程序编写
主程序
#include <reg52.h>
#include <intrins.h>
typedef unsigned int uint;
typedef unsigned char uchar;
void dispaly_smg();
void Zhenchang();
//定义南北显示数码管I/O端口
#define smg P2
#define LED P0
//定义按键IO端口
sbit key=P3^3;
//定义74LS138译码器I/O段
sbit LSA=P1^4;
sbit LSB=P1^5;
sbit LSC=P1^6;
uchar code smg_duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
//定义共阴极数码管的段码0~F
uchar key_num; //存储按键变量
uchar temp0; //中断计数变量
uchar temp1,temp2; //temp1东西方向时间显示,temp2南北方向时间显示
uchar flag0; //正常显示的变量
uchar flag1; //功能选择中断变量
void delay(uint i) //软件延时子程序
{
while(i--);
}
void main() //主程序
{
Time_Init(); //调用定时器和外部中断1初始化子程序
while(1)
{
if(flag1==0)
{
smg=0x00;
delay(50);
Zhenchang(); //正常工作显示
}
else if(flag1==1)
{
LED=0xf3; //南北通行
dispaly_smg(); //数码管显示子程序
}
else if(flag1==2)
{
LED=0xde; //东西通行
dispaly_smg();
}
else if(flag1==3)
{
LED=0xf6; //禁止通行
dispaly_smg();
}
}
}
数码管显示子程序
void dispaly_smg() //数码管显示函数
{
//74LS138译码器驱动
uchar i;
for(i=0;i<5;i++)
{
switch(i)
{
case 0:
LSA=0;LSB=0;LSC=0;smg=smg_duan[temp1/10];break; //东西通行时间显示
case 1:
LSA=1;LSB=0;LSC=0;smg=smg_duan[temp1%10];break;
case 2:
LSA=0;LSB=1;LSC=0;smg=smg_duan[temp2/10];break; //南北通行时间显示
case 3:
LSA=1;LSB=1;LSC=0;smg=smg_duan[temp2%10];break;
case 4:
LSA=0;LSB=0;LSC=1;smg=smg_duan[flag1];break; //显示功能选择值
}
delay(50);
smg=0x00; //数码管消隐
delay(50);
}
}
正常显示子程序
void Zhenchang()
{
switch(flag0)
{
case 0:
temp1=25;temp2=30; //两个方向显示赋初始值
LED=0xde; //东西绿,南北红
while(temp1!=0)
{
dispaly_smg(); //延时时间显示
if(temp0==100) //判断定时器中断变量是否到100次,也就是计时1s
{
temp1--; //temp1,temp2数字减1,temp0清零
temp2--;
temp0=0;
}
}
flag0++; //变量加一
break;
case 1:
temp1=5; //东西方向黄灯显示赋值
LED=0xee; //东西黄灯,南北红
while(temp1!=0)
{
dispaly_smg();
if(temp0==100)
{
temp1--;
temp2--;
temp0=0;
}
}
flag0++;
break;
case 2:
temp1=30;temp2=25;
LED=0xf3; //东西红灯,南北绿灯
while(temp2!=0)
{
dispaly_smg();
if(temp0==100)
{
temp1--;
temp2--;
temp0=0;
}
}
flag0++;
break;
case 3:
temp2=5;
LED=0xf5; //东西红灯,南北黄灯
while(temp2!=0)
{
dispaly_smg();
if(temp0==100)
{
temp1--;
temp2--;
temp0=0;
}
}
flag0=0;
break;
}
}
定时器中断初始化与外部中断初始化子程序以及中断服务程序
void Time_Init() //定时器中断0与外部中断1初始化
{
EA=1; //打开总中断
TMOD=0x01; //选择定时器工作方式,工作方式为方式1
ET0=1; //打开定时器0中断开关
TR0=1; //打开定时器0进行东西
TH0=0xdc; //装载初始值,初始值为10ms
TL0=0x00;
IT1=1; //打开外部中断1
EX1=1; //打开外部中断1的中断开关
}
void time() interrupt 1 //定时器中断复位程序
{
TH0=0xdc; //装载初始值
TL0=0x00;
temp0++; //定时器中断变量+1
}
void Init() interrupt 2 //外部中断1服务程序
{
P3=0xff; //P3口全部拉高
if(key==0) //按键是否按下
{
delay(1000); //消抖
if(key==0) //再次判断是否按下
{
while(!key); //判断按键是否松开
flag1++; //改变功能选择变量
if(flag1==4)
flag1=0; //当变量等于4的时候清零,复位
}
}
}
以上就是所有红绿灯控制的所有基本程序,大家也可以更改上面的程序使其更加的完美,比如可以加上人行横道的红绿灯、黄灯闪烁提示人们时间快到了等等一系列的功能。学无止境,编程不难,难的是贵在坚持。多写多学,时刻要保证自己脑子有一个清晰的思维能力与理解能力。