单片机(ISIS 7 Professional):交通灯代码项目

这一篇文章主要介绍用C语言制作一个按钮控制的多功能十字路口交通灯。

设计思路:代码有很多,因为功能很杂,有些地方有不懂的可以看我之前写的简易项目,都是分散开来然后拼接而成的,代码都标上了注释,还是希望能有点基础的再来看这篇文章,因为作者本身的基础也不是很好。

基本电路图如下:

  使用的代码如下:

#include <reg51.h>                //头文件
#define uchar unsigned char
#define uint  unsigned int        //宏定义

uchar data buf[4];                    //秒显示的变量
uchar data sec_dx=30;              //东西数默认
uchar data sec_nb=30;            //南北默认值
uchar data set_timedx=25;        //设置东西方向的时间
uchar data set_timenb=30;        //设置南北方向的时间
int n;
uchar data countt0,countt1;//定时器0中断次数
//定义6组开关
sbit  k4=P1^5;      //切换方向	
sbit  k1=P1^1;        //时间加		
sbit  k2=P1^2;        //时间减		
sbit  k3=P1^3;        //确认	
sbit  k5=P1^4;        //禁止	
sbit  k6=P1^0;        //夜间模式	


sbit Red_nb=P2^2;        //南北红灯标志
sbit Yellow_nb=P2^1;    //南北黄灯标志
sbit Green_nb=P2^0;     //南北绿灯标志

sbit Red_dx=P2^5;        //东西红灯标志
sbit Yellow_dx=P2^4;    //东西黄灯标志
sbit Green_dx=P2^3;        //东西绿灯标志

sbit green=P2^6;
sbit red=P2^7;
        
bit set=0;                //调时方向切换键标志 =1时,南北,=0时,东西
bit dx_nb=0;            //东西南北控制位
bit shanruo=0;            //闪烁标志位
bit yejian=0;            //夜间黄灯闪烁标志位

uchar code table[11]={    //共阴极字型码
    0x3f,  //--0
    0x06,  //--1
    0x5b,  //--2
    0x4f,  //--3
    0x66,  //--4
    0x6d,  //--5
    0x7d,  //--6
    0x07,  //--7
    0x7f,  //--8
    0x6f,  //--9
    0x00   //--NULL
};

