基于51单片机的十字路口交通灯系统

1 设计名称

基于51单片机的十字路口交通灯系统(C语言、Proteus开发环境)

2 设计要求

1、 基于51系列单片机设计一个十字路口交通灯控制系统,用于模拟道路十字路口交通灯实际运行的场景。

2、 东西向、南北向依次进行周期通行,默认设置为:东西向直行(绿灯)时间30秒,左转(蓝灯)时间15秒;南北向直行(绿灯)时间20秒,左转(蓝灯)时间10秒。

3、 每次直行(绿灯)变左转(蓝灯)和左转(蓝灯)变停车(红灯)前,黄灯需先闪烁3秒,此3秒时长包含在上述直行和左转时间内。

4、 可通过控制台按键实现对十字路口进行交通管制的功能。

5、 可通过控制台按键实现对十字路口各方向的通行时间进行设置的功能。

3 功能说明

整个十字路口由东西向道路和南北向道路垂直交叉形成,我们采用“上北下南,左西右东”的惯例进行构图。每个方向都有一组4色的LED灯来控制交通的流向和节奏。流向也即方向,通过不同LED灯颜色进行表征:红灯停,绿灯行,黄灯等一等,这里左转我们用蓝灯表示;节奏通过倒计时时间进行控制,该时间的时基由单片机的定时器提供。

十字路口的倒计时时间分别通过四个2位的七段共阴极数码管显示。绿灯点亮道路上的数码管显示的数字是该道路所剩余的可通行时间,红灯点亮道路上的数码管显示的数字是该道路所剩余的禁行时间,小伙伴需要注意区分两者不同的物理含义。

系统上电后,默认运行在“正常模式”下。此时南北向绿灯点亮,允许直行;东西向红灯点亮,禁止直行和左转。具体的状态迁移顺序可参照下面第 6 部分内容。

4 系统架构

整个架构非常简单,主要由四部分组成。分别是MCU单片机控制模块、按键输入扫描模块、数码管显示模块和交通灯显示模块。按键、数码管和LED灯都是典型的人机交互的元器件,按键用于接收命令,数码管和LED灯用于反馈信号和状态。数据流向也是单向的,由左至右。

图1 交通灯系统架构图

我们现在将十字路口交通灯的运行场景抽象归纳一下,然后用下面的图表进行复盘。

5 运行模式

对照日常生活,我们来盘点一下交通灯运行的模式:

“正常模式”:模拟十字路口正常运行的场景,交通灯按正常的顺序进行周期循环;

“夜间模式”:模拟十字路口夜间运行的场景,东西向和南北向的黄灯同时闪烁;

“紧急模式”:模拟十字路口进入紧急情况下的场景(救护车、消防车通过等),东西向和南北向的红灯全部点亮;

“强制东西向通行模式”:强制东西向通行,南北向停车等待。

“强制南北向通行模式”:强制南北向通行,东西向停车等待。

6 ”正常模式“下状态迁移之状态机

不同国家、不同城市、不同十字路口都有不同的状态设置。有的路口是先直行再左转,有的路口是先允许左转再允许直行,有的路口压根就没有专门的左转灯,有的路口有人行道指示灯,而有的没有。所谓千人千面,五官各不相同,但确有一个共性,就是都有五官。状态机的思路可以很好的解决这个问题。

图2 正常模式下状态机

7 ”正常模式“下状态迁移之矩阵表

图3 正常模式下状态矩阵表

1 - 表征对应颜色交通灯点亮;

0 - 表征对应颜色交通灯熄灭;

1/0 - 表征对应颜色交通灯闪烁;

蓝色灯 - 表征对应道路左转状态;

8 仿真电路图

因为案例更侧重功能的实现,对于硬件电路的设计要求不是太高,达到能用就行的标准就行,所以这里只简要说一下重点吧。

1 单片机P0一定要加上拉电阻。为什么?因为P0口内部为开集电极输出,无法输出高电平,只有加了上拉电阻,P0口才能输出高电平。

