/** 1、初始状态:南北绿,东西红(25s);后转为过渡状态:南北黄,东西红(5s); 再转为东西通行状态:东西绿,南北红(25s);再转为过渡状态:东西黄,南北红,然后循环往复 2、键控: 按下k1键,保持南北通行状态 按下k2键,保持东西通行状态 按下k3键,保持正常交通灯 3、具有闪烁的交通灯: 在2的基础上增加,绿灯最后5s闪烁,即亮0.5s,灭0.5s **/ #include #define uint unsigned int #define uchar unsigned char sbit key0 = P2^0; //按键位定义,k1/2/3可控 sbit key1 = P2^1; sbit key2 = P2^2; sbit key3 = P2^3; sbit sou_g = P1^2; //南绿灯位定义 sbit nor_g = P0^0; //北绿灯位定义 sbit eas_g = P0^3; //东绿灯位定义 sbit wes_g = P1^5; //西绿灯位定义 uchar flag = 0, sec = 0; //T0定时标志位 //uchar flag_key = 0; //按键检测标志 uchar flag_flash = 0; uchar flag2 = 0; //用以判断是东西还是南北的绿灯闪烁 void main() { TMOD = 0X11; //定时器0、1都设置为方式1 TH0 = (65535 - 50000) / 256; //定时器0赋初值 TL0 = (65535 - 50000) % 256; TH1 = (65535 - 50000) / 256; //定时器1赋初值 TL1 = (65535 - 50000) % 256; ET0 = 1; //允许定时器0中断 ET1 = 1; //允许定时器1中断 EA = 1; //开总中断 EX0 = 1; //允许外部中断0中断 IT0 = 1; //设置外部中断0为跳沿触发方式 P0 = 0xfc; //南北绿 P1 = 0xf3; //东西红 TR0 = 1; //开定时器0 while(1); } void int0(void) interrupt 0 //外部中断0 { if(!key0) //key0键无功能设定 { } if(!key1) //按下key1,保持南北通行状态 { TR0 = 0; //关闭定时器0,即关闭正常状态 P0 = 0xfc; //保持南北通行状态 P1 = 0xf3; } if(!key2) //按下key2,保持东西通行状态 { TR0 = 0; P0 = 0xf7; //保持东西通行状态 P1 = 0x9e; } if(!key3) //按下key3,保持正常交通灯 { flag = 0; //重新恢复正常状态,所以进行标志初始化,相当于重新开始 sec = 0;//既然是恢复正常状态,那就相当于重新开始,出于这个考虑,所有标志位恢复初始值 TH0 = (65535 - 50000) / 256; //初始化T0值 TL0 = (65535 - 50000) % 256; P0 = 0xfc; //恢复初始状态,南北绿,东西红 P1 = 0xf3; TR0 = 1; //重新打开定时器0中断 } } void t0(void) interrupt 1 { TH0 = (65535 - 50000) / 256; //方式1必须重装初值 TL0 = (65535 - 50000) % 256; flag++; //定时标志位自加 if(flag == 20) { flag = 0; sec++; //每计满1s,sec加1 /*在用switch的时候一定不要忘了break;还有就是一定要搞清楚这个语法点*/ switch(sec) { case 3: //在绿灯最后1S,打开定时器1,关设置标志flag2 flag2 = 1; TR1 = 1; break;//只要进行过任意一个处理,完毕后即跳出,不再执行后续程序 case 4: //关闭定时器1,绿灯不再闪烁 TR1 = 0; P0 = 0xfd; //过渡状态 P1 = 0x75; break; case 6: P0 = 0xf7; //东西通行状态 P1 = 0x9e; break; case 9: //在绿灯最后1S,打开定时器1,关设置标志flag2 flag2 = 2; //TH1 = (65535 - 50000) / 256; //这两句应该是要的,严谨的话 //TL1 = (65535 - 50000) % 256; flag_flash = 0; //T2计时标志清0,为了更准确 TR1 = 1; //打开定时器1 break; //万不可漏了 “break;” case 10: TR1 = 0; //关闭定时器1 P0 = 0xfb; //东西黄、南北红,过渡状态 P1 = 0xae; break; case 12: sec = 0; //sec清0,回到初始状态 P0 = 0xfc; P1 = 0xf3; break; } /*下面为第二种方式 if(sec == 4) { P0 = 0xfd; P1 = 0x75; } if(sec == 6) { P0 = 0xf7; P1 = 0x9e; } if(sec == 10) { P0 = 0xfb; P1 = 0xae; } if(sec == 12) { sec = 0; P0 = 0xfc; P1 = 0xf3; }*/ } } void t2(void) interrupt 3 { TH1 = (65535 - 50000) / 256; TL1 = (65535 - 50000) % 256; if(flag2 == 1) //如果为南北通行状态,则南北绿灯闪烁 { flag_flash++; //定时标志自加 if(flag_flash == 4) { flag_flash = 0; //标志清0 sou_g = ~sou_g; //南绿灯取反,下同 nor_g = ~nor_g; } } if(flag2 == 2) //如果为东西通行状态,则东西绿灯闪烁 { flag_flash++; if(flag_flash == 4) { flag_flash = 0; eas_g = ~eas_g; wes_g = ~wes_g; } } }