微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 交通灯程序

交通灯程序

时间:10-02 整理:3721RD 点击:
#include <reg52.h>#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;                        //按键状态 sbit R_ew=P0^0;                          //东西向灯sbit Y_ew=P0^1;sbit G_ew=P0^2;sbit R_sn=P0^3;                          //南北向灯sbit Y_sn=P0^4;sbit G_sn=P0^5;sbit dula=P0^6;                        //U2:74HC573 数码管段选sbit wela=P0^7;                    //U3:74HC573 数码管位选//sbit lcdrs=P2^0;//sbit lcden=P2^2;sbit SCK=P2^0;                        //SCK:74HC595 数据输入时钟线,11管脚sbit SDI=P2^1;                        //SDI:74HC595 数据线,14管脚sbit RCK=P2^2;                        //RCK:74HC595 输出存储器锁存时钟线,12管脚sbit beep=P2^3;                        //蜂鸣器sbit 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;                                }

程序可否发给我看看,学习学习,540775523@qq.com

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top