2 数码管的驱动一定要加限流电阻。虽然在Proteus中仿真不加问题也不大,但是实际产品肯定是不允许的,而且也无法工作。

3 LED灯驱动一定要加限流电阻。如果不加限流电阻,单片机会工作异常,因为单片机引脚的驱动电流的能力是有限制的,超出则正常功能无法保证,甚至烧坏单片机。

4 LED灯不建议直接并联使用。虽然LED灯具有正向单调的伏安特性曲线,但是它的温度系数却是负向的,不利于均流。

5 按键模块采用的是普通的点对点的结构,但设计中也可采用矩阵式按键,小伙伴可以自行发挥。

6 当前的设计,单片机引脚基本被全部分配用完,没有冗余。对于实物产品的开发这是不被允许的,因为过于捉襟见肘的单片机资源完全不利于产品后期的功能升级和延展。如果单片机引脚紧张,除可以采用矩阵式键盘节省引脚外,也可以采用数字锁存器或者译码器对引脚进行扩展使用。

图4 Proteus环境仿真图
图5 Proteus环境十字路口放大视图
图6 Proteus环境单片机模块放大视图
图7 Proteus环境控制台按键模块放大视图

9 器件清单

图8 交通灯仿真图元器件清单

其他未尽事宜,诸如导线啊,芯片底座啊,电源插座啊,电源啊等等,都是基本功,这里暂就不表了。

10 C 语言核心源代码

软件架构采用的是时间触发机制+状态机的设计模式,这种模式的好处是MCU执行效率高,实时性好,另外一点很重要的就是灵活性,代码容易扩展。时间片调度周期为20ms,用于按键的扫描识别和LED数码管的动态刷新。交通灯运转的状态机是通过switch来完成的。大侠看到网络上很多的案例代码用到了外部中断来实现按键扫描,这是完全没必要的,主函数轮询扫描的方式完全就够用了,51单片机的外部中断资源毕竟有限且珍贵,何以要用中断呢?难道江郎才尽了?此外,设计中按键扫描模块实现了去抖的功能。

因版面受限,这里只能贴出核心状态机的源代码供各位看管参考学习了。其他功能相对简单,大家可以适当脑补,或者也可划至文章最后寻找解决方案。

10.1 变量定义

sbit Gb_SN_LEDH_En = P2^0; // 南北向高位LED数码管使能控制位

sbit Gb_SN_LEDL_En = P2^1; // 南北向低位LED数码管使能控制位

sbit Gb_EW_LEDH_En = P2^2; // 东西向高位LED数码管使能控制位

sbit Gb_EW_LEDL_En = P2^3; // 东西向低位LED数码管使能控制位

sbit Gb_Debug_LEDH_En = P2^4; // 调试用高位LED数码管使能控制位

sbit Gb_Debug_LEDL_En = P2^5; // 调试用低位LED数码管使能控制位

sbit Gb_EW_Walk_Green_En = P2^6;  // 东西向人行道绿灯使能控制位

sbit Gb_SN_Walk_Green_En = P2^7;  // 南北向人行道绿灯使能控制位

sbit Gb_EW_Yellow_En = P1^2;  // 东西向黄灯使能控制位

sbit Gb_SN_Yellow_En = P1^6;  // 南北向黄灯使能控制位

sbit Gb_EW_Red_En = P1^3;  // 东西向黄灯使能控制位

sbit Gb_SN_Red_En = P1^7;  // 南北向黄灯使能控制位

#define SET 0  // 设置/确认按钮

#define SET_ADD 1  // 设置+

#define SET_SUB 2  //设置-

#define SET_HOME 3  // 正常模式

#define SET_YELLOW 4  // 夜间模式

#define SET_RED 5  // 紧急模式

#define SET_EW 6  // 强制东西向通行模式

#define SET_SN 7  //强制南北向通行模式

uint_8 Gb_Traffic_RunMode;  // 红绿灯运行模式  0-正常  1-夜间  2-紧急  3-东西强制  4-南北强制

