标题:
单片机交通灯程序
[打印本页]
作者:
吧更符合个
时间:
2020-7-25 19:25
标题:
单片机交通灯程序
这是写完的交通灯程序,在单片机上是能用的。因为很多时候单片机上能跑的程序在PROTEUS上不能跑,所以我没有搭建仿真,也不是用PCB板,只是在实验板上跑了一下,是能用的。具体实现的功能有
显示红绿灯:初始化状态为一向60s,另一向40s开始倒计时。然后,40s走完后,再走20s,然后就两向换倒计时的秒数。
现在有两个按键有具体功能:一个是按下停止刷新,再按一次继续刷新;一个是模式切换按键,按一下,为紧急模式,再按一下为正常模式,再按一下为特殊模式;重复按三下后转为初始化模式。代码在下面,希望对群友有用。
单片机源程序如下:
#include<reg52.h>
#include<intrins.h>
typedef unsigned int u16;
typedef unsigned char u8;
u8 digtub[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //用于实物显示的0~9
//u8 digtub[]={0xC0,0xf9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //用于Proteus显示用的0~9
u8 dat[8];//欲显示的数据
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;//以上三个是数码管位选位
sbit lred=P2^0;//东西方红灯
sbit lgreen=P3^4;//东西方绿灯
sbit lyellow=P2^7;//东西方黄灯
sbit rred=P2^5; //南北方红灯
sbit rgreen=P2^1;//南北方绿灯
sbit ryellow=P2^6;//南北向黄灯
sbit KEY1=P3^1; //按键1
sbit KEY2=P3^2; //按键2
sbit KEY3=P3^3; //按键3
sbit KEY4=P3^0;
#define RRED(x) {if((x))rred=0;else{rred=1;}} //南北向红灯开关函数
#define LRED(x) {if((x))lred=0;else{lred=1;}} //东西向红灯开关函数
#define RGREEN(x) {if((x))rgreen=0;else{rgreen=1;}} //南北向绿灯开关函数
#define LGREEN(x) {if((x))lgreen=0;else{lgreen=1;}} //东西向绿灯开关函数
#define RETURN_RYELLOW {ryellow=~ryellow;} //南北向黄灯闪烁函数
#define RETURN_LYELLOW {lyellow=~lyellow;} //东西向黄灯闪烁函数
sbit L1=P3^4;
sbit L2=P3^5;
void key_init();
void display();
void vestmode();
/********************************************************************************************
************************定时初始化函数**********************************************************/
void timer_init()
{
TMOD|=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
EA=1;
ET0=1;
}
/*********************************************************************************************************
************************以上是定时初始化函数**********************************************************/
/***************************************************************************************************
************************以下是延时函数***************************************************************/
void delay(u16 ms)
{
u16 i;
for(ms;ms>0;ms--)
{
for(i=0;i<120;i++);
}
}
/***************************************************************************************************
************************以上是延时函数***************************************************************/
u16 opendis;
void main()
{
timer_init();
while(1)
{
if(!opendis)display();
key_init();
vestmode();
}
}
bit givenum;//开关红绿灯秒数赋值的标志位
u16 staticgreen=30; //固定绿灯值可通过按键修改
u16 staticred=10; //固定红灯值可通过按键修改
u8 NSNUM[3]={40,20,60}; //南北方向红绿灯秒数[1]红灯;[2]右转红灯;[3]绿灯
u8 EWNUM[3]={60,20,40}; //东西方向红绿灯秒数[1]绿灯;[2]红灯;[3]右转红灯
/**********************
这个是定时中断函数************/
void time0() interrupt 1
{
static u16 num=0;
static u8 ewnum;//东西方向60s绿灯
static u8 nsnum;//南北方向40s红灯
static u16 nsflag=0;//南北向黄灯次数或转换红绿方向的标志
static u16 ewflag=0;//东西向黄灯次数或转换红绿方向的标志
u16 Rgreen,Lgreen; //Rgreen南北向绿灯灭标志 ;Lgreen东西向绿灯灭标志;lreturn右转红灯值(方便修改)
if(!givenum){ewnum=EWNUM[0];nsnum=NSNUM[0];}//二次赋值,为了方便修改
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++; //num=20时刚好计数是1s。
if(num==20)
{
givenum=1;
num=0;
ewnum--;
nsnum--;
if(nsnum==0){if(nsflag>=2){nsflag=0;RGREEN(0);}else{nsflag++;}nsnum=NSNUM[nsflag];}//南北向数码管循环显示。
if(ewnum==0){if(ewflag>=2){ewflag=0;}else{ewflag++;}ewnum=EWNUM[ewflag];}//东西向数码管循环显示。
if(nsflag==0||nsflag==1){RRED(1);}//南北向直行或右转时的红灯
if(nsnum>0&&nsnum<5){
RETURN_RYELLOW;
RRED(0);RGREEN(0);Rgreen=1;//南北向红绿灯都灭
}//大于0小于5时黄灯
if(nsflag==2&&!Rgreen){RGREEN(1);}//南北绿灯
if(ewflag==0||ewflag==1){LRED(1);}//东西向直行或右转时的红灯
if(ewnum>0&&ewnum<5){
RETURN_LYELLOW;
LRED(0);LGREEN(0);Lgreen=1;//东西向红绿灯都灭
}//大于0小于5时黄灯
if(ewflag==2&&!Lgreen){LGREEN(1);}//南北绿灯
dat[0]=digtub[ewnum/10];//东西方向红绿灯的十位
dat[1]=digtub[ewnum%10];//东西方向红绿灯的个位
dat[2]=digtub[nsnum/10];
dat[3]=digtub[nsnum%10];
dat[6]=digtub[ewnum/10];//东西方向红绿灯的十位
dat[7]=digtub[ewnum%10];//东西方向红绿灯的个位
dat[4]=digtub[nsnum/10];
dat[5]=digtub[nsnum%10];
}
}
/********************上面是定时中断函数*******************
*********************************************/
/*这个是按键程序*******************************************************
***************************************************************************/
static u16 modesign[6]={1,2,3};//模式选择标志
static u16 keymode;
static u16 ewgreen;
u16 ll;
void key_init()
{
static u16 i=0;
if(KEY1==0)//开关数码管显示按键
{
delay(100);
if(KEY1==0){TR0=~TR0;}
while(!KEY1);
}
if(KEY2==0) //切换模式按键
{
delay(100);
if(KEY2==0){
keymode=modesign[i++];
if(i>3){i=0;}
}
while(!KEY2);
}
if(KEY3==0)//后台修改红绿灯值,
{
delay(100);
if(KEY3==0);
while(!KEY3);
}
if(KEY4==0)//后台修改红绿灯值,
{
delay(100);
if(KEY4==0);
while(!KEY4);
}
}
/***********************************************************************************************/
/***************************************************************************************************/
void display()
{
u16 i;
for(i=0;i<8;i++)
{
switch(i)
{
case 0:LSA=0;LSB=0;LSC=0;P0=dat[1];break; //第一个数码管
case 1:LSA=1;LSB=0;LSC=0;P0=dat[0];break; //第二个数码管
case 2:LSA=0;LSB=1;LSC=0;P0=dat[5];break;//第三个数码管
case 3:LSA=1;LSB=1;LSC=0;P0=dat[4];break; //第四个数码管
case 4:LSA=0;LSB=0;LSC=1;P0=dat[7];break; //第五个数码管
case 5:LSA=1;LSB=0;LSC=1;P0=dat[6];break; //第六个数码管
case 6:LSA=0;LSB=1;LSC=1;P0=dat[3];break; //第七个数码管
case 7:LSA=1;LSB=1;LSC=1;P0=dat[2];break; //第八个数码管
}
}
}
/***************************************************************************************************
****************************************************************************************************
***********************************************************************************************/
void vestmode() //切换模式按键:keymode:1 紧急模式 ; 2 正常模式;3 特殊模式
{
if(keymode==1){
EWNUM[0]=45;EWNUM[1]=30;EWNUM[2]=15;
NSNUM[0]=30;NSNUM[1]=15;NSNUM[2]=45;
givenum =0;
keymode=0;
}
if(keymode==2){
EWNUM[0]=60;EWNUM[1]=40;EWNUM[2]=20;
NSNUM[0]=40;NSNUM[1]=20;NSNUM[2]=60;
givenum =0;
keymode=0;
}
if(keymode==3) //特殊模式后,继续按3次,会初始化到正常模式
{
opendis=~opendis;
keymode=0;
}
}
/***************************************************************************************************
****************************************************************************************************
***********************************************************************************************/
复制代码
所有程序51hei提供下载:
交通灯.rar
(71.28 KB, 下载次数: 8)
2020-7-25 19:25 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1