#include #define uchar unsigned char#define uint unsigned int#define CLEARSCREEN write_lcd_com(0x01); //清屏uchar code dis[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uchar code line1[]="Traffic Light";uchar code line2[]="2013-03-28";uchar data num[4];uchar data IRCOM[4];uchar aa,key; //定时器0中断次数,键值uchar ew_r_t,sn_r_t; //东西南北红灯时间uchar ew_g_t,sn_g_t; //东西南北绿灯时间//uchar yellowtime=5; //黄灯默认值uchar sec_ew,sec_sn; //东西南北数码管显示时间uchar temp1,temp2; //特殊模式数码管显示值bit led_flag=0; //灯循环状态uchar key_flag; //按键状态 ***it R_ew=P0^0; //东西向灯***it Y_ew=P0^1;***it G_ew=P0^2;***it R_sn=P0^3; //南北向灯***it Y_sn=P0^4;***it G_sn=P0^5;***it dula=P0^6; //U2:74HC573 数码管段选***it wela=P0^7; //U3:74HC573 数码管位选//***it lcdrs=P2^0;//***it lcden=P2^2;***it SCK=P2^0; //SCK:74HC595 数据输入时钟线,11管脚***it SDI=P2^1; //SDI:74HC595 数据线,14管脚***it RCK=P2^2; //RCK:74HC595 输出存储器锁存时钟线,12管脚***it beep=P2^3; //蜂鸣器***it IRIN = P3^3; //红外接收器数据线//***************延时函数****************************void delay(uint ms){ uchar i; while(ms--) for(i=110;i>0;i--); }void delay_ms(uchar x) //x*0.14MS{ unsigned char i; while(x--) { for (i = 0; i<13; i++); }}/*//****************蜂鸣器*****************************void speaker(){ uchar i; for(i=50;i>0;i--) { delay(2); beep=~beep; } } *///**********定时器T0与INT0初始化*********************void init(){ P0=0x3F; //0x3f=0011 1111,led关闭,U2、U3关闭 P1=0x00; //无数据送入数码管 TMOD|=0x01; //定时器0,工作模式1(0000 0001) TH0=(65536-50000)/256; //定时50ms TL0=(65536-50000)%256; EX0=1; //允许INT0中断 EX1=1; //允许INT1中断 ET0=1; //允许T0中断 IP=0x02; //设置优先级,T0高于INT0 EA=1; //开总中断 IT0=1; //下降沿触发方式 IT1=1; //下降沿触发方式}/******************************************************************** LCD显示部分********************************************************************///************写入74HC595数据*************void write_595_data(uchar date){ uchar j; for(j=0;j<8;j++) { SCK=0; SDI=date&0x80; SCK=1; date<<=1; } }//**************写入LCD指令****************void write_lcd_com(uchar com){ write_595_data(com); //P0=com; SCK=0; //lcdrs=0; delay(5); RCK=1; //lcden=1; delay(5); RCK=0; //lcden=0;}//**************写入LCD数据****************void write_lcd_data(uchar dat){ write_595_data(dat); //P0=dat; SCK=1; //lcdrs=1; delay(5); RCK=1; //lcden=1; delay(5); RCK=0; //lcden=0;}//***************写字符串******************void write_lcd_STR(uchar *s){ while(*s) write_lcd_data(*s++);}//***********写增加的时间及位置************void write_lcd_sfm(uchar add,uchar date){ uchar shi,ge; shi=date/10; ge=date%10; write_lcd_com(0x80+0x40+add); //设置显示位置 write_lcd_data(0x30+shi); //送去液晶显示十位 write_lcd_data(0x30+ge); //送去液晶显示个位} //*************LCD初始化函数***************void lcd_init(){ RCK=0; //lcden=0; write_lcd_com(0x38); //显示模式设置 write_lcd_com(0x0c); //显示开及光标位置 write_lcd_com(0x06); //显示光标移动设置 write_lcd_com(0x01); //显示清屏 }/******************************************************************** 交通灯显示部分********************************************************************///**************数码管显示****************void display(){ num[0]=sec_sn/10; num[1]=sec_sn%10; num[2]=sec_ew/10; num[3]=sec_ew%10; wela=1; P1=0xfe; //送位选数据 1111 1110,南北“十位” wela=0; dula=1; P1=dis[num[0]]; //送南北向“十位”的段选数据 delay(5); P1=0x00; wela=1; P1=0xfd; //送位选数据 1111 1101,南北“个位” wela=0; P1=dis[num[1]]; //送南北向“个位”的段选数据 delay(5); P1=0x00; wela=1; P1=0xfb; //送位选数据 1111 1011,东西“十位” wela=0; P1=dis[num[2]]; //送东西向“十位”的段选数据 delay(5); P1=0x00; wela=1; P1=0xf7; //送位选数据 1111 0111,东西“个位” wela=0; P1=dis[num[3]]; //送东西向“十位”的段选数据 delay(5); P1=0x00; }//****************正常显示****************void Normal_display(){ ew_r_t=sn_g_t+5; //东西红灯=南北绿灯+5 sn_r_t=ew_g_t+5; //南北红灯=东西绿灯+5 sec_ew=ew_r_t; //此时东西数码管显示东西红灯时间 sec_sn=sn_g_t; //此时南北数码管显示南北绿灯时间 R_ew=0;Y_ew=1;G_ew=1; //东西红灯亮 R_sn=1;Y_sn=1;G_sn=0; //南北绿灯亮 }//****************特殊显示****************void display1() //数码管显示"88"和“--”{ dula=1; P1=temp1; delay(5); dula=0; wela=1; P1=0xf0; wela=0;}void display2() //东西数码管相同,南北数码管相同{ wela=1; P1=0xf3; //1111 0011,打开东西数码管 wela=0; dula=1; P1=temp1; //送东西数码管段选数据 delay(5); P1=0x00; wela=1; P1=0xfc; //1111 1100,打开南北数码管 wela=0; P1=temp2; //送南北数码管段选数据 delay(5); P1=0x00; }/******************************************************************** 键盘扫描及处理********************************************************************///****************键盘处理***************************void key_process(){ uchar a,b; uchar flag1,flag2; uchar dat_ew,dat_sn; if(key==0) //正常模式 { key_flag=1; ew_g_t=20; sn_g_t=15; Normal_display(); CLEARSCREEN; //清屏 write_lcd_com(0x80+0x00); write_lcd_STR("Normal:"); write_lcd_com(0x80+0x40); write_lcd_STR("EW_G ;SN_G "); write_lcd_sfm(5,ew_g_t); write_lcd_sfm(13,sn_g_t); TR0=1; } if(key==1) //紧急模式 { TR0=0; key_flag=2; CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Emergency:"); write_lcd_com(0x80+0x40); write_lcd_STR("Special through"); R_ew=0;Y_ew=1;G_ew=1; //东西红灯亮 R_sn=0;Y_sn=1;G_sn=1; //南北红灯亮 } if(key==2) //东西禁止,南北通行 { TR0=0; key_flag=3; CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Emergency:"); write_lcd_com(0x80+0x40); write_lcd_STR("EW STOP;SN PASS"); R_ew=0;Y_ew=1;G_ew=1; //东西红灯亮 R_sn=1;Y_sn=1;G_sn=0; //南北绿灯亮 } if(key==3) //南北禁止,东西通行 { TR0=0; key_flag=4; CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Emergency:"); write_lcd_com(0x80+0x40); write_lcd_STR("SN STOP;EW PASS"); R_ew=1;Y_ew=1;G_ew=0; //东西绿灯亮 R_sn=0;Y_sn=1;G_sn=1; //南北红灯亮 } if(key==4) //忙时 { key_flag=1; ew_g_t=35; sn_g_t=30; Normal_display(); CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Busy Period!"); write_lcd_com(0x80+0x40); write_lcd_STR("EW_G 35;SN_G 30"); TR0=1; } if(key==5) //夜间模式 { TR0=0; key_flag=5; CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Night Driving"); write_lcd_com(0x80+0x40); write_lcd_STR("Please Caution"); } if(flag2!=0) //确认“+时间”按下 { if(key==6) //确认“确定”键按下 { key_flag=1; if(ew_r_t||sn_r_t==0) { ew_g_t=dat_ew; sn_g_t=dat_sn; } Normal_display(); CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Make Sure:"); write_lcd_com(0x80+0x40); write_lcd_STR("EW_G ;SN_G "); write_lcd_sfm(5,dat_ew); write_lcd_sfm(13,dat_sn); flag2=0; } } if(flag1!=0||flag2!=0) //取消 { if(key==7) { key_flag=1; CLEARSCREEN; write_lcd_STR("Normmal:"); write_lcd_com(0x80+0x40); write_lcd_STR("EW_G ;SN_G "); write_lcd_sfm(5,ew_g_t); write_lcd_sfm(13,sn_g_t); flag2=0; } }//******时间调整按键******** if(key_flag==1) { if(key==8) //东西方向绿灯时间+ { key_flag=1; CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Time Adjust:"); write_lcd_com(0x80+0x40); write_lcd_STR("EW_G +"); write_lcd_sfm(5,ew_g_t); flag1=1; a=b=0; dat_sn=sn_g_t; } if(key==9) //东西方向绿灯时间- { CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Time Adjust:"); write_lcd_com(0x80+0x40); write_lcd_STR("EW_G -"); write_lcd_sfm(5,ew_g_t); flag1=2; a=b=0; dat_sn=sn_g_t; } if(key==10) //南北方向绿灯时间+ { CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Time Adjust:"); write_lcd_com(0x80+0x40); write_lcd_STR("SN_G +"); write_lcd_sfm(5,sn_g_t); flag1=3; a=b=0; dat_ew=ew_g_t; } if(key==11) //南北方向绿灯时间- { CLEARSCREEN; write_lcd_com(0x80+0x00); write_lcd_STR("Time Adjust:"); write_lcd_com(0x80+0x40); write_lcd_STR("SN_G -"); write_lcd_sfm(5,sn_g_t); flag1=4; a=b=0; dat_ew=ew_g_t; } }//*******时间调整值********* if(flag1!=0) //有“调节时间”键按下 { if(flag1==1) { if(key==12) //按键12:时间+5 { a=a+5; dat_ew=ew_g_t+a+b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_ew); flag2=1; } if(key==13) //按键12:时间+10 { b=b+10; dat_ew=ew_g_t+a+b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_ew); flag2=1; } } if(flag1==2) { if(key==12) //按键12:时间+5 { a=a+5; dat_ew=ew_g_t-a-b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_ew); flag2=1; } if(key==13) //按键12:时间+10 { b=b+10; dat_ew=ew_g_t-a-b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_ew); flag2=1; } } //如果是按下“南北方向绿灯时间+” if(flag1==3) { if(key==12) //按键12:时间+5 { a=a+5; dat_sn=sn_g_t+a+b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_sn); flag2=1; } if(key==13) //按键12:时间+10 { b=b+10; dat_sn=sn_g_t+a+b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_sn); flag2=1; } } //如果是按下“东西方向绿灯时间-” if(flag1==4) { if(key==12) //按键12:时间+5 { a=a+5; dat_sn=sn_g_t-a-b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_sn); flag2=1; } if(key==13) //按键12:时间+10 { b=b+10; dat_sn=sn_g_t-a-b; write_lcd_sfm(8,a+b); write_lcd_com(0x80+0x40+10); write_lcd_data('='); write_lcd_sfm(11,dat_sn); flag2=1; } } }} /******************************************************************** start显示********************************************************************/void start(){ write_lcd_com(0x80+1); //第一行首地址 write_lcd_STR(line1); write_lcd_com(0xc0+3); //第二行首地址 write_lcd_STR(line2); R_ew=0;Y_ew=0;G_ew=0; R_sn=0;Y_sn=0;G_sn=0; temp1=0xff; //数码管全部显示“88” display1(); } /******************************************************************** 主函数********************************************************************/void main(){ init(); lcd_init(); start(); while(1) { while(key_flag==1) { display(); } while(key_flag==2) { temp1=0x40; display1(); } while(key_flag==3) //东西禁止,南北通行 { temp1=0x40; //东西数码管显示“--” temp2=0x3f; //南北数码管显示“00” display2(); } while(key_flag==4) //南北禁止,东西通行 { R_ew=1;Y_ew=1;G_ew=0; //东西绿灯亮 R_sn=0;Y_sn=1;G_sn=1; //南北红灯亮 temp1=0x3f; //东西数码管显示“00” temp2=0x40; //南北数码管显示“--” display2(); } while(key_flag==5) //夜间 { temp1=0x3f; display1(); R_ew=1;G_ew=1; R_sn=1;G_sn=1; Y_ew=~Y_ew;Y_sn=~Y_sn; delay(500); } }}/******************************************************************** 定时器0及外部中断0(INT0)部分********************************************************************///**************定时器0中断**************************void T0_time() interrupt 1{ TH0=(65536-50000)/256; TL0=(65536-50000)%256; aa++; if(aa==20) //中断20次,1s { aa=0; sec_sn--; sec_ew--; if(sec_sn==0&&sec_ew==5) sec_sn=5; if(sec_ew==0&&sec_sn==5) sec_ew=5; if(sec_ew<=5&&led_flag==0) //南北由绿灯变黄灯闪烁 { G_sn=1; Y_sn=!Y_sn; } if(sec_sn<=5&&led_flag==1) //东西由绿灯变黄灯闪烁 { G_ew=1; Y_ew=!Y_ew; } if(led_flag==0&&sec_ew==0) //东西由红灯变绿灯,南北由黄灯变红灯 { R_ew=1;Y_ew=1;G_ew=0; R_sn=0;Y_sn=1;G_sn=1; led_flag=!led_flag; //灯状态取反 sec_ew=ew_g_t; //此时东西数码管显示东西绿灯时间 sec_sn=sn_r_t; //此时南北数码管显示南北红灯时间 } if(led_flag==1&&sec_sn==0) //东西由黄灯变红灯,南北由红灯变绿灯 { R_ew=0;Y_ew=1;G_ew=1; R_sn=1;Y_sn=1;G_sn=0; led_flag=!led_flag; //灯状态取反 sec_ew=ew_r_t; //此时东西数码管显示东西红灯时间 sec_sn=sn_g_t; //此时南北数码管显示南北绿灯时间 } } } //****************INT0中断***************************void int0func(void) interrupt 0{ uchar temp; EX0=0; P2=0xf0; delay(1); temp=P2&0xf0; switch(temp) { case 0x00: key=0;break; case 0x10: key=1;break; case 0x20: key=2;break; case 0x30: key=3;break; case 0x40: key=4;break; case 0x50: key=5;break; case 0x60: key=6;break; case 0x70: key=7;break; case 0x80: key=8;break; case 0x90: key=9;break; case 0xa0: key=10;break; case 0xb0: key=11;break; case 0xc0: key=12;break; case 0xd0: key=13;break; case 0xe0: key=14;break; case 0xf0: key=15;break; default: break; } key_process(); EX0=1; } //****************INT1中断***************************void int1func(void) interrupt 2{ uchar value; uchar j,k,N=0; EX1=0; delay_ms(15); if (IRIN==1) { EX1=1; return; } //确认IR信号出现 while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。 { delay_ms(1); } for (j=0;j<4;j++) //收集四组数据 { for (k=0;k<8;k++) //每组数据有8位 { while (IRIN) //等 IR 变为低电平,跳过4.5ms的前导高电平信号。 { delay_ms(1); } while (!IRIN) //等 IR 变为高电平 { delay_ms(1); } while (IRIN) //计算IR高电平时长 { delay_ms(1); N++; if (N>=30) //0.14ms计数过长自动离开。 { EX1=1; return; } } //高电平计数完毕 IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0” if (N>=8) { IRCOM[j] = IRCOM[j] | 0x80; //数据最高位补“1” } N=0; } } if(IRCOM[2]!=~IRCOM[3]) { EX1=1; return; } value=IRCOM[2]; switch(value) { case 0x45: key=0;break; case 0x46: key=1;break; case 0x47: key=2;break; case 0x44: key=3;break; case 0x40: key=4;break; case 0x43: key=5;break; case 0x09: key=6;break; //make sure case 0x16: key=7;break; //cancel case 0x15: key=8;break; case 0x07: key=9;break; case 0x0d: key=10;break; case 0x19: key=11;break; case 0x0c: key=12;break; //5s case 0x18: key=13;break; //10s default: break; } key_process(); EX1=1; }
|