uint_8 Gb_SET_Active_Flag;  // 使能设置功能标志位

uint_8 Gb_SET_LEDSEG_Blink_Flag;  // 控制台数码管闪烁时基标志位

uint_8 Gb_LED_SEG_Update_Flag;  // LED数码管刷新调度标志位

uint_8 Gb_LED_YellowControl_Flag;  // LED黄灯闪烁调度标志位

uint_8 Gb_LED_Task1s_Flag;  // 交通灯任务调度标志位

uint_8 Gb_EW_YellowLight_Flag;  // 东西向黄灯闪烁标志位

uint_8 Gb_SN_YellowLight_Flag;  // 南北向黄灯闪烁标志位

uint_8 Gb_EW_LED_RealTime;  // 东西向LED数码管显示时间

uint_8 Gb_SN_LED_RealTime;  // 南北向LED数码管显示时间

uint_8 Gb_SET_LED_RealTime;  // 控制台LED数码管显示时间,默认无显示

uint_8 Gb_System_Step_Index = 0;  // 正常模式下红绿灯运行进度标志

uint_8 Cc_EW_DirectPass_Time = 10;  // 东西向道路直行时间参数(不含黄灯闪烁时间),单位秒

uint_8 Cc_SN_DirectPass_Time = 15;  // 南北向道路直行时间参数(不含黄灯闪烁时间),单位秒

uint_8 Cc_EW_LeftPass_Time = 5;  // 东西向道路左转时间参数(不含黄灯闪烁时间),单位秒

uint_8 Cc_SN_LeftPass_Time = 5;  // 南北向道路左转时间参数(不含黄灯闪烁时间),单位秒

uint_8 Cc_YellowLight_Time = 3;  // 黄灯闪烁时间参数,单位秒

uint_8 code LED_SEG_Table[11]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};  //共阴数码管0-9段选码表,及无显示状态

uint_8 code LED_Light_Table[4]={0X28,0X18,0X82,0X81};  //交通信号灯控制代码,对应P1引脚

10.2 交通灯控制函数

/*************************************************

函数名:十字路口交通灯控制函数

参  数:无

返回值:无

结  果:管理红绿蓝交通灯,管理人行道交通灯

************************************************/

void Traffic_Control(void)

