摘要:

本项目以AT89C52为基础,使用74LS245控制7SEG-MPX2-CC晶体数码管显示指定的内容,同时操控LED灯显示该时间对应的颜色,达到交通灯的效果

一.主体思路

将东西南北分为主干道和次干道,南北为主干道,东西为次干道,两个IO口控制主干道的数码管位选,另外两个IO口控制次干道的数码管位选,由74LS245控制主干道和次干道四个数码管的段选,显示相应的数字

将整个过程分为四个状态:
状态一:东西红灯亮,南北绿灯亮

状态二:东西红灯亮,南北黄灯亮

状态三:南北红灯亮,东西绿灯亮

状态四:南北红灯亮,东西黄灯亮

状态一、二为一周期,状态三、四为一周期

设红灯时间为RT,黄灯时间为YT,绿灯时间为GT,则RT=GT+YT

二.主要内容

1.主要功能

(一)日间模式:模拟交通灯闪烁

(二)夜间模式:黄灯间断闪烁

(三)南北紧急制动:南北亮红灯,东西亮绿灯

(四)东西紧急制动:东西亮红灯,南北亮绿灯

2.硬件电路设计

2.1 元件选取

如上图所示,选取AT89C52开发板,74LS245模块,7SEG-MPX2-CC晶体数码管,三色LED灯(RED、YELLOW、GREEN)、按钮BUTTON以及电阻RES和排阻RESPACK-8以及复位所需元器件

2.2 单片机IO口选取

 如上图所示,使用了P1的0~3IO口,使用了P0,P2全部IO口,使用了P3的0~1IO口和复位所需IO口

2.3 硬件部分作用

(一)74LS245模块

74LS245是8路同相三态双向总线收发器,可双向传输数据

该模块的作用是控制晶体数码管的段选和位选

CE是使能端,若为高电平,A/B端的信号将不导通,只有为低电平时A/B端被启用,起到开关的作用,即低电平有效

AB/BA是控制输入输出的方向,高电平时由A端输入,B端输出,低电平时由B端输入,A端输出,此处选用高电平

第2~9引脚,即A0~A7是信号输入输出端,A0=B0是一组,以此类推

第11-18引脚,即B7-B0上同
(二)7SEG-MPX2-CC晶体数码管模块

该模块的作用是显示交通灯剩余的时间,A~G分别代表8个段,不同的段组合能显示出不同的数组或字母,DP代表小数点,1,2代表第一位和第二位

(三)LED交通灯模块

该模块的作用是显示此时的交通情况,分为红、黄、绿三色,不同状态和模式将亮起不同的灯

(四)按键模块

该模块的作用是切换模式,改变交通灯的状态

(五)复位模块

该模块的作用是使系统复位,从而切换其他模式

3.软件设计

先进行模块化编程

如上图所示,将整体程序分为主函数main,延时函数delay,按键模块key,显示模块dis,定时器模块timer

(一)timer模块

定义timer_init函数,对定时器进行初始化。

初始化步骤如下:

1.首先设置TMOD寄存器,定时器T0工作在方式1,使TMOD寄存器的M1,M0=01,设置C/T=0,为定时器工作模式,对T0的运行仅由TR0来控制,应使相应的GATE位为0,定时器T1不使用,各相关位均设为0,所以TMOD寄存器应初始化为0x01。

2.计算定时器T0的计数初值,设定时时间为50ms,通过公式计算可得出相应的高八位和低八位,分别装入TH0和TL0。

3.设置IE寄存器,将寄存器中的EA,ET0位置1

4.启动和停止定时器T0,将定时器控制寄存器TCON中的TR0=1,则启动定时器T0;TR0=0,则启动定时器T0计时

(二)dis模块

首先使用sbit定义相关引脚,如上图所示

P2的0~2引脚代表主干道(南北)的LED交通灯,P2的5~7引脚代表次干道(东西)的LED交通灯,P1的2~3引脚代表主干道(南北)数码管的位选,P1的0~1引脚代表次干道(东西)数码管的位选。

定义数组tab代表0~9数字,同时定时时间AF和BF,并初始化为自定义数值。

定义计数变量count,用于定时器中断程序。

定义display1函数,为次干道数码管显示函数,如上图所示。

传入的形参num1,num2分别为倒计时的十位和个位,使P0显示下标为num的值。

定义display2函数,为主干道数码管显示函数,上同。

定义display3函数,为夜间模式,操控主次干道的四个黄灯进行间断闪烁。

定义display4函数,为南北紧急制动。

定义display5函数,为东西紧急制动。

定义display函数,模拟交通灯的四个状态。

第一种情况,为主干道红灯,次干道绿灯+黄灯的两个状态。

AF在定时器的作用下不断递减,当绿灯时间减为0,即进入黄灯时刻时,关闭次干道绿灯,打开次干道黄灯,循环结束后重新赋值进入下一状态。

第二种情况,为次干道红灯,主干道绿灯+黄灯的两个状态。

BF在定时器的作用下不断递减,当绿灯时间减为0,即进入黄灯时刻时,关闭主干道绿灯,打开主干道黄灯,循环结束后重新赋值进入下一状态(即回到第一种情况)。

定义定时器中断函数,如上图所示,每当进入中断程序,先重新为TH0和TL0赋初值,进入一次是50ms,所以20次是1s(此处取count界限为23),即每隔1s时间减1,完成倒计时的效果

(三)key模块

通过控制按钮改变点阵中所显示的内容

首先使用sbit定义相关引脚,如上图所示

