找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 273|回复: 0
打印 上一主题 下一主题
收起左侧

单片机交通灯的程序设计

[复制链接]
跳转到指定楼层
楼主
ID:1112063 发表于 2024-3-4 12:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
现代交通灯的设计
     
目录
第一章 任务要求      
1.1摘要      
1.2设计要求      
第二章 硬件设计      
2.1主控制器选择      
2.2时钟及复位电路      
2.3数码管显示模块      
2.4指示灯模块      
2.5按键模块      
2.4按键模块      
第三章 软件设计      
3.1软件设计需求及设计思路      
3.2主函数设计      
第四章 调试过程      
4.1 仿真电路图      
4.2 仿真结果      
4.2.1主干道交通灯倒计时      
4.2.2倒计时结束时黄灯闪烁      
4.2.3增加红绿灯时长      
4.2.4紧急情况车辆禁行      
第五章 总结      
第六章 参考文献      
附录1总体电路图      
附录2程序      


第一章 任务要求
1.1摘要
近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善。
十字路口车辆穿梭,行人熙攘,车行车道,人行人道,有条不紊。那么靠什么来实现这井然秩序呢?靠的就是交通信号灯的自动指挥系统。交通信号灯控制方式很多。本系统采用AT89C51单片机以及单片机最小系统和三极管驱动电路以及外围的按键和数码管显示等部件,设计一个基于单片机的交通灯设计。设计通过两位一体共阴极数码管显示,并能通过按键对定时进行设置。本系统实用性强、操作简单、扩展功能强。设计通过AT89C51单片机以及单片机最小系统和三极管驱动数码管(数码管更亮,白天看的很清楚)以及外围的按键和数码管显示等部件,数码管倒计时显示时间。
1.2设计要求
1、设计一款带左转、直行、右转三种通行绿灯;
2、带紧急按钮功能, 当紧急按钮按下时。所有方向均亮起红灯;
3、夜间运行模式按钮。按下时,所有方向黄灯闪烁;
4、可更在线修改红绿灯等待间隔时间;
5、实现显示倒计时功能;
6、其他功能、创新部分。
第二章 硬件设计
2.1主控制器选择
单片机(Microcontrollers)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。本文的单片机特指51单片机,具体芯片型号是AT89C51。需注意STC89C51,STC89C52,AT89C52都是51单片机的一种具体芯片型号。
AT89C51是AT89C5X系列单片机的典型产品,它采用ATMEL的高密非易失存储技术制造并和工业标准MCS—51指令集和引脚结构兼容。通过在单块芯片上组合通用的CPL1和快闪存储器,ATMEL公司生产的AT89C51是一强劲的微型计算机,它对许多嵌入式控制的应用,提供了一种高度灵活和成本低的解决办法。芯片AT89C51是ATMEL公司生产的带2K字节快闪存储器的8位单片机。
? 该单片机还具有体积小,价格低等特点。AT89C51单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线。
2.2时钟及复位电路
AT89C51内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但AT89C51单片机需外置振荡电容。
本设计中,使单片机运行在最小系统。
时钟电路由两个30pF的微调电容和一个晶振组成。AT89C51内部有一个用于构成振荡器的高增益反相放大器,它的输入端为芯片引脚XTAL1,输出端为引脚XTAL2。这两个引脚接石英晶体振荡器和微调电容,构成一个稳定的自激振荡器。本系统采用12Hz的振荡器,机器周期为1us。复位操作有上电自动复位、按键电平复位和外部脉冲复位三种方式,如图2.1所示。
           
2.1时钟及复位电路图
2.3数码管显示模块
如图2.2所示。
                     
2.2数码管显示图
2.4指示灯模块
设计电路中每个路口的控制信号灯应有三个,即红灯、黄灯、绿灯各一个。因此,本电路的设计中应用到红灯、黄灯、绿灯个四个。同一方向的两个路口的同一颜色指示灯是同时亮灭,为简化电路,可让这两个灯接同一引脚。这样可用P1口控制所有的指示灯,如图2.3所示。
         
2.3指示灯图
2.5按键模块
如图2.4所示。
                     
2.4按键图
第三章 软件设计
3.1软件设计需求及设计思路
根据本文设计需求,在硬件电路设计的基础上,需要通过软件编程实现的具体功能:
(1)驱动各个模块工作,实现数码管的显示及LED灯的点亮;
(2)按键设置功能。实现自动模式倒计时增加、自动模式倒计时减少等功能;
(3)倒计时功能实现。实现主干道方向通行30秒;
(4)LED红绿灯的切换。实现红灯和绿灯相互转换经过黄灯,并且黄灯闪烁。
具体设计流程如图3.1所示。
                       
3.1设计流程图
3.2主函数设计
主函数的主要功能是初始化数码管显示和定时系统、驱动各个模块工作、通过调用函数调用各个模块开始执行相应功能,如图3.2所示。
  
