源程序:
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={ //共阴极数码管码表
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0xC9,0xFF,0x40 };//设置码,测试码,不计时码
void delay(uint x);//延时函数
void display(uchar,uchar,uchar,uchar); //数码管显示函数
void scankeys(); //键盘函数
void traffic(); //交通灯函数
uchar num,num1,num2, //1南北 2东西
shi1,ge1,shi2,ge2,
value1,value2,//南北 绿灯时间 黄灯时间
value3,value4,//东西 绿灯时间 黄灯时间
count1,count2,flag1,flag2; //南北标记 东西标记 南北设置标记 东西设置标记
void main()
{
TMOD=0x01; //设置定时器0位工作模式1(M1,M0位0,1)
TH0=(65536-45872)/256; //装初值11.0592M晶振定时50ms数为45872
TL0=(65536-45872)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
/*初状态*/
value1=40; //南北 黄绿灯默认值
value2=5;
value3=60; //东西 黄绿灯默认值
value4=5;
num1=value1; //南北数码管先绿灯时间
num2=value2+value1;//东西红灯时间 20s
P1=0x41;//初始状态:东西红灯 南北绿灯 20 15
while(1){
if(num==20) //定时器1s
{
num=0;
num1--;
num2--;
traffic();
shi1=num1/10;
ge1=num1%10;
shi2=num2/10;
ge2=num2%10;
}
scankeys();
display(shi1,ge1,shi2,ge2);
}
}
/************************红绿灯主控制程序*******************
说明: 南北方向红绿灯时间: 红灯 15s 绿灯 40s 黄灯 5s
东西方向红绿灯时间: 红灯 20s 绿灯 60s 黄灯 5s
************************************************************/
void traffic()
{
if(num1==0){ //1南北
count1++; //南北标志位
if(count1==1){ //南北方向红灯15s倒计时结束,
P1=0x42; //东西方向仍为红灯,南北方向变为黄灯
num1=value2; //黄灯时间为5s
}
if(count1==2){ //南北方向黄灯5s倒计时结束,
P1=0x14; //东西方向变为绿灯,南北方向变为红灯
num1=value3+value4; //南北方法红灯时间为15s
}
if(count1==3){ //南北方向红灯15s倒计时结束,
P1=0x41; //东西方向变为红灯,南北方向变为绿灯
num1=value1; //南北方向绿灯时间15s
count1=0; //重置南北标志位
}
}
if(num2==0){ // 2东西
count2++; //东西标志位
if(count2==1){ //东西方向红灯20s倒计时结束,
P1=0x14; //东西方向变为绿灯,南北方向变为红灯
num2=value3; //东西方向绿灯时间10s
}
if(count2==2){ //东西方向绿灯10s倒计时结束,
P1=0x24; //东西方向变为黄灯,南北方向变为仍为红灯
num2=value4; //东西方向黄灯时间5s
}
if(count2==3){ //东西方向黄灯时间5s倒计时结束,
P1=0x41; //东西方向变为红灯,南北方向变为绿灯
num2=value1+value2; //东西方向红灯时间20s
count2=0; //重置东西标志位
}
}
}
/************************************数码管显示子函数********************************************/
void display(uchar shi1,uchar ge1,uchar shi2,uchar ge2)
{
uchar temp;
temp=P2;
P2=0xfe;
P0=table[shi1];
delay(5);
P2=0xfd;
P0=table[ge1];
delay(5);
P2=0xfb;
P0=table[shi2];
delay(5);
P2=0xf7;
P0=table[ge2];
delay(5);
}
/*************************************延时子函数********************************************/
void delay(uint x)
{
uint i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}
/*************************4*4矩阵键盘功能子函数********************
说明:
*******************************************************************/
void scankeys()
{
uchar temp,key;
P3=0xfe; //第一行线
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10); //按键去抖
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee: key=0; break;
case 0xde: key=1; break;
case 0xbe: key=2; break;
case 0x7e: key=3; break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
if(key==0) //按键1:
{
TR0=~TR0; //定时器取反
flag1=~flag1; //南北能够设置标志 0有效
flag2=~flag2; //东西能够设置标志
}
if(key==1&&flag1==0) //按键2:
{
TR0=0;
P1=0x44; //禁止东南西北车辆 全为红灯 可以设置
shi1=ge1=shi2=ge2=16; //数码管显示设置符号
}
if(key==2&&flag2==0) //按键3:
{
TR0=1;
num=0; //定时器初始化
P1=0x41; //重新开始初状态
num1=value1; //南北数码管绿灯时间
num2=value2+value1; //东西数码管红灯时间
shi1=num1/10;
ge1=num1%10;
shi2=num2/10;
ge2=num2%10;
}
if(key==3&&P1==0x44){ //按键4:
P1=0xff;
delay(1000);
P1=~P1;
shi1=ge1=shi2=ge2=17;
P1=0x44;
}
}
}
P3=0xfd;//第二行线
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0){
temp=P3;
switch(temp)
{
case 0xed: key=0; break;
case 0xdd: key=1; break;
case 0xbd: key=2; break;
case 0x7d: key=3; break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
if(key==0&&P1==0x44){ //按键5:
num1=value1;
if(num2!=159){ //@@@@保证交通合理,红灯最大值计时159s,绿灯不再增加
num1++;
value1=num1;
}
shi1=num1/10;
ge1=num1%10;
num2=value1+value2;//显示东西红灯时间
shi2=num2/10;
ge2=num2%10;
}
if(key==1&&P1==0x44){ //按键6:
num1=value2;
if(num2!=159)
{
num1++;
value2=num1;
}
shi1=num1/10;
ge1=num1%10;
num2=value1+value2;//显示东西红灯时间
shi2=num2/10;
ge2=num2%10;
}
if(key==2&&P1==0x44&&value1>3){ //按键7:
num1=value1;
num1--;
value1=num1;
shi1=num1/10;
ge1=num1%10;
num2=value1+value2;//显示东西红灯时间
shi2=num2/10;
ge2=num2%10;
}
if(key==3&&P1==0x44&&value2>3){ //按键8:
num1=value2;
num1--;
value2=num1;
shi1=num1/10;
ge1=num1%10;
num2=value1+value2;//显示东西红灯时间
shi2=num2/10;
ge2=num2%10;
}
}
}
////||||||||||||||||||
P3=0xfb;//第三行线
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0){
temp=P3;
switch(temp)
{
case 0xeb: key=0; break;
case 0xdb: key=1; break;
case 0xbb: key=2; break;
case 0x7b: key=3; break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
if(key==0&&P1==0x44){ //按键9:
num2=value3;
if(num1!=159){
num2++;
value3=num2;
}
shi2=num2/10;
ge2=num2%10;
num1=value3+value4;//显示南北红灯时间
shi1=num1/10;
ge1=num1%10;
}
if(key==1&&P1==0x44){ //按键10:
num2=value4;
if(num1!=159){
num2++;
value4=num2;
}
shi2=num2/10;
ge2=num2%10;
num1=value3+value4;//显示南北红灯时间
shi1=num1/10;
ge1=num1%10;
}
if(key==2&&P1==0x44&&value3>3){ //按键11:
num2=value3;
num2--;
value3=num2;
shi2=num2/10;
ge2=num2%10;
num1=value3+value4;//显示南北红灯时间
shi1=num1/10;
ge1=num1%10;
}
if(key==3&&P1==0x44&&value4>3){ //按键12:
num2=value4;
num2--;
value4=num2;
shi2=num2/10;
ge2=num2%10;
num1=value3+value4;//显示南北红灯时间
shi1=num1/10;
ge1=num1%10;
}
}
}
P3=0xf7;//第四行线 2未用
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0){
temp=P3;
switch(temp)
{
case 0xe7:
key=0;
break;
case 0xd7:
key=1;
break;
case 0xb7:
key=2;
break;
case 0x77:
key=3;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
if(key==0&&P1==0x44){ //按键13:
P1=0x41;
shi1=ge1=shi2=ge2=18;
}
if(key==1&&P1==0x44){ //按键14:
P1=0x14;
shi1=ge1=shi2=ge2=18;
}
if(key==2&&P1==0x44){//按键15:
}
if(key==3&&P1==0x44){//按键16:
}
}
}
}
/************************定时器T0 中断子程序*********************************/
void T0_time() interrupt 1
{
TH0=(65536-45872)/256; //定时50ms
TL0=(65536-45872)%256;
num++;
}
|