{

    Gb_SN_LED_RealTime--;  // 南北向时间倒计时

    Gb_EW_LED_RealTime--;  // 东西向时间倒计时

    switch(Gb_System_Step_Index)

    {

        case 0:  // 状态0 - 南北向绿灯,东西向红灯

            if(Gb_SN_LED_RealTime <= Cc_YellowLight_Time)

            {

                P1 = P1&0x0F;

                Gb_SN_YellowLight_Flag = 1;

                Gb_System_Step_Index++;

            }

            break;

        case 1:  // 状态1 - 南北向黄灯,东西向红灯

            if(Gb_SN_LED_RealTime <= 0)

            {

                P1 = LED_Light_Table[1];

                Gb_SN_LED_RealTime = Cc_SN_LeftPass_Time + Cc_YellowLight_Time;

                Gb_SN_YellowLight_Flag = 0;

                Gb_System_Step_Index++;

            }           

            break;

        case 2:  // 状态2 - 南北向左转灯亮,东西向红灯

            if(Gb_SN_LED_RealTime <= Cc_YellowLight_Time)

            {

                P1 = P1&0x0F;

                Gb_SN_YellowLight_Flag = 1;

                Gb_System_Step_Index++;

            }

            break;

        case 3:  // 状态3 - 南北向黄灯,东西向红灯

            if(Gb_SN_LED_RealTime <= 0)

            {

                P1 = LED_Light_Table[2];

                Gb_SN_LED_RealTime = Cc_EW_DirectPass_Time + Cc_EW_LeftPass_Time + 2*Cc_YellowLight_Time;

                Gb_EW_LED_RealTime = Cc_EW_DirectPass_Time + Cc_YellowLight_Time;

                Gb_SN_Walk_Green_En = 0;

                Gb_EW_Walk_Green_En = 1;

                Gb_SN_YellowLight_Flag = 0;

                Gb_System_Step_Index++;

            }           

            break;

        case 4:  // 状态4 - 南北向红灯,东西向绿灯

            if(Gb_EW_LED_RealTime <= Cc_YellowLight_Time)

            {

                P1 = P1&0xF0;

                Gb_EW_YellowLight_Flag = 1;

                Gb_System_Step_Index++;

            }       

            break;

        case 5:  // 状态5 - 南北向红灯,东西向黄灯

            if(Gb_EW_LED_RealTime <= 0)

            {

                P1 = LED_Light_Table[3];

                Gb_EW_LED_RealTime = Cc_EW_LeftPass_Time + Cc_YellowLight_Time;

                Gb_EW_YellowLight_Flag = 0;

                Gb_System_Step_Index++;

            }       

            break;

        case 6:  // 状态6 - 南北向红灯,东西向左转灯亮

            if(Gb_EW_LED_RealTime <= Cc_YellowLight_Time)

            {

                P1 = P1&0xF0;

                Gb_EW_YellowLight_Flag = 1;

                Gb_System_Step_Index++;

            }       

            break;

        case 7:  // 状态7 - 南北向红灯,东西向黄灯

            if(Gb_SN_LED_RealTime <= 0)

            {

                Cc_EW_DirectPass_Time = Cc_EW_DirectPass_Time2; 

                Cc_SN_DirectPass_Time = Cc_SN_DirectPass_Time2; 

                Cc_EW_LeftPass_Time = Cc_EW_LeftPass_Time2; 

                Cc_SN_LeftPass_Time = Cc_SN_LeftPass_Time2; 

                Cc_YellowLight_Time = Cc_YellowLight_Time2;

                Gb_SN_LED_RealTime = Cc_SN_DirectPass_Time + Cc_YellowLight_Time;

                Gb_EW_LED_RealTime = Cc_SN_DirectPass_Time + Cc_SN_LeftPass_Time + 2*Cc_YellowLight_Time;

                P1 = LED_Light_Table[0];

                Gb_SN_Walk_Green_En = 1;

                Gb_EW_Walk_Green_En = 0;

                Gb_EW_YellowLight_Flag = 0;

                Gb_System_Step_Index = 0;

            }       

            break;

        default:

            break;

    }

}

11 操作说明

从按键用途的角度进行划分,上图中的8个按键可以被归为两类。一类是用来设置时间参数的,另一类是用来切换交通灯系统运行模式的,我们就根据这2种大的分类分别进行详细的解释和说明。

11.1 “参数设置”按键操作说明

“参数设置”类的按键有三个,由上至下分别为“设置/确认“按钮、”加+“按钮和”减-“按钮。其主要功能是用来对十字路口东西向和南北向在各个阶段(东西向直行、东西向左转、南北向直行、南北向左转和黄灯等待)的通行时间参数进行设置和更新。

”设置/确认“按钮:共有三种功能:1 使系统进入时间参数设置状态;2 对设置参数进行顺序切换;3 完成参数设置并返回退出;

”加+“按钮:单击一下,对应时间参数加1。

” 减-“按钮:单击一下, 对应时间参数减1。

11.2 “模式切换”按键操作说明

“模式切换”类按键共有五个,由上至下分别为“正常模式“按钮、”夜间模式“按钮、”紧急模式“按钮、”强制东西向通行模式“按钮和”强制南北向通行模式“按钮。此处操作非常简单,不再赘述。交通灯在个模式下运行时对应的实际场景请参照上文说明。

以上为全部分享内容,如有任何技术疑问,可以在文章下方留言交流或关注下方公众号讨论。

- END -

如果你觉得我的分享对你有那么一点点启发和帮助,请帮忙点赞!

更多案例分享,请关注公众号【电控夜雨十年灯】,一个专注于分享硬件电路设计、单片机开发、C语言设计和Proteus案例的旮旯,保证干货满满!

本文为作者原创,未经允许,不得转载,谢谢支持!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345