//函数的声明部分
void delay(int ms);            //延时子程序
void key();                    //按键扫描子程序
void display();                //显示子程序
void logo();                   //开机LOGO
void Buzzer();
//主程序
void main()
{
    TMOD=0X11;                       //定时器设置
    TH1=0X3C;        
    TL1=0XB0;
    TH0=0X3C;                    //定时器0置初值 0.05S
    TL0=0XB0;
    EA=1;                        //开总中断
    ET0=1;                        //定时器0中断开启
    ET1=1;                       //定时器1中断开启
    TR0=1;                        //启动定时0
    TR1=0;                             //关闭定时1
    logo();                        //开机初始化
    P2=0Xc3;                    // 开始默认状态,东西绿灯,南北黄灯   
    sec_nb=sec_dx;             //默认南北通行时间比东西多5秒
    while(1)                      //主循环
    {     
        key();                     //调用按键扫描程序
        display();                 //调用显示程序
    }   
}
//函数的定义部分
void key(void)    //按键扫描子程序
{     
    if(k1!=1)                            //当K1(时间加)按下时
    {
        display();                       //调用显示,用于延时消抖
        if(k1!=1)                            //如果确定按下
        {
              TR0=0;                           //关定时器   
            shanruo=0;                    //闪烁标志位关
            P2=0x00;                    //灭显示
            TR1=0;                            //启动定时1
            if(set==0)                    //设置键按下
                set_timedx++;           //南北加1S
            else
                set_timenb++;            //东西加1S
            if(set_timenb==100)
                set_timenb=1;
            if(    set_timedx==100)
                set_timedx=1;           //加到100置1
            sec_nb=set_timenb ;         //设置的数值赋给东西南北
            sec_dx=set_timedx;            
              do
             {
                display();                 //调用显示,用于延时
            }
            while(k1!=1);             //等待按键释放
        }
    }

    if(k2!=1)                            //当K2(时间减)按键按下时
    {        
        display();                       //调用显示,用于延时消抖  
        if(k2!=1)                        //如果确定按下
        {   
             TR0=0;                         //关定时器0   
            shanruo=0;                    //闪烁标志位关
            P2=0x00;                    //灭显示
            TR1=0;                        //关定时器1   
            if(set==0)
                set_timedx--;              //南北减1S
            else
                set_timenb--;              //东西减1S
            if(set_timenb==0)
                set_timenb=99;   
            if(    set_timedx==0 )
                set_timedx=99;           //减到1重置99
            sec_nb=set_timenb ;             //设置的数值赋给东西南北
            sec_dx=set_timedx;
              do   
            {
                display();               //调用显示,用于延时
            }
            while(k2!=1);               //等待按键释放
        }
    }

    if(k3!=1)                            //当K3(确认)键按下时
    {   
        display();                       //调用显示,用于延时消抖
        if(k3!=1)                        //如果确定按下
        {
            TR0=1;                          //启动定时器0
            sec_nb=set_timenb;                //从中断回复,仍显示设置过的数值
            sec_dx=set_timedx;                //显示设置过的时间
            TR1=0;                            //关定时器1   
            if(set==0)                        //时间倒时到0时
            {
                P2=0X00;                     //灭显示	
                Green_dx=1;                        //东西绿灯亮	
                Red_nb=1;                    //南北红灯亮	
                sec_nb=sec_dx;             //回到初值	
            }
            else
            {
                P2=0x00;                    //南北绿灯,东西红灯	
                Green_nb=1;
                Red_dx=1;
                sec_dx=sec_nb;
            }
        }
    }
     
    if(k4!=1)                            //当K4(切换)键按下
    {
        display();                       //调用显示,用于延时消抖
        if(k4!=1)                        //如果确定按下
        {  
             TR0=0;                        //关定时器0   
            set=!set;                    //取反set标志位,以切换调节方向
            TR1=0;                        //关定时器1
            dx_nb=set;
            do
            {
                display();                //调用显示,用于延时
            }               
            while(k4!=1);              //等待按键释放
        }
    }   

    if(k5!=1)                            //当K5(禁止)键按下时
    {
           display();                       //调用显示,用于延时消抖
           if(k5!=1)                        //如果确定按下
           {     
            TR0=0;                        //关定时器
            P2=0x00;                    //灭显示
            Red_dx=1;
            Red_nb=1;                    //全部置红灯
            TR1=0;
            sec_dx=00;                    //四个方向的时间都为00
            sec_nb=00;
            do
            {
                display();                 //调用显示,用于延时
            }   
            while(k5!=1);            //等待按键释放   
           }
    }
    if(k6!=1)                            //当K6(夜间模式)按下
    {
           display();                       //调用显示,用于延时消抖
           if(k6!=1)                        //如果确定按下
           {     
            TR0=0;                        //关定时器
            P2=0x00;
            TR1=1;
            sec_dx=00;                    //四个方向的时间都为00
            sec_nb=00;
            do
            {
                display();               //调用显示,用于延时
            }   
            while(k6!=1);            //等待按键释放   
           }
    }
}
void display(void) //显示子程序
{        
    buf[1]=sec_nb/10;         //第1位 东西秒十位
    buf[2]=sec_nb%10;         //第2位 东西秒个位
    buf[3]=sec_dx/10;         //第3位 南北秒十位
    buf[0]=sec_dx%10;         //第4位 南北秒个位        
	P3=0xff;                  // 初始灯为灭的	
    P0=0x00;                 灭显示
    P3=0xef;                   //片选LED1
    P0=table[buf[1]];        //送东西时间十位的数码管编码            
    delay(1);                //延时
    P3=0xff;                //关显示
    P0=0x00;                //灭显示
                           
    P3=0xdf;                 //片选LED2
    P0=table[buf[2]];         //送东西时间个位的数码管编码
    delay(1);                 //延时
    P3=0xff;                //关显示
    P0=0x00;                //关显示
    P3=0Xbf;                  //片选LED3
    P0=table[buf[3]];        //送南北时间十位的数码管编码
    delay(1);                //延时
    P3=0xff;                 //关显示
    P0=0x00;                 //关显示
    P3=0X7f;                 //片选LED4   
    P0=table[buf[0]];        //送南北时间个位的数码管编码
    delay(1);                //延时
}

