找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5633|回复: 0
收起左侧

基于51单片机的智能交通灯

[复制链接]
ID:153791 发表于 2017-4-11 21:17 | 显示全部楼层 |阅读模式
#include <reg52.h>                  //调用单片机头文件
#define uchar unsigned char   //宏定义"uchar"代替"unsigned char"。
#define uint  unsigned int          //宏定义"uint"用来定义无符号整型数。


//数码管段选定义共阳极  给0点亮        ,给1熄灭                       
uchar code smg_du[17] = {
                          0xc0,                //0                1100 0000
                          0xf9,                //1
                          0xa4,                //2
                          0xb0,                //3
                          0x99,                //4
                          0x92,                //5
                          0x82,                //6
                          0xf8,                //7
                          0x80,                //8
                          0x90,                //9
                          0x88,                //A
                          0x83,                //b
                          0xc6,                //C
                          0xa1,                //d
                          0x86,                //E
                          0x8e                //F
                      };               
uchar dis_smg[4 ] = {0xc0,0xf5,0x8c,0x94};
//数码管位选定义
sbit smg_we1 = P2^0;                //东西数码管2
sbit smg_we2 = P2^1;                        //东西数码管1
sbit smg_we3 = P2^3;                        //南北数码管2
sbit smg_we4 = P2^2;                        //南北数码管1
//红绿灯位选定义
sbit nb_red    = P1^0;                    //南北红灯
sbit nb_green  = P1^2;                    //南北绿灯
sbit nb_yellow = P1^1;                      //南北黄灯
       
sbit dx_red    = P1^3;                //东西红灯
sbit dx_green  = P1^5;                    //东西绿灯
sbit dx_yellow = P1^4;                    //东西黄灯


bit flag = 1;                        //进入南北方向切换的标志位
bit flag_dx_nb;                                 //东西南北模式标志位
bit flag_500ms;
uchar time1;                       
uchar nb_time = 30,dx_time = 20;   //东西、南北的时间
uchar jdgz ;               //交通管制
uchar djs= 0;                        //东西 南北 倒计时变量


