设计路口交通灯

273 阅读5分钟

一、实验内容

交通灯指示器是通过单片机控制模拟交通灯的运行的器件。实验使用主要设备为计算机。在Keil软件平台上使用C51语言编写“交通灯指示器”的控制程序,最后通过Proteus软件仿真电路的运行。


二、实验目的与要求

实验目的:

  1. 学习使用Keil软件平台进行C51语言的项目建立、设计文件装载、程序录入、编译、软件仿真调试的方法
  2. 使用Proteus软件进行硬件电路的搭建、仿真及设计程序虚拟下载、故障排除硬件仿真的实验方法
  3. 综合应用C51语言中的宏命令、if语句、while语句、运算符、函数进行程序设计。学习模块化程序设计的特点及编程方法。 实验要求: 首先东西方向红灯亮20秒,同时南北方向绿灯亮20秒。随后东西南北四个方向黄灯都闪烁3次,大约5秒。最后东西方向绿灯亮40秒,南北方向红灯亮40秒。持续循环下去。

三、实验工具

①Keil μVision5软件 ②Proteus仿真软件

四、设计原理和设计方案

该系统采用计时器,对于路灯的亮灭时间进行控制。利用数码管设计出实现显示系统。但是由于使用的数码管数量过多,采用静态显示单片机的剩余的I/O口显然不能够满足数码管的显示。因此,这里我采用动态显示。 动态显示,我采用74LS373(三态输出的八D锁存器)和延时函数。利用人眼的余晖效应实现显示系统。

五、实验操作

1、主要步骤

① 时钟设置子程序 ② 开时钟 ③ 红蓝灯设置子程序(proteus中没有黄灯,固用蓝灯代表黄灯) ④ 状态固定。(利用延时函数,实现动态显示)

2、成果分析

实际的定时要比理论定时多15s(多次计数,求取平均值)。最后在单片机上调试,理论与实际时间相符。

六、实验结论

1.图表

在这里插入图片描述

2.代码

#include"REG51.H"
#include"intrins.h"
typedef unsigned int uint;
static unsigned char second;//默认uchar初值为0
static unsigned int count=0;
sbit P36=P3^6;sbit P37=P3^7;
uint code SegCode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
/**
 * 设单片机为12KHZ    则定时  1s   使用方式1  要计数10^6  当方式1一次计数50000次,需要20次  
 *    采用T1进行定时 模式为方式1
 * 
 */

void DelayMs(uint ms);
void main(void)
{	
	uint left=second,temp=0x01;//东西南北四个方向显示的数字一样,所以我只用一个。
	P0=0X00;      //防止定时器启动就亮灯
	P2=P1=0X00;   //节约电能,保护环境。
	P36=P37=0;
	IE=0X88;     //开启T1
	TMOD=0X10;   //采用  方式2  T1
	TH1=15536/256;  TL1=15536%256;
	TR1=1;        //启动定时器T1
	while(1)
	{
		temp=0x01;
		//显示交通灯
		switch(second)
		   {
			case 21:P0=0X12;break;  //东西指示灯和南北指示灯 闪烁黄灯
			case 22:P0=0X00;break;  
			case 23:P0=0X12;break;	
			case 24:P0=0X00;break;
			case 25:P0=0X12;break;
			default:break;	
		}
		
		if(second <= 20)
			P0=0X21;
		else if(second >25 && second <= 65 )
			P0=0X0C;	
		else if(second>65)
		{
			P0=0X00;  //灭灯
			second=0;	
		}
		//显示数字
		if(second<=20)
		{	
			left=20;
			switch(0)
			{   //底下五个灯
				case 0:P1=temp;P2=SegCode[(left-second)/10];DelayMs(5);
				P1=temp<<1;P2=SegCode[(left-second)%10];DelayMs(5);		
				case 1:P1=temp<<2;P2=0x00;DelayMs(5);
				P1=temp<<3;P2=0x00;DelayMs(5);P1=temp<<4;P2=0X00;
				//右边五个灯
				case 2:P1=temp<<5;P2=0X00;DelayMs(5);
				P1=temp<<6;P2=0x00;DelayMs(5);
                case 3:P1=temp<<7;P2=0X00;P1=0X00;DelayMs(5);P36=1;P2=SegCode[(left-second)/10];
				DelayMs(5);P36=0;P37=1;P2=SegCode[(left-second)%10];DelayMs(5);P37=0;	
				default:break;				
			}
					
		}
		else if(second <= 25)
		{
			left=25;
			switch(0)
			{   //底下五个灯
				case 0:P1=temp;P2=0X00;DelayMs(5);
				P1=temp<<1;P2=0X00;DelayMs(5);		
				case 1:P1=temp<<2;P2=SegCode[(left-second)%10];DelayMs(5);
				P1=temp<<3;P2=0x00;DelayMs(5);P1=temp<<4;P2=0X00;
				//右边五个灯
				case 2:P1=temp<<5;P2=0X00;DelayMs(5);
				P1=temp<<6;P2=0x00;DelayMs(5);
                case 3:P1=temp<<7;P2=SegCode[(left-second)%10];P1=0X00;DelayMs(5);
				P36=1;P2=0X00;DelayMs(5);P36=0;P37=1;P2=0x00;DelayMs(5);P37=0;	
				default:break;				
			}			
		}
		else 
		{
			left=65;
			switch(0)
			{   //底下五个灯
				case 0:P1=temp;P2=0X00;DelayMs(5);
				P1=temp<<1;P2=0X00;DelayMs(5);		
				case 1:P1=temp<<2;P2=0X00;DelayMs(5);P1=temp<<3;P2=SegCode[(left-second)/10];
				DelayMs(5);P1=temp<<4;P2=SegCode[(left-second)%10];
				//右边五个灯
				case 2:P1=temp<<5;P2=SegCode[(left-second)/10];DelayMs(5);
				P1=temp<<6;P2=P2=SegCode[(left-second)%10];DelayMs(5);
                case 3:P1=temp<<7;P2=0X00;P1=0X00;DelayMs(5);
				P36=1;P2=0X00;DelayMs(5);P36=0;P37=1;P2=0x00;DelayMs(5);P37=0;	
				default:break;				
			}		
			
		}
		
	}
}

void timer1(void)interrupt 3
{
	count++;
	if(count==20)
	{   
		second++;
		count=0;
	}
   TH1=15536/256; 
   TL1=15536%256;//方式1要赋初值

}

void DelayMs(uint ms)
{
    uint i;
    while(ms--)	
	    for(i=0;i<113;i++);
}

总结

需要注意的我已标注在代码上。需要proteus原理图的可以私信我。