基于51单片机的交通灯设计利用AT89C51作为系统主控,使用四个二位数码管设计四个方向的倒计时,同时每个路口设计了红外模块,通过外部中断扩展检测下降沿,判断是否有行人通过。当未能到红灯时间有行人通过,蜂鸣器响起。
一、参考代码
下面是本次设计的主要代码,主要实现定时器定时交通灯切换的逻辑,同时检测,红灯方向上是否有人员通过,如果有人员通过蜂鸣器进行报警,表示人员危险状态。
#include <REGX52.H>
#include "delay.h"
#include "Timer0.h"
#include "nixie.h"
#include "KEY.H"
typedef unsigned char u8;
u8 KeyNum,Temp;
u8 Sec,MiniSec;
u8 RunFlag=1;
int upSec_set=20, rightSec_set=20, btnSec_set=20, leftSec_set=20, change=5;
int upSec=20, rightSec=20, btnSec=20, leftSec=20;
u8 mode=0, lastState=0;
int upNum=0, rightNum=0, btnNum=0, leftNum=0;
sbit buzzer=P2^7;
sbit upRed = P1^0;
sbit upGreen = P1^1;
sbit upYellow = P1^2;
sbit rightRed = P1^3;
sbit rightGreen = P1^4;
sbit rightYellow = P1^5;
sbit dwnRed = P1^6;
sbit dwnGreen = P1^7;
sbit dwnYellow = P2^3;
sbit leftRed = P2^4;
sbit leftGreen = P2^5;
sbit leftYellow = P2^6;
void setTime()
{
upSec = upSec_set;
rightSec = rightSec_set;
btnSec = btnSec_set;
leftSec = leftSec_set;
}
//数码管显示显示
void showNixie()
{
switch(mode){
case 0:{
nixie(1, upSec/10);
nixie(2, upSec%10);
nixie(3, (upSec+change)/10);
nixie(4, (upSec+change)%10);
nixie(5, (upSec+change+rightSec+change)/10);
nixie(6, (upSec+change+rightSec+change)%10);
nixie(7, (upSec+change+rightSec+change+btnSec+change)/10);
nixie(8, (upSec+change+rightSec+change+btnSec+change)%10);
}break;
case 1:{
nixie(1, (rightSec+change+btnSec+change+leftSec+change)/10);
nixie(2, (rightSec+change+btnSec+change+leftSec+change)%10);
nixie(3, (rightSec)/10);
nixie(4, (rightSec)%10);
nixie(5, (rightSec+change)/10);
nixie(6, (rightSec+change)%10);
nixie(7, (rightSec+change+btnSec+change)/10);
nixie(8, (rightSec+change+btnSec+change)%10);
}break;
case 2:{
nixie(1, (btnSec+change+leftSec+change)/10);
nixie(2, (btnSec+change+leftSec+change)%10);
nixie(3, (btnSec+change+leftSec+change+upSec+change)/10);
nixie(4, (btnSec+change+leftSec+change+upSec+change)%10);
nixie(5, (btnSec)/10);
nixie(6, (btnSec)%10);
nixie(7, (btnSec+change)/10);
nixie(8, (btnSec+change)%10);
}break;
case 3:{
nixie(1, (leftSec+change)/10);
nixie(2, (leftSec+change)%10);
nixie(3, (leftSec+change+upSec+change)/10);
nixie(4, (leftSec+change+upSec+change)%10);
nixie(5, (leftSec+change+upSec+change+rightSec+change)/10);
nixie(6, (leftSec+change+upSec+change+rightSec+change)%10);
nixie(7, (leftSec)/10);
nixie(8, (leftSec)%10);
}break;
case 4:{
if(lastState==0){
nixie(1, change/10);
nixie(2, change%10);
nixie(3, (upSec+change)/10);
nixie(4, (upSec+change)%10);
nixie(5, (upSec+change+rightSec+5)/10);
nixie(6, (upSec+change+rightSec+5)%10);
nixie(7, (upSec+change+rightSec+5+btnSec+5)/10);
nixie(8, (upSec+change+rightSec+5+btnSec+5)%10);
}
else if(lastState==1){
nixie(1, (rightSec+change+btnSec+5+leftSec+5)/10);
nixie(2, (rightSec+change+btnSec+5+leftSec+5)%10);
nixie(3, (change)/10);
nixie(4, (change)%10);
nixie(5, (rightSec+change)/10);
nixie(6, (rightSec+change)%10);
nixie(7, (rightSec+change+btnSec+5)/10);
nixie(8, (rightSec+change+btnSec+5)%10);
}
else if(lastState==2){
nixie(1, (btnSec+change+leftSec+5)/10);
nixie(2, (btnSec+change+leftSec+5)%10);
nixie(3, (btnSec+change+leftSec+5+upSec+5)/10);
nixie(4, (btnSec+change+leftSec+5+upSec+5)%10);
nixie(5, (change)/10);
nixie(6, (change)%10);
nixie(7, (btnSec+change)/10);
nixie(8, (btnSec+change)%10);
}
else if(lastState==3){
nixie(1, (leftSec+change)/10);
nixie(2, (leftSec+change)%10);
nixie(3, (leftSec+change+upSec+5)/10);
nixie(4, (leftSec+change+upSec+5)%10);
nixie(5, (leftSec+change+upSec+5+rightSec+5)/10);
nixie(6, (leftSec+change+upSec+5+rightSec+5)%10);
nixie(7, (change)/10);
nixie(8, (change)%10);
}
}break;
default:break;
}
}
void showYellowLed(u8 lastState)
{
switch(lastState){
case 0:{
upRed=1;upGreen=1;upYellow =0;
rightRed =0;rightGreen =1;rightYellow =1;
dwnRed =0;dwnGreen =1;dwnYellow =1;
leftRed =0;leftGreen =1;leftYellow =1;
}break;
case 1:{
upRed =0;upGreen =1;upYellow =1;
rightRed =1;rightGreen =1;rightYellow =0;
dwnRed =0;dwnGreen =1;dwnYellow =1;
leftRed =0;leftGreen=1;leftYellow=1;
}break;
case 2:{
upRed =0;upGreen=1;upYellow=1;
rightRed =0;rightGreen =1;rightYellow =1;
dwnRed =1;dwnGreen =1;dwnYellow=0;
leftRed=0;leftGreen=1;leftYellow=1;
}break;
case 3:{
upRed =0;upGreen=1;upYellow=1;
rightRed=0;rightGreen =1;rightYellow =1;
dwnRed =0;dwnGreen =1;dwnYellow=1;
leftRed=1;leftGreen =1;leftYellow=0;
}break;
default:break;
}
}
//外部中断初始化
void Int0_Init()
{
// 使能全局中断
EA = 1;
// 使能外部中断0
EX0 = 1;
// 配置外部中断0的触发方式为下降沿触发
IT0 = 1;
}
//外部中断捕捉
void Int0_ISR() interrupt 0
{
switch(mode){
case 0:{
//进行车流量统计
if(P3_4==0){
upNum++;
}
}break;
case 1:{
if(P3_5==0){
rightNum++;
}
}break;
case 2:{
if(P3_6==0){
btnNum++;
}
}break;
case 3:{
if(P3_7==0){
leftNum++;
}
}break;
default:break;
}
}
void main()
{
Int0_Init();
Timer0_Init();
// UART_Init();
while(1)
{
//违规行驶判断
switch(mode){
case 0:{
if(P3_5==0 || P3_6==0 || P3_7==0){
buzzer=0;
}
else{
buzzer=1;
}
}break;
case 1:{
if(P3_4==0 || P3_6==0 || P3_7==0){
buzzer=0;
}
else{
buzzer=1;
}
}break;
case 2:{
if(P3_4==0 || P3_5==0 || P3_7==0){
buzzer=0;
}
else{
buzzer=1;
}
}break;
case 3:{
if(P3_4==0 || P3_5==0 || P3_6==0){
buzzer=0;
}
else{
buzzer=1;
}
}break;
default:break;
}
}
}
void Sec_Loop()
{
if(RunFlag)
{
if(++MiniSec>=100)
{
MiniSec=0;
switch(mode){
//北方向通行
case 0:{
showNixie();
if(--upSec<=0){
lastState=0;
mode=4;
}
upRed =1;
upGreen =0;
upYellow =1;
rightRed =0;
rightGreen =1;
rightYellow =1;
dwnRed =0;
dwnGreen =1;
dwnYellow =1;
leftRed =0;
leftGreen =1;
leftYellow =1;
}break;
//东方向通行
case 1:{
showNixie();
if(--rightSec<=0){
lastState=1;
mode=4;
}
upRed =0;
upGreen =1;
upYellow =1;
rightRed =1;
rightGreen =0;
rightYellow =1;
dwnRed =0;
dwnGreen =1;
dwnYellow =1;
leftRed =0;
leftGreen =1;
leftYellow =1;
}break;
//南方向通行
case 2:{
if(--btnSec<=0){
lastState=2;
mode=4;
}
upRed =0;
upGreen =1;
upYellow =1;
rightRed =0;
rightGreen =1;
rightYellow =1;
dwnRed =1;
dwnGreen =0;
dwnYellow =1;
leftRed =0;
leftGreen =1;
leftYellow =1;
showNixie();
}break;
case 3:{
showNixie();
if(--leftSec<=0){
lastState=3;
mode=4;
}
upRed =0;
upGreen =1;
upYellow =1;
rightRed =0;
rightGreen =1;
rightYellow =1;
dwnRed =0;
dwnGreen =1;
dwnYellow =1;
leftRed =1;
leftGreen =0;
leftYellow =1;
}break;
//西方向通行
case 4:{
showNixie();
showYellowLed(lastState);
if(--change<0){
change=5;
switch(lastState){
case 0:{
mode=1;
if(upNum>20){
upSec_set+=5;
}
else if(upNum<10){
upSec_set-=5;
if(upSec_set<=10){
upSec_set=10;
}
}
upNum=0;
setTime();
}break;
case 1:{
mode=2;
if(rightNum>20){
rightSec_set+=5;
}
else if(rightNum<10){
rightSec_set-=5;
if(rightSec_set<=10){
rightSec_set=10;
}
}
rightNum=0;
setTime();
}break;
case 2:{
mode=3;
if(btnNum>20){
btnSec_set+=5;
}
else if(btnNum<10){
btnSec_set-=5;
if(btnSec_set<=10){
btnSec_set=10;
}
}
btnNum=0;
setTime();
}break;
case 3:{
mode=0;
if(leftNum>20){
leftSec_set+=5;
}
else if(leftNum<10){
leftSec_set-=5;
if(leftSec_set<=10){
leftSec_set=10;
}
}
leftNum=0;
setTime();
}break;
default:break;
}
}
}break;
default:break;
}
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count1,T0Count2,T0Count3;
TL0=0X18;
TH0=0xfc;
T0Count1++;
if(T0Count1>=20)
{
T0Count1=0;
Key_Loop();
}
T0Count2++;
if(T0Count2>=2)
{
T0Count2=0;
nixie_Loop();
}
T0Count3++;
if(T0Count3>=10)
{
T0Count3=0;
Sec_Loop();
}
}
二、功能演示
1、灯光切换逻辑
如图可知,以下是红绿灯运行逻辑,四个二位数码管进行显示时间,同时到点进行红绿黄灯切换,如下图:
2、红外检测人员通过并报警
当红灯方向有人员通过的时候,此时检测到有人员闯红灯,此时系统驱动蜂鸣器进行报警。
三、项目总结
本次项目使用定时器加数码管加led实现了交通灯的一个仿真,通过交通灯倒计时时间实现红绿黄灯的切换,完成最后功能。