/*===Chip:STC12C5A32S2=================================*/
/*===Software:Keil 4 C51===================================*/
/*===Author:梁鵬=========================================*/
/*===Organization:廣西民族大學物電學院07自動化=======================*/
/*===Date:2010年05月26日=================================*/
/*===Version:1.0=========================================*/
/*===聲明:本程序?qū)僭瓌?chuàng)作品,僅供學習交流,不得用于商業(yè)用途,如需
轉(zhuǎn)載,請注明出處,謝謝合作!==============================*/
///*----------文件名: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; //調(diào)整時間的模式按鍵
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); //延時子函數(shù)
void init(); //程序定時中斷外部中斷初始化
void system_on(); //系統(tǒng)上電,兩只黃燈閃爍3秒的子函數(shù)
void display_lcd(); //LCD顯示子函數(shù)
void display_light(); //LED燈的顯示
void judge(); //各狀態(tài)切換的判斷函數(shù)
void yellow_light(); //黃燈閃爍3秒的子函數(shù)
void GoStraight(); //直行通路的子函數(shù)
void TurnLeft(); //左拐通路的子函數(shù)
//===========================
bit direction; //0->南北方向;1->東西方向;
bit flash_flags; //閃爍狀態(tài)變量
bit change_flags; //計時結(jié)束變量
bit Lock_flags; //0->交通不封鎖;1->交通封鎖
uint ovf_cnt; //定時中斷計數(shù)變量
uchar mode_flags; //按鍵改變變量
uchar run_flags; //運行時的狀態(tài)變量
uchar time_temp; //計時時間緩存
uchar north_green_time=10;//南北直行綠燈時間初始化
uchar east_green_time=10; //東西直行綠燈時間初始化
/*左轉(zhuǎn)綠燈時間與通行綠燈時間相等*/
/*-紅燈時間為綠燈時間加黃燈時間-*/
/*------黃燈時時間固定為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(); //兩只黃燈閃爍子函數(shù)
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下降沿觸發(fā)
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);//首次計時未完成不改變狀態(tài)
}
//===========================
void display_lcd()
{
if((!mode_flags)&&(!Lock_flags)){//正常顯示狀態(tài)
switch(run_flags){
case 0:case 2:case 4:case 6:case 8: //黃燈閃爍狀態(tài)
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: //直行狀態(tài)
if(!direction) {LCD_str(1,1,"North GoStraight");}
else {LCD_str(1,1,"East GoStraight");}
break;
case 3:case 7: //左拐狀態(tài)
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)){//更改南北直通時間狀態(tài)
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)){//更改東西直通時間狀態(tài)
LCD_str(1,1,"East Green Time");
LCD_str(2,6,"To: ");
LCD_int_(east_green_time);
LCD_str_("S ");
}
if(!Lock_flags){/*當前狀態(tài)剩余時間的顯示*/
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狀態(tài)決定燈的亮滅*/
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() /*黃燈閃爍的子函數(shù)*/
{
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(){ /*直行通路的子函數(shù)*/
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() /*左轉(zhuǎn)通路的子函數(shù)*/
{
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() /*狀態(tài)切換判斷函數(shù)*/
{
if(change_flags){ //狀態(tài)計時結(jié)束標志
change_flags=0; //狀態(tài)標志清零
run_flags++; //狀態(tài)切換
if((run_flags==5)||(run_flags==9))direction=~direction;
switch(run_flags){ //狀態(tài)時間賦值
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 /*按鍵掃描子函數(shù)*/
{
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;
}
/*還可以在此處添加狀態(tài),用以改變左拐通行時間*/
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++);
}
本設(shè)計的源文件與hex文件下載:
http://m.raoushi.com/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的數(shù)據(jù)口
#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的初始化函數(shù),在使用1602之前都必須調(diào)用
void Locate(uchar,uchar); //顯示定位函數(shù)
void LCD_half(uchar); //送半字節(jié)函數(shù)
void LCD_char(uchar); //寫一個字符函數(shù)
void LCD_cmd(uchar); //寫命令函數(shù)
void LCD_int_(int); //寫整型數(shù)據(jù)函數(shù)
void LCD_str_(uchar str[]);//寫字符串數(shù)據(jù)函數(shù)
void LCD_delay(uint); //延時子函數(shù)
/******************************************/
/*-函數(shù)功能:液晶使用初始化---------------*/
/*-入口參數(shù):無*/
/******************************************/
void LCD_init()
{
LCD_cmd(0x01);
LCD_delay(10);
LCD_cmd(0x28); //4位數(shù)據(jù)、雙行顯示、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);
}
/******************************************/
/*-函數(shù)功能:顯示數(shù)據(jù)定位函數(shù)-------------*/
/*-入口參數(shù):行坐標x、列坐標y-------------*/
/******************************************/
void Locate(uchar x,uchar y)
{
x&=0x01;
LCD_cmd((x==0)?(y+0xbf):(y+0x7f));
}
/******************************************/
/*-函數(shù)功能:送半字節(jié)函數(shù)-----------------*/
/*-入口參數(shù):要寫到液晶指令或數(shù)據(jù)寄存器的-*/
/* 字節(jié)的高四位或低四位---------*/
/******************************************/
void LCD_half(uchar dataw_)
{
LCM_DATA=(LCM_DATA&0x0f)|(dataw_);
LCM_EN_1;_nop_();_nop_();_nop_();
LCM_EN_0;
LCD_delay(1);//實際使用中加上10ms的延時
}
/******************************************/
/*-函數(shù)功能:寫一位數(shù)據(jù)函數(shù)---------------*/
/*-入口參數(shù):數(shù)據(jù)內(nèi)容---------------------*/
/******************************************/
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);//循環(huán)結(jié)束后,counter的值比數(shù)長多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