3.2主函数设计图
第四章 调试过程
4.1 仿真电路图
本系统用protues设计的仿真原理图如图4.1所示。
        
4.1 仿真电路图
4.2 仿真结果4.2.1主干道交通灯倒计时
如图4.2所示。
           
4.2主干道交通灯倒计时图
4.2.2倒计时结束时黄灯闪烁
如图4.3所示。
         
4.3倒计时结束时黄灯闪烁图
4.2.3增加红绿灯时长
如图4.4、4.5所示。
     
4.4增加红绿灯时长图
     
4.5增加红绿灯时长图
4.2.4紧急情况车辆禁行
如图4.6所示。
4.6紧急情况车辆禁行图
第五章 总结
刚开始选设计项目时,我原本以为应该不麻烦的。 因为我选择的是交通灯的控制。感觉大体是运用定时器及中断的原理来做。这类问题以前在单片机实验中做过类似的实验,所以大体感觉应该是很简单的。
拿到项目后。我看了看后,感觉思路清晰了。用单片机中定时器和中断的知识即可。所以我决定先完成程序设计部分,在编程过程中,我感觉以前学过的一些单片机编程的某些语法不熟悉,所以还花了一些时间复习以前的内容。本次设计不必以前的实验操作。 因为这次交通灯的控制要求实现的功能比以前复杂、不仅要有各个方向通行灯的定时指示。还需要有扩展功能。整个程序中、子程序的调用比较频繁。
编完程序后,我在Protues中画系统原理图。以前曾用CAD画过图,但是感觉Protues和CAD二者还是有一定区别的。有的原件不怎么好找,画图、调试感觉有点麻烦。也费了许多时间,但是感觉整个过程,收获还是不少的。

