/*===Chip:STC12C5A32S2=================================*/
/*===Software:Keil 4 C51===================================*/
/*===Author:梁鵬=========================================*/
/*===Organization:廣西民族大學物電學院07自動化=======================*/
/*===Date:2010年05月26日=================================*/
/*===Version:1.0=========================================*/
/*===聲明:本程序屬原創作品,僅供學習交流,不得用于商業用途,如需
轉載,請注明出處,謝謝合作!==============================*/
///*----------文件名:Traffic_light.c-------------*/
#include<reg52.h> #include<intrins.h> #include<LCD1602.H> #define ON 0 #define OFF 1 #define yellow_time 3 //=========================== sbit MODE_KEY=P3^3; //調整時間的模式按鍵 sbit TIME_ADD=P3^4; //時間增加5s的按鍵 sbit TIME_DEC=P3^5; //時間減少5s的按鍵 sbit LOCK_KEY=P3^6; //封鎖/恢復交通按鍵 sbit North_turn_R= P0^0; //南北左拐紅燈 sbit North_turn_G= P0^1; //南北左拐綠燈 sbit North_Y = P0^2; //南北黃燈 sbit North_R = P0^3; //南北直行紅燈 sbit North_G = P1^0; //南北直行綠燈 sbit East_turn_R = P1^1; //東西左拐紅燈 sbit East_turn_G = P1^2; //東西左拐綠燈 sbit East_Y = P1^3; //東西黃燈 sbit East_R = P1^4; //東西直行紅燈 sbit East_G = P1^5; //東西直行綠燈 //=========================== void delay_ms(uint); //延時子函數 void init(); //程序定時中斷外部中斷初始化 void system_on(); //系統上電,兩只黃燈閃爍3秒的子函數 void display_lcd(); //LCD顯示子函數 void display_light(); //LED燈的顯示 void judge(); //各狀態切換的判斷函數 void yellow_light(); //黃燈閃爍3秒的子函數 void GoStraight(); //直行通路的子函數 void TurnLeft(); //左拐通路的子函數 //=========================== bit direction; //0->南北方向;1->東西方向; bit flash_flags; //閃爍狀態變量 bit change_flags; //計時結束變量 bit Lock_flags; //0->交通不封鎖;1->交通封鎖 uint ovf_cnt; //定時中斷計數變量 uchar mode_flags; //按鍵改變變量 uchar run_flags; //運行時的狀態變量 uchar time_temp; //計時時間緩存 uchar north_green_time=10;//南北直行綠燈時間初始化 uchar east_green_time=10; //東西直行綠燈時間初始化 /*左轉綠燈時間與通行綠燈時間相等*/ /*-紅燈時間為綠燈時間加黃燈時間-*/ /*------黃燈時時間固定為3秒-----*/ //uchar north_red_time; //uchar east_red_time; //uchar north_turn_time; //uchar east_turn_time; //=========================== //紅燈切換到綠燈時,黃燈不用閃爍 //綠燈切換到紅燈時,黃燈需要閃爍 //黃燈閃爍時,綠燈沒有熄滅 //紅燈時間=綠燈時間+黃燈時間 //左拐時間=直行綠燈時間 //============================================ //******************************************** void main() { init(); //定時中斷外部中斷初始化 LCD_init(); //LCD1602初始化 /*首次運行時,黃燈閃爍三秒*/ LCD_str(1,1,"System on ..."); time_temp=yellow_time; system_on(); //兩只黃燈閃爍子函數 while(1) { judge(); /*LED燈的顯示*/ display_light(); /*1602顯示*/ display_lcd(); } } //********************************************* //============================================= void init() { TMOD|=0x02; //定時器0方式2,自動重載 TH0=5;TL0=5; //250us中斷一次 ET0=1; //允許定時器0中斷 TCON|=0x01; //外部中斷0下降沿觸發 EX0=1; //允許外部中斷0 EA=1; //允許全局總中斷 TR0=1; //啟動定時器0 } //=========================== void system_on() //上電后,東西南北路口黃燈閃爍3秒 { do{ if(flash_flags) {North_Y=OFF;East_Y=OFF;} else {North_Y=ON; East_Y=ON; } }while(!change_flags);//首次計時未完成不改變狀態 } //=========================== void display_lcd() { if((!mode_flags)&&(!Lock_flags)){//正常顯示狀態 switch(run_flags){ case 0:case 2:case 4:case 6:case 8: //黃燈閃爍狀態 if(!direction){ if(flash_flags) {LCD_str(1,1," ");} else {LCD_str(1,1,"Status Change...");} }else{ if(flash_flags) {LCD_str(1,1," ");} else {LCD_str(1,1,"Status Change...");} } break; case 1:case 5: //直行狀態 if(!direction) {LCD_str(1,1,"North GoStraight");} else {LCD_str(1,1,"East GoStraight");} break; case 3:case 7: //左拐狀態 if(!direction) {LCD_str(1,1,"North Turn Left ");} else {LCD_str(1,1,"East Turn Left ");} break; } LCD_str(2,6," "); //第二行清屏 } if((mode_flags==1)&&(!Lock_flags)){//更改南北直通時間狀態 LCD_str(1,1,"North Green Time"); LCD_str(2,6,"To: "); LCD_int_(north_green_time); LCD_str_("S "); } if((mode_flags==2)&&(!Lock_flags)){//更改東西直通時間狀態 LCD_str(1,1,"East Green Time"); LCD_str(2,6,"To: "); LCD_int_(east_green_time); LCD_str_("S "); } if(!Lock_flags){/*當前狀態剩余時間的顯示*/ LCD_int(2,1,time_temp); LCD_char(' '); LCD_str(2,4,"S ") } if(Lock_flags){ //封鎖交通時顯示 if(flash_flags){ LCD_str(1,1," "); LCD_str(2,1," "); }else{ LCD_str(1,1," Please Wait... "); LCD_str(2,1," Locking... "); } } } //=========================== void display_light() { if(!Lock_flags){//交通未被封鎖時,交通燈按以下程序顯示 /*以下由run_flags狀態決定燈的亮滅*/ switch(run_flags){ case 0:case 2:case 4:case 6:case 8: yellow_light(); break; case 1:case 5: GoStraight(); break; case 3:case 7: TurnLeft(); break; default: run_flags=1; } /*紅燈的亮滅*/ if(!direction){ //南北通行時,東西綠燈全滅,紅燈全亮 East_R=ON; East_turn_R=ON; East_G=OFF; East_turn_G=OFF; East_Y=OFF; }else{ //東西通行時,南北綠燈全滅,紅燈全亮 North_R=ON; North_turn_R=ON; North_G=OFF;North_turn_G=OFF; North_Y=OFF; } }else{//封鎖交通時,所有紅燈亮 North_R=ON; North_turn_R=ON; North_G=OFF;North_turn_G=OFF; North_Y=OFF;East_Y=OFF; East_R=ON; East_turn_R=ON; East_G=OFF; East_turn_G=OFF; } } //=========================== void yellow_light() /*黃燈閃爍的子函數*/ { if(!direction){ //North_G=OFF; //南北直行綠燈滅 //North_turn_G=OFF; if(flash_flags) {North_Y=OFF;} else {North_Y=ON; } }else{ //East_G=OFF; //East_turn_G=OFF; if(flash_flags) {East_Y=OFF; } else {East_Y=ON; } } } //=========================== void GoStraight(){ /*直行通路的子函數*/ if(!direction){ North_Y=OFF; //南北黃燈滅 North_turn_R=ON; //南北左拐紅燈亮 North_R=OFF; //南北直行紅燈滅 North_G=ON; //南北直行綠燈亮 }else{ East_Y=OFF; East_turn_R=ON; East_R=OFF; East_G=ON; } } //=========================== void TurnLeft() /*左轉通路的子函數*/ { if(!direction){ North_G=OFF; //南北直行綠燈滅 North_R=ON; //南北直行紅燈亮 North_turn_R=OFF; //南北左拐紅燈滅 North_turn_G=ON; //南北左拐綠燈亮 }else{ East_G=OFF; East_R=ON; East_turn_R=OFF; East_turn_G=ON; } } //=========================== void judge() /*狀態切換判斷函數*/ { if(change_flags){ //狀態計時結束標志 change_flags=0; //狀態標志清零 run_flags++; //狀態切換 if((run_flags==5)||(run_flags==9))direction=~direction; switch(run_flags){ //狀態時間賦值 case 0:case 2:case 4:case 6:case 8: //黃燈閃爍 time_temp=yellow_time;break; case 1:time_temp=north_green_time;break;//南北直行 case 5:time_temp=east_green_time;break; //東西直行 case 3:time_temp=north_green_time;break;//南北左拐 case 7:time_temp=east_green_time;break; //東西左拐 default:run_flags=1;time_temp=north_green_time; } } } //=========================== void keys_scan() interrupt 0 /*按鍵掃描子函數*/ { delay_ms(20); if(!INT0){ if(!MODE_KEY){ if(++mode_flags>=3)mode_flags=0; } if(!TIME_ADD){ if(mode_flags==1)north_green_time+=5; if(mode_flags==2)east_green_time+=5; if(north_green_time>90)north_green_time=5; if(east_green_time>90)east_green_time=5; } if(!TIME_DEC){ if(mode_flags==1)north_green_time-=5; if(mode_flags==2)east_green_time-=5; if(north_green_time>90)north_green_time=5; if(east_green_time>90)east_green_time=5; } /*還可以在此處添加狀態,用以改變左拐通行時間*/ if(!LOCK_KEY)Lock_flags=~Lock_flags; } INT0=1; } //=========================== void T0_isr() interrupt 1 { if(ovf_cnt==1846)flash_flags=~flash_flags; if(++ovf_cnt>=3691){ ovf_cnt=0; flash_flags=~flash_flags; if(!Lock_flags)if(time_temp--==1)change_flags=1; } } //=========================== void delay_ms(uint xms) { uint i,j; for(i=0;i<xms;i++) for(j=0;j<990;j++); } 本設計的源文件與hex文件下載: http://www.zg4o1577.cn/ziliao/file/jiaotd1.rar,您的電路如果不同請自行更改端口.
/*--------------文件名:LCD1602.H----------------*/ #ifndef _LCD1602_H_ #define _LCD1602_H_ #define uint unsigned int #define uchar unsigned char #define LCM_P P2 //LCD的控制端口 #define LCM_DATA P0 //LCD的數據口 #define LCM_RS_0 LCM_P&=~(1<<5) #define LCM_RS_1 LCM_P|= 1<<5 #define LCM_RW_0 LCM_P&=~(1<<6) #define LCM_RW_1 LCM_P|= 1<<6 #define LCM_EN_0 LCM_P&=~(1<<7) #define LCM_EN_1 LCM_P|= 1<<7 /*========================================*/ #define LCD_str(x,y,s) Locate(x,y);LCD_str_(s); #define LCD_int(x,y,n) Locate(x,y);LCD_int_(n); /*========================================*/ void LCD_init(); //LCM1602的初始化函數,在使用1602之前都必須調用 void Locate(uchar,uchar); //顯示定位函數 void LCD_half(uchar); //送半字節函數 void LCD_char(uchar); //寫一個字符函數 void LCD_cmd(uchar); //寫命令函數 void LCD_int_(int); //寫整型數據函數 void LCD_str_(uchar str[]);//寫字符串數據函數 void LCD_delay(uint); //延時子函數 /******************************************/ /*-函數功能:液晶使用初始化---------------*/ /*-入口參數:無*/ /******************************************/ void LCD_init() { LCD_cmd(0x01); LCD_delay(10); LCD_cmd(0x28); //4位數據、雙行顯示、5*7(0x38為八位) LCM_EN_1;_nop_();_nop_();_nop_(); LCM_EN_0; /*此處必須加上這兩句*/ LCD_delay(10); LCD_cmd(0x28); LCD_cmd(0x06); LCD_cmd(0x0c); LCD_cmd(0x01); LCD_delay(10); } /******************************************/ /*-函數功能:顯示數據定位函數-------------*/ /*-入口參數:行坐標x、列坐標y-------------*/ /******************************************/ void Locate(uchar x,uchar y) { x&=0x01; LCD_cmd((x==0)?(y+0xbf):(y+0x7f)); } /******************************************/ /*-函數功能:送半字節函數-----------------*/ /*-入口參數:要寫到液晶指令或數據寄存器的-*/ /* 字節的高四位或低四位---------*/ /******************************************/ void LCD_half(uchar dataw_) { LCM_DATA=(LCM_DATA&0x0f)|(dataw_); LCM_EN_1;_nop_();_nop_();_nop_(); LCM_EN_0; LCD_delay(1);//實際使用中加上10ms的延時 } /******************************************/ /*-函數功能:寫一位數據函數---------------*/ /*-入口參數:數據內容---------------------*/ /******************************************/ void LCD_char(uchar dataw) { LCM_RS_1;LCM_RW_0;LCM_EN_0;_nop_(); LCD_half(dataw&0xf0); LCD_half(dataw<<4); } /*========================================*/ void LCD_cmd(uchar cmd) { LCM_RS_0;LCM_RW_0;LCM_EN_0;_nop_(); LCD_half(cmd&0xf0); LCD_half(cmd<<4); } /*========================================*/ void LCD_str_(uchar *str) { while(*str)LCD_char(*str++); } /*========================================*/ void LCD_int_(int num) { uchar counter=0,num_str[10],neg_flags=0; if(num<0){num=-num,neg_flags=1;} do{ num_str[counter++]=num%10+0x30; num/=10; }while(num!=0);//循環結束后,counter的值比數長多1 if(neg_flags){num_str[counter++]='-';} while(counter) { LCD_char(num_str[--counter]); }//counter的值必須先減一 } /*========================================*/ void LCD_delay(uint xus) { uint i=0,j=0; for(i=0;i<xus;i++) for(j=0;j<123;j++); } /*========================================*/ #endif