评论区有工程文件,自取
设计目标:
1、东西方向、南北方向均有红、黄、绿三种信号灯,初始红灯30秒,黄灯闪烁3秒,绿灯30秒,东西方向红灯时刻,南北方向绿灯,南北方向绿灯,东西方向红灯。
2、按键调节与控制功能,通过按键,可以控制某一个方向长时间绿灯,另一个方向长时间红灯;通过按键可以调整某一个方向的红灯时长,比如调整东西方向红灯40秒,绿灯20秒,于此同时,南北方向红灯20秒,绿灯40秒。
3、夜间模式按钮按下,所有方向显示黄灯闪烁。
4、实时提醒灯亮的剩余时间。
设计内容:
(1)我们将东西南北四个方向的led红绿灯分为两组(东西和南北)接到51单片机的P2口,利用P2口上引脚的高低电平对led灯的 亮灭实现控制
(2)我们的数码管采用动态显示的方式,将数码管串联(除了引脚5,10控制为分为两组)接入到P0引脚,用数码管的控制位(即5,10引脚)对数码管实现片选,分别给数码管的个位和十位送不同的数字,快速显示,实现动态显示的功能。
(3)我们使用了单片机的四个中断,包括外部中断0,定时/计数器中断0,外部中断1,定时/计数器中断1。定时计数器中断0主要实现计数功能,定时计数器中断0主要实现夜间模式功能。两个外部中断,实现仅限东西通行或者仅限南北通行。采用了6个按键实现加减,模式转换,确定,东西同行,南北通行。
#include<reg51.h>
char count0,count1;//定时器0中断次数
sbit green_nb=P2^0;
sbit yellow_nb=P2^1;
sbit red_nb=P2^2;
sbit green_dx=P2^5;
sbit yellow_dx=P2^6;
sbit red_dx=P2^7;
sbit k1=P3^4;
sbit k2=P3^5;
sbit k3=P3^6;
sbit k4=P3^7;
int jia=0;
int z1=0;
int z2=0;
char m=0; //模式
int dx_nb=0; //东西南北控制位
int shan=0; //闪烁标志位
char sec_dx=27; //东西数默认
char sec_nb=27; //南北默认值
int nb_time=27;
int dx_time=27;
char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极数模
void delay(int ms) //延时程序
{
int j,k;
for(j=0;j<ms;j++) //延时ms
for(k=0;k<124;k++); //大约1毫秒的延时
}
void gua1() interrupt 1 //定时中断程序
{
count0++; //软件计数加1
if(count0==10) //加到10也就是半秒
{
if((sec_nb<=3)&&(dx_nb==0)&&(shan==1)) //东西黄灯闪
{
green_dx=0;
yellow_dx=0;
}
if((sec_dx<=3)&&(dx_nb==1)&&(shan==1)) //南北黄灯闪
{
green_nb=0;
yellow_nb=0;
}
}
if(count0==20) // 定时器中断次数=20时(即1秒时)
{ count0=0; //清零计数器
sec_dx--; //东西时间减1
sec_nb--; //南北时间减1
if((sec_nb<=3)&&(dx_nb==0)&&(shan==1)) //东西黄灯闪
{
green_dx=0;
yellow_dx=1;
}
if((sec_dx<=3)&&(dx_nb==1)&&(shan==1)) //南北黄灯闪
{
green_nb=0;
yellow_nb=1;
}
if(sec_dx==0&&sec_nb==3) //当东西倒计时到0时,重置3秒,用于黄灯闪烁时间
{
sec_dx=3;
shan=1;
}
if(sec_nb==0&&sec_dx==3) //当南北倒计时到0时,重置3秒,用于黄灯闪烁时间
{
sec_nb=3;
shan=1;
}
if((dx_nb==0)&&(sec_nb==0)&&(shan==1)) //当黄灯闪烁时间倒计时到0时,
{
P2=0x00; //重置东西南背方向的红绿灯
green_nb=1;
red_dx=1;
dx_nb=!dx_nb;
shan=0;
sec_nb=27+jia; //重赋南北方向的起始值
sec_dx=sec_nb+3; //重赋东西方向的起始值
}
if((dx_nb==1)&&(sec_dx==0)&&(shan==1)) //当黄灯闪烁时间到
{
P2=0X00; //重置东西南北的红绿灯状态
green_dx=1; //东西绿灯亮
red_nb=1; //南北红灯亮
dx_nb=!dx_nb; //取反
shan=0; //闪烁
sec_dx=27+jia; //重赋东西方向的起始值
sec_nb=sec_dx+3; //重赋南北方向的起始值
}
}
TH0=0X3C; //重赋初值
TL0=0XB0; //12m晶振50ms//重赋初值
}
void gua2() interrupt 3 //定时中断程序夜间模式
{
TH1=0X3C; //重赋初值
TL1=0XB0; //12m晶振50ms//重赋初值
count1++; //软件计数加1
if(count1==10) // 定时器中断次数=10时(即0.5秒)
{
yellow_nb=1; //南北黄灯亮
yellow_dx=1; //东西黄灯亮
}
else if(count1==20) // 定时器中断次数=20时(即1秒时)
{ count1=0; //清零计数器
yellow_nb=0; //南北黄灯灭
yellow_dx=0; //东西黄灯灭
}
}
//外部中断0
void gua3() interrupt 0 //只允许东西通行
{
z1=1;
m=-1;
TR0=0; //关定时器0
TR1=0; //关定时器1
P2=0x00; //灭显示
green_dx=1; //东西方向置绿灯
red_nb=1; //南北方向为红灯
sec_dx=00; //四个方向的时间都为00
sec_nb=00;
}
//外部中断1
void gua4() interrupt 2 //只允许南北通行
{
z2=1;
m=-1;
TR0=0; //关定时器0
TR1=0; //关定时器1
P2=0x00; //灭显示
green_nb=1; //置南北方向为绿灯
red_dx=1; //东西方向为红灯
sec_nb=00; //四个方向的时间都为00
sec_dx=00;
}
void gua(void) //显示程序
{
P1=0xff; // 初始灯为灭的
P0=0x00; 灭显示
P1=0xfe; //片选数码管1的十位
P0=table[sec_dx/10]; //送东西时间十位的数码管编码
delay(1); //延时
P1=0xff; //关显示
P0=0x00; //灭显示
P1=0xfd; //片选数码管1
P0=table[sec_dx%10]; //送东西时间个位的数码管编码
delay(1); //延时
P1=0xff; //关显示
P0=0x00; //关显示
P1=0Xfb; //片选数码管2的十位
P0=table[sec_nb/10]; //送南北时间十位的数码管编码
delay(1); //延时
P1=0xff; //关显示
P0=0x00; //关显示
P1=0Xf7; //片选数码管2
P0=table[sec_nb%10]; //送南北时间个位的数码管编码
delay(1); //延时
}
void zhuanhuan(void)
{
if(k1==0){
delay(10); // 消抖
if(k1==0){
m++;
if(m==3||z1==1||z2==1){
z1=z2=0;
P2=0x00;
delay(1);
P2=0X24; // 开始默认状态,南北绿灯,东西红灯
sec_dx=27+jia;
sec_nb=sec_dx+3; //默认南北通行时间比东西多3秒
m=0;}
while(k1==0);
}
}
}
void moshi()
{
if(m==0&&z1==0&&z2==0){
TR0=1; //启动T0
TR1=0; //关闭T1
gua();
}
if(m==1&&sec_dx!=0){ //夜间模式
P2=0x00;
TR0=0; //关定时器T0
TR1=1; //开定时器T1
sec_dx=00; //四个方向的时间都为00
sec_nb=00;
gua(); //调用显示,用于延时
}
if(m==1&&sec_dx==0)
gua();
if(z1==1||z2==1)
gua();
if(m==2){
TR0=0; //关定时器T0
TR1=1; //开定时器T1
sec_dx=27+jia;
sec_nb=sec_dx+3; //默认南北通行时间比东西多3秒
gua();
if(k2==0){
delay(10); // 消抖
if(k2==0){
jia++;
while(k2==0);
}}
if(k3==0){
delay(10); // 消抖
if(k3==0){
jia--;
while(k3==0);
}}
if(k4==0)
{
P2=0X00;
delay(10);
P2=0X24;
m=0;
} }}
main(){
TMOD=0X11; //T0方式1
TH0=0X3C; //重赋初值
TL0=0XB0; //12m晶振50ms//重赋初值
TH1=0X3C;
TL1=0XB0;
IT0=1;
IT1=1;
IE=0X8F; //开中断
P2=0X24; // 开始默认状态,南北绿灯,东西红灯
sec_nb=sec_dx+3; //默认南北通行时间比东西多3秒
while(1){
zhuanhuan();
moshi();
}
}