//交换一个字节的位置用于数码管显示
#define LED_a                6        //数码管段选的a段接在段选IO口的第0位
#define LED_b                5
#define LED_c                0
#define LED_d                2
#define LED_e                1
#define LED_f                4
#define LED_g                3
#define LED_dp            7


  uchar ChangeFor( uchar dat)
{
         uchar temp=0;
        if(dat&0x01)                   //判断数据的第一位是否为1
                temp|=0x01<<LED_a; //如果为1,放到控制数码管a段的位置        ( &按位与,1&1=1 ,1&0=0 )
        if(dat&0x02)
                temp|=0x01<<LED_b;
        if(dat&0x04)
                temp|=0x01<<LED_c;
        if(dat&0x08)
                temp|=0x01<<LED_d;
        if(dat&0x10)
                temp|=0x01<<LED_e;
        if(dat&0x20)
                temp|=0x01<<LED_f;
        if(dat&0x40)
                temp|=0x01<<LED_g;
        if(dat&0x80)
                temp|=0x01<<LED_dp;
        return temp;
}
//数码位选函数 ,选择哪一个数码管亮
//i:        0,东西数码管2
//                1,东西数码管1
//                2,南北数码管1
//                3,南北数码管2
void smg_we_switch(uchar i)
{
        switch(i)
        {
                case 0: smg_we1 = 0;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 1; break;
                case 1: smg_we1 = 1;  smg_we2 = 0; smg_we3 = 1;  smg_we4 = 1; break;
                case 2: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 0;  smg_we4 = 1; break;
                case 3: smg_we1 = 1;  smg_we2 = 1; smg_we3 = 1;  smg_we4 = 0; break;
        }       
}
//延时函数1ms
void delay_1ms(uint q)
{
        uint i,j;
        for(i=0;i<q;i++)
                for(j=0;j<110;j++);
}
//数码管显示
void DisplayScan()
{
       uchar i;
        {
          {               
                 P0 = 0xff;                         //消隐 ,避免出现乱码
             smg_we_switch(i);               //位选           选择哪一个数码管亮
             P0 =ChangeFor(dis_smg);         //段选           选择哪一段数码管亮
                   delay_1ms(3);                                 //延时3ms
          }
                i++;
                if(i>3)
                        i=0;
        }
}
//定时器0初始化
void time0_init()          
{
        TMOD = 0x01;                  //设置定时器0为工作模式1 (16-bit)
        TL0 = (65536-50000)%256;      //给定时器低位赋初始值        65536-15536=50000us=50ms
        TH0 = (65536-50000)/256;      //给定时器高位赋初始值
        TR0 = 1;                      //开启定时器0
        ET0 = 1;                      //允许定时器0中断
        EA =  1;                       //开启全局中断
}
//交通灯处理函数
void jiaotongdeng()
{
        if(flag == 1)                 //如果标志位为1
        {
                flag = 0;                       //清零标志位
                if(        djs == 0)             //倒计时变量
                {
                        if(flag_dx_nb == 1)
                        djs = nb_time;              //南北时间
                        else
                                djs= dx_time;          //东西时间
                        flag_dx_nb = ~flag_dx_nb; //切换南北时间
                }
                        djs--;
        }
        if(flag_dx_nb == 0)  //南北显示
        {       
                if(        djs > 3)
                {
                        dis_smg[2] = smg_du[(djs-3)%10] ;              //南北数码管2亮
                        dis_smg[3] = smg_du[(djs-3)/10] ;              //南北数码管1亮
                        dis_smg[0] = smg_du[djs%10] ;          //东西数码管2亮
                        dis_smg[1] = smg_du[djs/10] ;          //东西数码管1亮


                        dx_red    = 0;  //亮
                        dx_yellow = 1;        //灭
                        nb_green  =        0;        //亮
                        nb_yellow = 1;        //灭
                        dx_green  =        1;        //灭
                        nb_red    = 1;  //灭
                        time1 = 0    ;
                }else if(djs<= 3)                 //当小于3秒时  黄灯要闪了
                {
                        dis_smg[0] = smg_du[djs%10] ;
                        dis_smg[1] = smg_du[djs/10] ;
                        dis_smg[2] = smg_du[djs%10] ;
                        dis_smg[3] = smg_du[djs/10] ;


                        dx_red    = 0;    //灭
                        dx_green  =        1;          //灭
                        nb_green  =        1;          //亮
                        nb_red    = 1;    //灭
                        dx_yellow = 1;    //亮       
                        if(flag_500ms==0)       
                        {       
                           nb_yellow = 0;          //灭
                        }
                        else  
                         {
                           nb_yellow = 1;          //灭       
                         }               
                }
        }
        if(flag_dx_nb ==1)       //东西显示          
        {       
                if(        djs > 3)
                {
                        dis_smg[0] = smg_du[(djs-3)%10] ;                 //        东西数码管2亮
                        dis_smg[1] = smg_du[(djs-3)/10] ;                 //        东西数码管1亮
                        dis_smg[2] = smg_du[djs%10] ;         //        南北数码管2亮
                        dis_smg[3] = smg_du[djs/10] ;         //        南北数码管1亮


                        dx_red    = 1;     //灭
                        nb_green  =        1;           //灭
                        nb_yellow = 1;           //灭
                        dx_green  =        0;           //亮
                        dx_yellow = 1;           //灭
                        nb_red    = 0;     //亮       
                        time1 = 0    ;
                }else if(        djs <= 3)                 //当小于3秒时  黄灯要闪了
                {
                        dis_smg[0] = smg_du[djs%10] ;
                        dis_smg[1] = smg_du[djs/10] ;
                        dis_smg[2] = smg_du[djs%10] ;
                        dis_smg[3] = smg_du[djs/10] ;


                        dx_red    = 1;     //灭
                        dx_green  =        1;           //亮
                        nb_red    = 0;     //灭
                        nb_green  =        1;           //灭
                        nb_yellow = 1;           //亮       
                        if(flag_500ms==0)       
                        {       
                                   dx_yellow = 0;           //灭          
                        }
                        else  
                         {
                                   dx_yellow = 1;           //灭                 
                         }                               
                }
          }                       
}                 
//按键位定义
sbit Key1=P1^6;                                 //定时70s
sbit Key2=P1^7;                                 //定时60s
sbit Key3=P3^2;                                 //定时50s
sbit Key4=P3^3;                                 //交通管制键
//  该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
uchar Key_Scan()
{         
        static  uchar key_up=1;       //按键按松开标志
        if(key_up&&(Key1==0||Key2==0||Key3==0||Key4==0))
        {
                delay_1ms(10);            //去抖动
                key_up=0;
                if(Key1==0)                        return 1;
                else if(Key2==0)    return 2;
                else if(Key3==0)    return 3;
                else if(Key4==0)    return 4;
        }
        else if(Key1==1&&Key2==1&&Key3==1&&Key4==1)
                key_up=1;             
        return 0;               // 无按键按下
}