附录2程序
#include <reg52.h>//数码管选择位
sbit EW_1=P1^0;                  
sbit EW_2=P1^1;
sbit NS_1=P1^2;                  
sbit NS_2=P1^3;
sbit add_red_time=P1^4;                                   //加红灯时间按钮
sbit add_green_time=P1^5;                           //加绿灯时间按钮
sbit reduce_red_time=P1^6;                           //减红灯时间按钮
sbit reduce_green_time=P1^7;                   //减绿灯时间按钮
sbit NS_led=P2^6;                                           //南北向灯紧急控制按钮
sbit EW_led=P2^7;                                           //东西向灯紧急控制按钮
sbit EW_red=P2^0;                                           //东西向红灯
sbit EW_green=P2^1;                                           //东西向绿灯
sbit EW_yellow=P2^2;                               //东西向黄灯
sbit NS_red=P2^3;                                           //南北向红灯
sbit NS_green=P2^4;                                           //南北向绿灯
sbit NS_yellow=P2^5;                                   //南北向黄灯
char count=0;                                                //计数,count=20表示1s
char red_time=30;                                        //红灯停留时间
char green_time=25;                                        //绿灯停留时间
char yellow_time=0;                                        //黄灯停留时间
char NS_second=0;                                        //南北红绿灯秒计时
char EW_second=0;                                    //东西红绿灯秒计时
char code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};                //共阳数码管段码表,仿真中用的是共阴数码管,所以使用时需对段码取反
char display_data[4]={0};                        //show_data[0]显示南北计时十位,show_data[1]显示南北计时个位,show_data[2]显示东西计时十位,show_data[3]显示东西计时个位
char temp_data[4]={0};
char NS_R_G_mode=0;                                        //南北红绿灯亮模式  0  红灯  1  绿灯  2  黄灯
char EW_R_G_mode=1;                                        //东西红绿灯亮模式  0  红灯  1  绿灯  2  黄灯
bit NS_R_G_flag=0;                                        //南北红绿灯标识位  0  红灯  1  绿灯
bit EW_R_G_flag=0;                                        //东西红绿灯标识位  0  红灯  1  绿灯
void delay(unsigned int i)                        //简单延时
{
        while(i--);
}
void Timer_init()                                        //定时器初始化
{
        //定时50ms
    TMOD = 0x01;                                        //定时器方式1
    TH0 = 0x3C;                                                //定时器赋初值
    TL0 = 0xB0;
    EA = 1;                                                        //开启总中断
    ET0 = 1;                                                //开启定时器中断
    TR0 = 1;                                                //开启定时器
}
void Init()                                                        //系统初始化
{
        P0=0x00;
        P2=0x00;
        EW_1=1;                  
        EW_2=1;
        NS_1=1;
        NS_2=1;
        NS_led=1;
        EW_led=1;
        NS_second=red_time;                                //默认初始时南北向灯亮红灯,并赋红灯时长
        EW_second=green_time;                        //默认初始时东西向灯亮绿灯,并赋绿灯时长
        yellow_time=red_time-green_time;//黄灯时间为红灯时间与绿灯时间差
        Timer_init();
}
void NS_SMG_drive(char *buff)                //南北向数码管驱动
{
        //显示十位
        NS_1=0;
        NS_2=1;
        P0=~smgduan[buff[0]];           //段码取反
        delay(5);                                                 //间隔一段时间扫描      
        P0=0x00;                                                //消隐
        NS_1=1;
        NS_2=0;
        P0=~smgduan[buff[1]];
        delay(5);
        P0=0x00;                    //关闭南北向数码管
        NS_1=1;
        NS_2=1;
}
void EW_SMG_drive(char *buff)                //东西向数码管驱动
{
        EW_1=0;
        EW_2=1;
        P0=~smgduan[buff[2]];           //段码取反
        delay(5);                                                 //间隔一段时间扫描      
        P0=0x00;                                                  //消隐      
        EW_1=1;
        EW_2=0;
        P0=~smgduan[buff[3]];
        delay(5);        
        P0=0x00;                            //关闭东西向数码管
        EW_1=1;                  
        EW_2=1;
}
void data_del(char *buff,char data1,char data2)        //数据处理
{
        buff[0]=data1/10;                                                        //取data1的十位
        buff[1]=data1%10;                                                        //取data1的个位
        buff[2]=data2/10;                                                        //取data2的十位
        buff[3]=data2%10;                                                        //取data2的个位
}
void Time_del()                                                                        //计时处理
{
        if(count>=20)                                                                //判断是否满1s
        {
                NS_second--;                                                        //南北向灯计时自减
                EW_second--;                                                        //东北向灯计时自减
                switch(NS_R_G_mode)                                                //南北向灯
                {
                        case 0:                                                                //红灯
                        {
                                if(NS_second<0)
                                {
                                        NS_second=green_time;                //开始绿灯倒计时
                                        NS_R_G_mode=1;                           //红灯亮完绿灯亮
                                }                              
                        }break;
                        case 1:                                                                //绿灯
                        {
                                if(NS_second<0)
                                {
                                        NS_second=yellow_time;                //开始黄灯倒计时
                                        NS_R_G_mode=2;                           //绿灯亮完黄灯亮                                       
                                }               
                        }break;
                        case 2:                                                                //黄灯
                        {
                                if(NS_second<0)
                                {
                                        NS_second=red_time;                        //开始红灯到计时
                                        NS_R_G_mode=0;                           //黄灯亮完红灯亮                                       
                                }               
                        }break;
                        default:break;
                }
               
void R_G_Y_led()                                                                //红绿灯驱动
{
        switch(NS_R_G_mode)                                                        //南北向
        {
                case 0:                                                                        //红灯
                {
                        NS_yellow=0;                                                //黄灯灭
                        NS_red=1;                                                        //红灯亮
                }break;
                case 1:                                                                        //绿灯
                {
                        NS_red=0;                                                        //红灯灭
                        NS_green=1;                                                        //绿灯亮
                }break;
                case 2:                                                                        //黄灯
                {
                        NS_green=0;                                                        //绿灯灭
                        if(count<10)                                                //黄灯以1hz频率闪烁
                                NS_yellow=1;
                        else
                                NS_yellow=0;                       
                }break;
                default:break;               
        }
        switch(EW_R_G_mode)                                                        //东西向
        {
                case 0:                                                                        //红灯
                {
                        EW_yellow=0;                                                //黄灯灭
                        EW_red=1;                                                        //红灯亮
                }
        if((add_red_time==0)||(add_green_time==0)||(reduce_red_time==0)||(reduce_green_time==0))//设置红绿灯时长时任一设置按钮都可触发
        {
                TR0 = 0;                                                                //关闭定时器
                P2=0x00;                                                                //清零P2寄存器
                EW_led=1;                                                                //EW_led、NS_led引脚也在P2寄存器内,但是后面需要这两个按钮结束设置红绿灯时长任务,故而这两个引脚要拉高
                NS_led=1;
                while(1)
                {
                        data_del(temp_data,red_time,green_time);//显示当前红绿灯时长
                        NS_SMG_drive(temp_data);
                        EW_SMG_drive(temp_data);
                        if(add_red_time==0)                                        //判断加红灯时间按钮是否按下
                        {
                                delay(5);                                                //消抖
                                if(add_red_time==0)
                                {
                                        red_time++;                                        //红灯时间自加
                                        if(red_time>99)                                //限制红灯时间最大值为99
                                                red_time=99;
                                        data_del(temp_data,red_time,red_time);//南北向数码管显示红灯时长
                                        NS_SMG_drive(temp_data);
                                }while(!add_red_time);                        //等待加红灯时间按钮弹起
                        }
                        if(add_green_time==0)                                //判断加绿灯时间按钮是否按下
                        {
                                delay(5);
                                if(add_green_time==0)
                                {
                                        green_time++;                                //绿灯时间自加
                                        if(green_time>95)                        //限制绿灯时间最大值95
                                                green_time=95;
                                        data_del(temp_data,green_time,green_time);//东西向数码管显示绿灯时长
                                        EW_SMG_drive(temp_data);
                                }while(!add_green_time);                //等待加绿灯时间按钮弹起
                        }
                        if(reduce_red_time==0)                                //判断减红灯时间按钮是否按下
                        {
                                delay(5);
                                if(reduce_red_time==0)
                                {
                                        red_time--;                                        //红灯时间自减
                                        if(red_time<10)                                //限制红灯时间最小值10
                                                red_time=10;
                                        data_del(temp_data,red_time,red_time);
                                        NS_SMG_drive(temp_data);
                                }while(!reduce_red_time);                //等待减红灯时间按钮弹起
                        }
                        if(reduce_green_time==0)                        //判断减绿灯时间按钮是否按下
                        {
                                delay(5);
                                if(reduce_green_time==0)
                                {
                                        green_time--;                                //绿灯时间自减
                                        if(green_time<5)                        //限制绿灯时间最小值5
                                                green_time=5;
                                        data_del(temp_data,green_time,green_time);
                                        EW_SMG_drive(temp_data);
                                }while(!reduce_green_time);                //等待减绿灯时间按钮弹起
                        }
                        if((NS_led==0)||(EW_led==0))                //任一紧急控制按钮按下则结束设置红路灯时长任务
                        {
                                break;
                        }
                }while((!NS_led)||(!EW_led));                        //等待紧急控制按钮弹起
                TR0 = 1;                                                                //开启定时器
                yellow_time=red_time-green_time;                //更新黄灯时间
        }
}
void Urgent()                                                                        //红绿灯紧急控制
{
        if((NS_led==0)||(EW_led==0))                                //任一紧急控制按钮按下触发
        {
                TR0 = 0;                                                                //关闭定时器
                P2=0x00;
                EW_led=1;
                NS_led=1;
                EW_1=1;                                                                        //关闭所有数码管
                EW_2=1;
                NS_1=1;
                NS_2=1;
                while((!NS_led)||(!EW_led));                        //判断紧急控制按钮按是否弹起
                while(1)
                {
                        if(NS_R_G_flag)                                                //根据NS_R_G_flag状态交替亮红灯或者绿灯
                        {
                                NS_green=1;      
                                NS_red=0;                                       
                        }      
                        else
                        {
                                NS_red=1;      
                                NS_green=0;                              
                        }
                        if(EW_R_G_flag)                                                //根据EW_R_G_flag状态交替亮红灯或者绿灯
                        {
                                EW_green=1;      
                                EW_red=0;                                                                       
                        }
                        else
                        {
                                EW_red=1;
                                EW_green=0;                                               
                        }      
                        if(NS_led==0)                                                //判断南北向紧急控制按钮是否按下
                        {
                                delay(5);
                                if(NS_led==0)
                                {
                                        NS_R_G_flag=!NS_R_G_flag;        //NS_R_G_flag状态取反                              
                                }while(!NS_led);                                //等待南北向紧急控制按钮弹起
                        }
                        if(EW_led==0)                                                //判断东西向紧急控制按钮是否按下
                        {
                                delay(5);
                                if(EW_led==0)
                                {
                                        EW_R_G_flag=!EW_R_G_flag;        //EW_R_G_flag状态取反                                               
                                }while(!EW_led);                                //等待东西向紧急控制按钮弹起
                        }      
                        if((add_red_time==0)||(add_green_time==0)||(reduce_red_time==0)||(reduce_green_time==0))//任一红绿灯设置时长按钮按下结束紧急控制人物
                        {
                                TR0 = 1;                                                //开启定时器
                                break;
                        }
                }while((!add_red_time)||(!add_green_time)||(!reduce_red_time)||(!reduce_green_time));//等待红绿灯时间设置按钮弹起      
                P2=0x00;
                EW_led=1;
                NS_led=1;
        }
}
void main()
{
        Init();
        while(1)
        {
                Time_del();                                                                //时间处理
                data_del(display_data,NS_second,EW_second);//数据处理
                NS_SMG_drive(display_data);                                //南北向数码管驱动
                EW_SMG_drive(display_data);                                //东西向数码管驱动
                R_G_Y_led();                                                        //红绿灯驱动
                Set_time();                                                                //红绿灯时长设置
                Urgent();                                                                //紧急控制
        }
}
void Timer0(void) interrupt 1                                        //定时器中断
{
    TH0 = 0x3C;
    TL0 = 0xB0;
        count++;                                                //触发中断后计数值自加,定时器中断每50ms触发一次
}




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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