不断扫描是否有按键按下,若有按键按下,则该引脚变为低电平,对其进行消除抖动,并判断是否松开,若松开,进行二次消除抖动,并传回相关按键的值

(四)delay模块

编写能够延时1ms的函数

(五)main模块

首先调用定时模块初始化函数,将定时器初始化,在循环中不断扫描key的按键值,不同的按键值代表不同的模式,每个模式会模拟不同的交通灯状态

4.源程序代码

(一)main模块

#include <reg52.h>
#include "delay.h"
#include "dis.h"
#include "timer.h"
#include "key.h"
#define uchar unsigned char
#define uint unsigned int
uchar KeyNum;
void main(){
	timer_init();
	while(1){
		KeyNum=Key();
		if(KeyNum==1){
			while(1){
				display();             //日间模式
			}
		}
		else if(KeyNum==2){
			while(1){
				display3();            //夜间模式
			}
		}
		else if(KeyNum==3){
			while(1){
				display4();            //南北紧急制动
			}
		}
		else if(KeyNum==4){
			while(1){
				display5();            //东西紧急制动
			}
		}
	}
}

(二)delay模块

#define uchar unsigned char
#define uint unsigned int
void delay(uint x){
	uchar i,j;
	while(x--){
		i=2;
		j=239;
		do{
			while(--j);
		}while(--i);
	}
}

(三)key模块

#include<reg52.h>
#include"delay.h"
sbit key1=P2^3;
sbit key2=P2^4;
sbit key3=P3^0;
sbit key4=P3^1;
unsigned char Key(){
	unsigned char number=0;
	if(key1==0){delay(20);while(key1==0);delay(20);number=1;}
	if(key2==0){delay(20);while(key2==0);delay(20);number=2;}
	if(key3==0){delay(20);while(key3==0);delay(20);number=3;}
	if(key4==0){delay(20);while(key4==0);delay(20);number=4;}
	return number;
}

(四)dis模块

#include <reg52.h>
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
#define ON 0
#define OFF 1
sbit AR=P2^0;
sbit AY=P2^1;
sbit AG=P2^2;
sbit BR=P2^5;
sbit BY=P2^6;
sbit BG=P2^7;
sbit A1=P1^2;
sbit A2=P1^3;
sbit B1=P1^0;
sbit B2=P1^1;
char tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar BF=7,AF=10;
uchar count;
//东西方向
void display1(uchar num1,uchar num2){
	P0=tab[num1];
	B1=ON;
	delay(1);
	B1=OFF;
	P0=tab[num2];
	B2=ON;
	delay(1);
	B2=OFF;
}
//南北方向
void display2(uchar num1,uchar num2){
	P0=tab[num1];
	A1=ON;
	delay(1);
	A1=OFF;
	P0=tab[num2];
	A2=ON;
	delay(1);
	A2=OFF;
}
void display3(){
	AY=ON;
	BY=ON;
	delay(200);
	AY=OFF;
	BY=OFF;
	delay(200);
}
void display4(){
	AR=ON;
	AY=OFF;
	AG=OFF;
	BR=OFF;
	BY=OFF;
	BG=ON;
}
void display5(){
	AR=OFF;
	AY=OFF;
	AG=ON;
	BR=ON;
	BY=OFF;
	BG=OFF;
}
void display(){				
	//南北红灯,东西绿灯+黄灯
	AR=BG=ON;
	while(AF){
		display2(AF/10,AF%10);
		display1(BF/10,BF%10);
		while(AF==3)//黄灯时刻
		{
			while(AF!=0){
			display1(AF/10,AF%10);
			display2(AF/10,AF%10);
			BG=OFF;
			BY=~BY;
			}
		}
	}
	AR=OFF;
	BG=OFF;
	BY=OFF;
	BF=10,AF=7;
	
	//东西红灯,南北绿灯+黄灯
	AG=BR=ON;
	while(BF){
		display1(BF/10,BF%10);
		display2(AF/10,AF%10);
		while(BF==3)//黄灯时刻
		{
			while(BF!=0){
			display1(BF/10,BF%10);
			display2(BF/10,BF%10);
			AG=OFF;
			AY=~AY;
			}
		}
	}
	BR=OFF;
	AG=OFF;
	AY=OFF;
	AF=10,BF=7;			
}
void timer0() interrupt 1{
	TH0=(65536-40000)/256; 
	TL0=(65536-40000)%256; 
	count++; 
	if(count>23){ 
		BF--; 
		AF--; 
		count=0; 
		} 
	}

(五)timer模块

#include <reg52.h>
#include "delay.h"
#define uchar unsigned char
#define uint unsigned int
#define ON 0
#define OFF 1
sbit AR=P2^0;
sbit AY=P2^1;
sbit AG=P2^2;
sbit BR=P2^5;
sbit BY=P2^6;
sbit BG=P2^7;
sbit A1=P1^2;
sbit A2=P1^3;
sbit B1=P1^0;
sbit B2=P1^1;
void timer_init(){
	TMOD=0x01;
	TH0=(65536-40000)/256; 
	TL0=(65536-40000)%256; 
	EA=1; 
	ET0=1; 
	TR0=1;
	AR=OFF;
	AY=OFF;
	AG=OFF;
	BR=OFF;
	BY=OFF;
	BG=OFF;
}

至此,我们已经基本完成了整个项目,.h文件自然不必多说,相信各位读者的能力,最后感谢读者能够学习到这里,你是否对单片机有了更深的了解?

不足之处请多担待,欢迎各位一起讨论和交流!

物联沃分享整理
物联沃-IOTWORD物联网 » Arduino交通灯实验教程

发表评论