uchar key_can;                   //按键值
void key_with()                           //设置函数
{
        if(key_can == 1)
            djs= 70;       
        if(key_can == 2)       
            djs= 60;       
        if(key_can ==3)
            djs= 50;                       
    if(key_can == 4)      //交通管制按键,紧急车辆通行
        {
                jdgz ++;
                if(jdgz > 4)
                        jdgz = 0;       
                if(jdgz == 1)         //全部亮红灯,紧急车辆通行  
                 {
                        dx_red    = 0;  //亮
                        nb_red    = 0;  //亮
                        dx_green  =        1;        //灭
                        dx_yellow = 1;        //灭
                        nb_green  =        1;        //灭
                        nb_yellow = 1;        //灭                       
                  }
                  if(jdgz == 2)         //全部亮黄灯 ,夜间模式
                 {
                        dx_red    = 1;  //灭
                        nb_red    = 1;  //灭
                        dx_green  =        1;        //灭
                        dx_yellow = 0;        //亮
                        nb_green  =        1;        //灭
                        nb_yellow = 0;        //亮                       
                  }if(jdgz == 3)         // 南北绿灯,东西红灯 (南北优先通行)
                 {
                        dx_red    = 0;  //亮
                        nb_red    = 1;  //灭
                        dx_green  =        1;        //灭
                        dx_yellow = 1;        //灭
                        nb_green  =        0;        //亮
                        nb_yellow = 1;        //灭                       
                  }if(jdgz == 4)         // 东西绿灯,南北红灯(东西优先通行)   
                 {
                        dx_red    = 1;  //灭
                        nb_red    = 0;  //亮
                        dx_green  =        0;        //亮
                        dx_yellow = 1;        //灭
                        nb_green  =        1;        //灭
                        nb_yellow = 1;        //灭                       
                  }
        }
}
//主函数
void main()
{
        time0_init();                                 // 初始化
        djs=nb_time;
        while(1)
        {
                key_can=Key_Scan();                 //        按键返回值
                if(key_can )                         
                  key_with();                         //按键设置函数
       if(jdgz == 0)                         //无紧急按键按下,执行交通灯处理
                  jiaotongdeng();                 //交通灯处理
                DisplayScan();                         //数码管显示
        }
}  
//定时器0中断服务程序
void time0_int() interrupt 1  
{                                                  
    uchar time;                                  //定时中断次数
        TL0 = (65536-50000)%256;      //给定时器低位重装初始值 50ms       
        TH0 = (65536-50000)/256;      //给定时器高位重装初始值
        time ++;
        time1++;
        if(time1 % 10 == 0)
                flag_500ms = ~flag_500ms;  //500ms变换一次
        if(time == 20)                                  // 20x50=1000ms=1s
        {
                time = 0;
                flag = 1;
        }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表