一、实验要求
以Proteus为硬件仿真平台,以C51语言为设计语言编程实现交通灯指示功能。具体如下:东西向红灯亮20秒,绿灯亮40秒;南北向红灯亮40秒,绿灯亮20秒,红绿灯之间黄灯闪烁5秒。
二、实验代码
代码如下(示例):
/**
* @brief :实现交通灯
* @exception proteus仿真时间与理论实践不符
* @author 不留名
* @date 2022-06-1 20:00:00
* @version 2.0
* */
#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++);
}
三、实验原理图
总结
本次实验还是比较困难的,这个是我改过后的版本。虽然第一版也可以应对作业,但是追求最优解(当前,因为受限于自身知识的不足)对我来说更加重要。我改原理图和程序总共花费了4小时。但是当我做出来之后,一切疲惫似乎都以消失不见。