#include<reg51.h> /*对单片机的口进行了定义********/
#define uchar unsigned char /*定义字符串类型为无符号型*/
uchar code a[10]={0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,0x80,0x90}; /*段码组合,P0口,低有效*/
uchar code b[4]={0x02,0x01,0x08,0x04}; /****P2口,低有效*/
uchar code c[5]={0xDE,0xEE,0xF3,0xF5,0xF6}; /****P0口.低有效*/
char SN=40,WE=25; /*SN表示南北方向--主干道,WE表示东西方向--支干道*/
char SN_G=25,WE_G=20,Y=5; /*SN_G表示南北方向的绿灯,WE_G表示东西方向的绿灯,Y表示黄灯*/
uchar i,k=0,count=0,J; /*定义无符号字符串变量*/
void delay(uchar t);/*定义函数*/
void light(); /*定义函数*/
void led(); /*定义函数*/
void ledthrough();/*定义函数*/
void leddrive(); /*定义函数*/
sbit K0=P3^7;/*开关K0接P3^7管脚*/
sbit K1=P3^6;/*开关K1接P3^6管脚*/
sbit K2=P3^3;/*开关K2接P3^3管脚*/
sbit K3=P3^5;/*开关K3接P3^5管脚*/
sbit K4=P3^2;/*开关K4接P3^2管脚*/
/*程序初始化*/
void init(void)
{
/*晶振频率12MHz */
TMOD=0x01; /**计数器用模式1,为16位计数器*****/
TH1=(65536-50000)/256; /*0x3C*/
TL1=(65536-50000)%256; /*0xB0*//*计50000个数,用时50ms*/
IT0=1;/*外部中断为低电平触发方式*/
ET0=1;/*允许T0中断*/
TR0=1;/*启动计数器*/
EA=1;/*CPU开放总中断*/
EX0=1;/*允许外部中断0中断,即允许响应端口P3^2(K4)中断*/
EX1=1;/*允许外部中断1中断,即允许响应端口P3^3(K2)中断*/
}
/*中断0处理程序*/
void int0(void) interrupt 0
{
EA=0;/*CPU禁止响应一切中断*/
P0=0xF6;/*东西南北方向均红灯亮*/
TR0=!TR0;/*计数器停止工作*/
for(;;)/*无条件循环*/
{
ledthrough(); /*调用通行时间显示函数*/
/*设置南北方向通行时间*/
if(K0==0) /*P3^7=0*/
{
delay(10);/*延时,把抖动的时间抛掉*/
if(K0==0)
{
while(!K0)/*当松开K0开关时,跳出循环,执行后面的程序*/
{
ledthrough(); /*调用通行时间显示函数*/
}
SN_G++;/*南北方向绿灯时间+1*/
if((SN_G+Y)==100)/*南北方向通行时间(绿灯加黄灯时间)为100s*/
SN_G=1;/*由于使用的是两位数码管,当南北方向通行时间加到100后绿灯时间归1*/
}
}
/*设置东西方向通行时间*/
if(K1==0) /*P3^6=0*/
{
delay(10);/*延时,把抖动的时间抛掉*/
if(K1==0)
{
while(!K1)/*当松开K1开关时,跳出循环,执行后面的程序*/
{
ledthrough(); /*调用通行时间显示函数*/
}
WE_G++;/*东西方向绿灯时间+1*/
if((WE_G+Y)==100)/*东西方向通行时间(绿灯加黄灯时间)为100s*/
WE_G=1;/*由于使用的是两位数码管,当东西方向通行时间加到100后绿灯时间归1*/
}
}
/*返回*/
if(K3==0) /*P3^5=0*/
{
delay(10);/*延时,把抖动的时间抛掉*/
if(K3==0)
{
while(!K3)/*当松开K3开关时,跳出循环,执行后面的程序*/
{
ledthrough(); /*调用通行时间显示函数*/
}
TR0=!TR0;/*启动计数器*/
EA=1; /*CPU开放总中断*/
break;/*跳出*/
}
}
}
}
/*中断1处理程序*/
void int1(void) interrupt 2
{
SN=15;
WE=15;
led();
k=4;
light();
}
/*键盘程序*/
void key()
{
/*南北有车而东西无车*/
if(K0==0) /*K0=0*/
{
delay(10);/*延时,把抖动的时间抛掉*/
if(K0==0)
{
while(!K0)/*当松开K0开关时,跳出循环,执行后面的程序*/
{
light();/*调用交通灯函数*/
led(); /*调用数码管函数*/
}
count=0;/*清零*/
k=0;/*南北方向通车,东西方向不通车*/
SN=15,WE=15;/*南北方向显示时间为南北方向绿灯通行时间,东西方向显示时间为南北方向绿灯通行时间加黄灯闪亮时间*/
}
}
/*南北无车而东西有车*/
if(K1==0) /*K1=0*/
{
delay(10);/*延时,把抖动的时间抛掉*/
if(K1==0)
{
while(!K1)/*当松开K1开关时,跳出循环,执行后面的程序*/
{
light();/*调用交通灯函数*/
led(); /*调用数码管函数*/
}
count=0;/*清零*/
k=2;/*南北方向不通车,东西方向通车*/
SN=15,WE=15;/*南北方向显示时间为东西方向绿灯通行时间加黄灯闪亮时间,东西方向显示时间为东西方向绿灯通行时间*/
}
}
}
/*定时函数0*/
void time0(void) interrupt 1
{
TH1=0x3c;
TL1=0xb0;/*计50000个数,用时50ms*/
count++; /*自增运算*/
if(count>=20)/*当count大于或等于20时,历时1s,执行程序*/
{
SN--;/*自减运算*/
WE--;/*自减运算*/
count=0;/*清零*/
if(SN==0||WE==0)/*当SN=0或者WE=0时,执行程序*/
{
k++;/*自增运算*/
if(k>3)/*当k>3时,执行程序*/
k=0;/*清零*/
switch(k)/*switch 语句*/
{
case 0:SN=SN_G,WE=SN_G+Y;break;/*南北方向显示时间为南北方向绿灯通行时间,东西方向显示时间为南北方向绿灯通行时间加黄灯闪亮时间*/
case 1:SN=Y,WE=Y;break; /*东西南北方向显示时间均为黄灯闪亮时间*/
case 2:SN=WE_G+Y,WE=WE_G;break;/*南北方向显示时间为东西方向绿灯通行时间加黄灯闪亮时间,东西方向显示时间为东西方向绿灯通行时间*/
case 3:SN=Y,WE=Y;break; /*东西南北方向显示时间均为黄灯闪亮时间*/
}
}
}
}
/*延时t毫秒*/
void delay(uchar t)
{
uchar i; /*定义无符号字符常量*/
for(t;t>0;t--) /*执行t次循环*/
{
for(i=2000;i>0;i--) /*由于时钟脉冲是12MHz,执行2000次循环的时间为1ms*/
{
}
}
}
/*交通灯函数*/
void light()
{
P0=c[k];/*交通灯对应着k的值变化*/
if(P0==c[1]&&count==0)/*当南北方向亮黄灯且count=0时,执行程序*/
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;/*延时50ms*/
P0=0xFE;/*南北方向黄灯熄灭,东西方向亮红灯*/
}
else
if(P0==c[3]&&count==0)/*当东西方向亮黄灯且count=0时,执行程序*/
{
TH1=(65536-500000)/256;
TL1=(65536-500000)%256;/*延时50ms*/
P0=0xF7;/*南北方向亮红灯,东西方向黄灯熄灭*/
}
}
/*数码管函数*/
void led()
{
P2=b[0],P1=a[SN%10];/*显示南北方向个位*/
delay(5);/*延时*/
P2=b[1],P1=a[SN/10];/*显示南北方向十位*/
delay(5);/*延时*/
P2=b[2],P1=a[WE%10];/*显示东西方向个位*/
delay(5);/*延时*/
P2=b[3],P1=a[WE/10];/*显示东西方向十位*/
delay(5); /*延时*/
}
/*通行时间显示函数*/
void ledthrough()
{
P2=b[0],P1=a[(SN_G+Y)%10];/*南北方向数码管显示可通行时间的个位*/
delay(5); /*延时*/
P2=b[1],P1=a[(SN_G+Y)/10];/*南北方向数码管显示可通行时间的十位*/
delay(5); /*延时*/
P2=b[2],P1=a[(WE_G+Y)%10];/*东西方向数码管显示可通行时间的个位*/
delay(5); /*延时*/
P2=b[3],P1=a[(WE_G+Y)/10];/*东西方向数码管显示可通行时间的十位*/
delay(5); /*延时*/
}
/*数码管驱动函数*/
void leddrive()
{
P2=b[0];/*显示南北方向个位*/
delay(5);/*延时*/
P2=b[1];/*显示南北方向十位*/
delay(5);/*延时*/
P2=b[2];/*显示东西方向个位*/
delay(5);/*延时*/
P2=b[3];/*显示东西方向十位*/
delay(5);/*延时*/
}
/*主函数*/
void main(void)
{
init();/*调用程序初始化函数*/
for(;;)/*无条件循环*/
{
key();/*调用键盘程序*/
light();/*调用交通灯函数*/
led(); /*调用数码管函数*/
}
}