本交通灯程序贴合实际,除了可以显示时间外,还可以切换红绿显示。原理图利用595控制数码管位,减少IO口的占用。如果想减少595,也可以将双向同色显示屏的位接在一起。注意:仿真必须用proteus8.12版本才能打开!!!
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit duanla=P2^6;
sbit weila =P2^7;
/******控制红绿灯切换******/
sbit SH_CP=P2^0;
sbit DS=P2^1;
sbit ST_CP=P2^2;
/******控制红绿显示屏切换******/
sbit SH_CP1=P2^3;
sbit DS1=P2^4;
sbit ST_CP1=P2^5;
sbit OE=P3^0;
sbit key1=P2^6;//紧急按钮
sbit key2=P2^7;//回复运行按钮
uchar count,time;//中断次数,时间分段
uchar a,b;//显示时间变量
/******两个方向的时间设置,以1分钟为总时间******/
uchar Atime_red=30,Atime_green=25,Atime_yellow=5;
uchar Btime_red=30,Btime_green=25,Btime_yellow=5;
//uchar code duanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar code duanma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴数码管段码{0123456789}
void delay(uint z)//延时函数
{
while(z--);
}
/**************** 向HC595发送一个字节函数,控制红绿黄灯 ******************/
void send_595(uint dat)
{
uchar i;
for(i=0;i<16;i++)
{
dat <<= 1;
DS = CY; //溢出位赋值数据输出端
SH_CP = 1; //移位时钟
SH_CP = 0;
}
}
/**************** 向HC595发送一个字节函数,控制红绿显示屏 ******************/
void send_595W(uint dat)
{
uchar i;
for(i=0;i<16;i++)
{
dat <<= 1;
DS1 = CY; //溢出位赋值数据输出端
SH_CP1 = 1; //移位时钟
SH_CP1 = 0;
}
}
void init()
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TMOD=0X01;
EA=1;
ET0=1;
TR0=1;
SH_CP=0;
ST_CP=0;
SH_CP1=0;
ST_CP1=0;
OE=0;
}
void display_SN_R_EW_G()//南北红灯-东西绿灯
{
send_595W(0xffbe);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a/10];
delay(500);
send_595W(0xff7d);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a%10];
delay(500);
send_595W(0xebff);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b/10];
delay(500);
send_595W(0xd7ff);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b%10];
delay(500);
}
void display_SN_R_EW_Y()//南北红—东西黄灯
{
send_595W(0xffbe);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a/10];
delay(500);
send_595W(0xff7d);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a%10];
delay(500);
send_595W(0xffeb);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b/10];
delay(500);
send_595W(0xffd7);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b%10];
delay(500);
}
void display_SN_G_EW_R()//南北绿灯——东西红
{
send_595W(0xbeff);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a/10];
delay(500);
send_595W(0x7dff);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a%10];
delay(500);
send_595W(0xffeb);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b/10];
delay(500);
send_595W(0xffd7);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b%10];
delay(500);
}
void display_SN_Y_EW_R()//南北黄灯——东西红
{
send_595W(0xffbe);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a/10];
delay(500);
send_595W(0xff7d);
ST_CP1=1;
ST_CP1=0;
P0=duanma[a%10];
delay(500);
send_595W(0xffeb);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b/10];
delay(500);
send_595W(0xffd7);
ST_CP1=1;
ST_CP1=0;
P0=duanma[b%10];
delay(500);
}
void main()
{
init();
while(1)
{
if(time>=0&&time<25)display_SN_R_EW_G();
else if(time>=25&&time<30)display_SN_R_EW_Y();
else if(time>=30&&time<55)display_SN_G_EW_R();
else if(time>=55&&time<60)display_SN_Y_EW_R();
else
{
}
if(key1==0)
{
delay(20);
if(key1==0)
{
OE=1;//关闭显示屏
send_595(0xfff0);//双方向红灯
ST_CP=1;
ST_CP=0;
TR0=0;//关闭定时器
}
while(!key1);//按键释放
}
if(key2==0)
{
delay(20);
if(key2==0)
{
TR0=1;//开启定时器,重新开始
return;
}
while(!key2);
}
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20)
{
time++;
if(time>=0&&time<25)
{
send_595(0xff5a);
ST_CP=1;
ST_CP=0;
a=Atime_red--;
b=Btime_green--;
}
else if(time>=25&&time<30)
{
send_595(0xf5fa);
ST_CP=1;
ST_CP=0;
Btime_green=25;
a=Atime_red--;
b=Btime_yellow--;
}
else if(time>=30&&time<55)
{
send_595(0xffa5);
ST_CP=1;
ST_CP=0;
Atime_red=30;
Btime_yellow=5;
a=Atime_green--;
b=Btime_red--;
}
else if(time>=55&&time<60)
{
send_595(0xfaf5);
ST_CP=1;
ST_CP=0;
Atime_green=25;
a=Atime_yellow--;
b=Btime_red--;
}
else
{
time=0;
Atime_yellow=5;
Btime_red=30;
}
count=0;
}
}
Keil代码与Proteus仿真下载:
注意:仿真必须用proteus8.12版本才能打开,如果没有8.12的话就不要下载了
交通灯51单片机.7z
(247.58 KB, 下载次数: 36)
|