源程序:
#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++;
}
|