void time0(void) interrupt 1 using 1      //定时中断子程序
{
    TH0=0X3C;                            //重赋初值
    TL0=0XB0;                            //12m晶振50ms//重赋初值
    TR0=1;                                //重新启动定时器
    countt0++;                            //软件计数加1
    if(countt0==10)                        //加到10也就是半秒
    {
        if((sec_nb<=4)&&(shanruo==1))          //东西黄灯闪        
        {
            Green_dx=0;
            Yellow_dx=0;
        }                           
        if((sec_dx<=4)&&(shanruo==1))          //南北黄灯闪        
        {  
            Green_nb=0;
            Yellow_nb=0;
        }   
    }
        
    if(countt0==20)                          // 定时器中断次数=20时(即1秒时)
    {    countt0=0;                        //清零计数器		
        sec_dx--;                        //东西时间减1		
        sec_nb--;                        //南北时间减1	

        if((sec_nb<=4)&&(shanruo==1))          //东西黄灯闪        
        {
            Green_dx=0;
            Red_dx=0;
            Yellow_dx=1;
        }                           
        if((sec_dx<=4)&&(shanruo==1))          //南北黄灯闪        
        {  
            Green_nb=0;
            Red_nb=0;
            Yellow_nb=1;
        }                                 
        if(sec_dx==4&&sec_nb==4)         //当东西倒计时到0时,重置5秒,用于黄灯闪烁时间   	
        {
            shanruo=1;
        }
        if(sec_nb==4&&sec_dx==4)        //当南北倒计时到0时,重置5秒,用于黄灯闪烁时间   	
        {
            shanruo=1;
        }
        if(dx_nb==0&&sec_nb==0)            //当黄灯闪烁时间倒计时到0时,
        {
            P2=0x00;                    //重置东西南背方向的红绿灯		
            Green_nb=1;
            Red_dx=1;
            green=1;
			red=0;
			dx_nb=!dx_nb;
            shanruo=0;
            sec_nb=set_timenb;            //重赋南北方向的起始值		
            sec_dx=set_timenb;        //重赋东西方向的起始值		
        }        
        if(dx_nb==1&&sec_dx==0)            //当黄灯闪烁时间到		
        {
            P2=0X00;                    //重置东西南北的红绿灯状态		
            Green_dx=1;                     //东西绿灯亮	
            Red_nb=1;                     //南北红灯亮	
            green=0;
			red=1;
			dx_nb=!dx_nb;                 //取反	
            shanruo=0;                    //闪烁		
            sec_dx=set_timedx;            //重赋东西方向的起始值	
            sec_nb=set_timedx;        //重赋南北方向的起始值	
        }
    }   
}
void time1(void) interrupt 3     //定时中断子程序
{
    TH1=0X3C;                            //重赋初值
    TL1=0XB0;                            //12m晶振50ms//重赋初值
    countt1++;                            //软件计数加1
    if(countt1==10)                       // 定时器中断次数=10时(即0.5秒)
    {
            Yellow_nb=0;                //南北黄灯灭	
            Yellow_dx=0;                //东西黄灯灭	
    }
    if(countt1==20)                          // 定时器中断次数=20时(即1秒时)
    {    countt1=0;                        //清零计数器	
            Yellow_nb=1;                    //南北黄灯亮	
            Yellow_dx=1;                  //东西黄灯亮	
    }   
}

void logo()//开机的Logo  "- - - -"
{
    for(n=0;n<50;n++)    //循环显示----50次
       {
        P0=0x40;  //送形“-”
        P1=0xfe;    //第一位显示	
        delay(1);    //延时
        P1=0xfd;    //第二位显示	
        delay(1);    //延时	
        P1=0Xfb;    //第三位显示	
        delay(1);    //延时
        P1=0Xf7;    //第四位显示	
        delay(1);    //延时
        P1 = 0xff;    //灭显示	
    }
}

void delay(int ms)        //延时子程序
{
    uint j,k;
    for(j=0;j<ms;j++)            //延时ms
       for(k=0;k<124;k++);        //大约1毫秒的延时
}
/*仅供学习参考*/

  • 9
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值