一、实验内容
交通灯指示器是通过单片机控制模拟交通灯的运行的器件。实验使用主要设备为计算机。在Keil软件平台上使用C51语言编写“交通灯指示器”的控制程序,最后通过Proteus软件仿真电路的运行。
二、实验目的与要求
实验目的:
- 学习使用Keil软件平台进行C51语言的项目建立、设计文件装载、程序录入、编译、软件仿真调试的方法
- 使用Proteus软件进行硬件电路的搭建、仿真及设计程序虚拟下载、故障排除硬件仿真的实验方法
- 综合应用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原理图的可以私信我。