分类: C/C++
2009-11-01 18:37:43
基于AT89S52单片机的交通灯系统实验
实物图如下图所示:
原理图如下图所示:
操作说明:
南北每次通行时间设为30秒、东西每次通行间为20秒,时间按K1可设置修改。
按K1一次进入调南北通行时间,再按一次K1进入调东西通行时间。再按一次K1退出设定通行时间模式,进入设定通行时间模式后按K2加1,按K3减1。
在正常模式下按K2进入禁止南北通行模式,再按一下K2进入禁止东西通行模式,再按一下K2退出。
在正常模式下按一下K3进入紧急模式,再按一下K3进入夜间模式,再按一下K3退出。
C语言程序为:
/********************************************************************
* 程序名; 单片机控制的交通灯
* 功 能: 南北每次通行时间设为30秒、东西每次通行间为20秒,时间按K1可设置修改。
* 按K1一次进入调南北通行时间,再按一次K1进入调东西通行时间。再按一次K1退出设定
* 通行时间模式,进入设定通行时间模式后按K2加1,按K3减1。再正常模式下按K2进入禁
* 止南北通行模式,再按一下K2进入禁止东西通行模式,再按一下K2退出。在正常模式下
* 按一下K3进入紧急模式,再按一下K3进入夜间模式,再按一下K3退出。
* 编程者: ZPZ
* 编程时间:2009/10/2
*********************************************************************/
#include
#define uint unsigned int //变量类型宏定义
#define uchar unsigned char
//定义数据口
#define data_bus P0
#define shu 5
//定义全局变量
char sn_num0=30,ew_num0=20;
char sn_num,ew_num;
uchar a=0,num=0,i=0,j=0,k=0;
bit b=0; //定义位标志
bit c=0;
bit v=1;
sbit sn_h=P2^7; //定义数码管的位选口
sbit sn_l=P2^6;
sbit ew_h=P2^5;
sbit ew_l=P2^4;
//定义led灯口
sbit n_red=P1^2;
sbit n_yellow=P1^1;
sbit n_green=P1^0;
sbit s_red=P1^6;
sbit s_yellow=P1^7;
sbit s_green=P2^0;
sbit e_red=P1^3;
sbit e_yellow=P1^4;
sbit e_green=P1^5;
sbit w_red=P2^3;
sbit w_yellow=P2^2;
sbit w_green=P2^1;
sbit k1=P3^2; //定义键盘口
sbit k2=P3^1;
sbit k3=P3^0;
uchar code num_table[]={ 0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f}; //定义显示段码
uchar code num_table1[]={ 0x00,0x71};
/***********************延时子函数************************/
void delay(uint t)
{
uint i,j;
for(i=t;i>0;i--)
for(j=120;j>0;j--);
}
/**************************定时器1初始化函数***************************/
void timer0_init(bit t)
{
TMOD=0x01; //定时器0工作在方式1
TH0=0x3c; //赋初值
TL0=0xb0;
EA=1; //开总中断
ET0=1; //允许定时器0中断
TR0=t; //为‘1’启动定时器0
}
/**************************定时器1中断函数*****************************/
void timer0() interrupt 1
{
TH0=0x3c; //重复初值 (50ms)
TL0=0xb0;
num++;
if(num==20) //定时1分钟 (20*50ms)
{
c=~c; //c取反用于黄灯和数码管闪烁
if(b==0)
{
sn_num--; //一分钟南北通行时间减1
if(sn_num<0)
{b=1;sn_num=sn_num0;}
}
else
{
ew_num--; //一分钟东西通行时间减1
if(ew_num<0)
{b=0;ew_num=ew_num0;}
}
num=0;
}
}
/***********************显示函数************************/
void display(char sn_n,char ew_n)
{
uchar i;
for(i=0;i<4;i++)
{
switch(i)
{
case 0:
if(a==0){data_bus=num_table[sn_n/10];}//数码管1显示南北通行时间的十位
else if(a==1)
{
data_bus=num_table[sn_n/10];
}
else if(a==2)
{
data_bus=num_table1[0]; // 数码管1不显示
}
else
{
if(c==0)
data_bus=num_table1[1]; //数码管1显示F
else
data_bus=num_table1[0];
}
ew_h=0; //关其他的三个数码管
ew_l=0;
sn_l=0;
sn_h=1;//开数码管1
break;
case 1:
if(a==0){data_bus=num_table[sn_n%10];}//数码管2显示南北通行时间的个位
else if(a==1)
{
data_bus=num_table[sn_n%10];
}
else if(a==2)
{
data_bus=num_table1[0];
}
else
{
if(c==0)
data_bus=num_table1[1];
else
data_bus=num_table1[0];
}
ew_h=0;
ew_l=0;
sn_h=0;
sn_l=1;
break;
case 2:
if(a==0){data_bus=num_table[ew_n/10];}//数码管3显示东西通行时间的十位
else if(a==1)
{
data_bus=num_table1[0];
}
else if(a==2)
{
data_bus=num_table[ew_n/10];
}
else
{
if(c==0)
data_bus=num_table1[1];
else
data_bus=num_table1[0];
}
sn_h=0;
sn_l=0;
ew_l=0;
ew_h=1;
break;
case 3:
if(a==0){data_bus=num_table[ew_n%10];}//数码管4显示东西通行时间的个位
else if(a==1)
{
data_bus=num_table1[0];
}
else if(a==2)
{
data_bus=num_table[ew_n%10];
}
else
{
if(c==0)
data_bus=num_table1[1];
else
data_bus=num_table1[0];
}
sn_h=0;
sn_l=0;
ew_h=0;
ew_l=1;
break;
}
delay(3);
}
}
/***********************键盘扫描函数************************/
void keyscan()
{
if(k1==0)
{
delay(10); //键盘消抖
if(k1==0)
{
TR0=0; //关定时器0
v=0; //标志位v赋0,v为0时K2K3实现时间的加减功能
i++;
if(i>2)
{
v=1; //标志位v赋1,v为1时K2K3实现强制南北、强制东西、紧急、夜间功能
TR0=1; //开定时器0
i=0;
sn_num=sn_num0;//存储调节好的时间供调节返回后立即从设定好的值执行
ew_num=ew_num0;
}
switch(i) //选择显示模式
{
case 0:a=0;break;
case 1:a=1;break;
case 2:a=2;break;
default:break;
}
}
while(k1==0);
delay(10);
}
if(k2==0)
{
delay(10);
if(k2==0)
{
if(v==0)
{
if(a==1) //通行时间加加
{
sn_num0++;
if(sn_num0>99)
sn_num0=99;
}
if(a==2)
{
ew_num0++;
if(ew_num0>99)
ew_num0=99;
}
}
if(v==1) //进入禁止南北、禁止东西通行模式
{
j++;
if(j==0)
a=0;
else if(j==1)
a=3;
else if(j==2)
a=4;
else
{
a=0;
j=0;
sn_num=sn_num0;
ew_num=ew_num0;
}
}
}
while(k2==0);
delay(10);
}
if(k3==0)
{
delay(10);
if(k3==0)
{
if(v==0)
{
if(a==1) //通行时间加加
{
sn_num0--;
if(sn_num0<0)
sn_num0=0;
}
if(a==2)
{
ew_num0--;
if(ew_num0<0)
ew_num0=0;
}
}
if(v==1) //进入紧急、夜间通行模式
{
k++;
if(k==0)
a=0;
else if(k==1)
a=5;
else if(k==2)
a=6;
else
{
a=0;
k=0;
sn_num=sn_num0;
ew_num=ew_num0;
}
}
}
while(k3==0);
delay(10);
}
}
/***********************led控制函数************************/
void cotrol_led()
{
if(a==0)
{
if(b==0)
{
s_red=1;
n_red=1;
e_yellow=1; //关东西黄灯
w_yellow=1;
e_green=1; //关东西绿灯
w_green=1;
n_green=0; //开南北绿灯
s_green=0;
if(sn_num>=shu) //时间大于shu时
{
s_yellow=1; //关南北黄灯
n_yellow=1;
e_red=0; //开东西红灯
w_red=0;
}
if(sn_num
{
n_green=1; //关南北绿灯
s_green=1;
if(c==1) //南北黄灯闪烁
{
s_yellow=1;
n_yellow=1;
}
else
{
s_yellow=0;
n_yellow=0;
}
}
display(sn_num,sn_num);//显示南北通行时间
}
if(b==1)
{
e_red=1;
w_red=1;
s_yellow=1;
n_yellow=1;
n_green=1;
s_green=1;
e_green=0;
w_green=0;
if(ew_num>=5)
{
e_yellow=1;
w_yellow=1;
s_red=0;
n_red=0;
}
if(ew_num<5)
{
e_green=1;
w_green=1;
if(c==1)
{
e_yellow=1;
w_yellow=1;
}
else
{
e_yellow=0;
w_yellow=0;
}
}
display(ew_num,ew_num); //显示东西通行时间
}
}
else
{
if(a==1)
{
n_red=1; //设定时间时关闭所有灯
n_yellow=1;
n_green=1;
s_red=1;
s_yellow=1;
s_green=1;
e_red=1;
e_yellow=1;
e_green=1;
w_red=1;
w_yellow=1;
w_green=1;
display(sn_num0,sn_num0); //显示设定的南北时间
}
if(a==2)
{
n_red=1; //设定时间时关闭所有灯
n_yellow=1;
n_green=1;
s_red=1;
s_yellow=1;
s_green=1;
e_red=1;
e_yellow=1;
e_green=1;
w_red=1;
w_yellow=1;
w_green=1;
display(ew_num0,ew_num0); //显示设定的东西时间
}
if(a==3) //南北禁止模式下南北红灯亮,东西绿灯亮
{
n_red=0;
n_yellow=1;
n_green=1;
s_red=0;
s_yellow=1;
s_green=1;
e_red=1;
e_yellow=1;
e_green=0;
w_red=1;
w_yellow=1;
w_green=0;
display(sn_num,sn_num); //显示FF
}
if(a==4) //东西禁止模式下南北绿灯亮,东西红灯亮
{
n_red=1;
n_yellow=1;
n_green=0;
s_red=1;
s_yellow=1;
s_green=0;
e_red=0;
e_yellow=1;
e_green=1;
w_red=0;
w_yellow=1;
w_green=1;
display(ew_num,ew_num); //显示FF
}
if(a==5) //紧急模式下东西南北红灯亮
{
n_red=0;
n_yellow=1;
n_green=1;
s_red=0;
s_yellow=1;
s_green=1;
e_red=0;
e_yellow=1;
e_green=1;
w_red=0;
w_yellow=1;
w_green=1;
display(ew_num,ew_num); //显示FF
}
if(a==6) //夜间模式下东西南北绿灯亮
{
n_red=1;
n_yellow=1;
n_green=0;
s_red=1;
s_yellow=1;
s_green=0;
e_red=1;
e_yellow=1;
e_green=0;
w_red=1;
w_yellow=1;
w_green=0;
display(ew_num,ew_num); //显示FF
}
}
}
/***********************主函数************************/
void main()
{
sn_num=sn_num0; //赋设定好的时间
ew_num=ew_num0;
timer0_init(1); //启动定时器0
while(1) //主循环
{
keyscan(); //键盘扫描
cotrol_led(); //LED灯控制
}
}