5.2模拟交通灯1任务三交通灯的模拟控制5.3.1任务要求红绿交通灯安装在各个路口上,已经成为疏导交通车辆最有效和最常见的手段。本节的任务是利用单片机控制开发板上的6个LED,模拟实现交通灯的简单控制。通过编写交通灯控制程序,加深状态机的理解。任务要求如下:A:放行线:绿灯亮放行27秒,黄灯闪烁警告3秒,然后红灯亮禁行。B:禁行线:红灯亮30秒禁止通行,然后绿灯亮放行。设计能控制东、南、西、北四个路口的黄红绿信号灯正常工作,当东西方向放行时,南北方向禁行,反之亦然。同时用2位数码管显示倒计时。5.3.2知识准备1、交通灯的状态切换南北两个方向的交通灯控制方式相同,东西方向控制方式也相同。我们以西和北两个方向来分析一下交通灯的切换状态,状态如下:整个过程从状态1到状态4,状态4执行完后又重新回到状态1中,在程序中我们用状态机来切换状态。另外数码管要显示当前状态剩余的时间。2、交通灯硬件电路开发板上只有西和北两个方向的交通灯,共6只LED,分别为红、绿、黄。另外开发板上6位数码管的前两位和后两位来显示倒计时,其中前两位用来显示西方向的倒计时,后两位用来显示北方向的倒计时,中间两位不用。交通灯的电路如图5.3.1所示。状态1:西方向绿灯亮,北方向红灯亮,持续27秒钟。状态2:西方向黄灯闪烁,北方向红灯亮,持续3秒钟。状态3:西方向红灯亮,北方向绿灯亮,持续27秒。状态4:西方向红灯亮,北方向黄灯闪烁,持续3秒钟。5.2模拟交通灯2图5.3.1交通灯电路图5.3.3任务实施模拟交通灯的程序中任务较多,采用模块化,模块化后文档结构如图5.3.2所示。图5.3.2交通灯文档结构图在文档结构图中,除了主函数,在HardWare文件夹中有3个功能模块,分别是定时器模块,交通都能控制模块Traffic,数码管显示模块Seg7Display,以及宏定义模块。定时器模块提供1ms时标信号,数码管显示模块负责对4位数码管的扫描,和之前的一样,不再重复。先来分析一下主函数:(1)Main.cR1R2R3R6R5R4VCCP30P31P32VCCP33P34P35北西#includereg52.h#includemicroDefine.h#includeTimer0.h#includeTraffic.h5.2模拟交通灯3程序解释:系统上电后,首先完成定时器的初始化和交通灯状态的初始化。在大循环中,每间隔1ms,扫描一次数码管。每间隔500ms,运行一次交通灯控制程序。(2)交通灯控制模块TrafficLedRun.h#includeSeg7Display.h/****************************************************************************函数名称:main()*功能:完成模拟交通灯的各个人物*入口参数:无*出口参数:无*说明:***************************************************************************/voidmain(void){uintCnt1Ms=0;//1ms计数变量DelayMs(200);Timer0Init();//定时器0初始化TrafficInit();//交通灯状态初始化while(1){if(FlagSystem1Ms==1){FlagSystem1Ms=0;Seg7Display();//每隔1ms,扫描一次数码管if(++Cnt1Ms=500)//每隔500ms,执行1次交通灯函数{Cnt1Ms=0;TrafficLedRun();//交通灯控制NumToBuffer();//待显示值送入显示缓冲区}}}}#ifndef_TRAFFIC_H#define_TRAFFIC_H5.2模拟交通灯4在头文件中,完成了交通灯中的6个LED的接口定义,另外声明了3个函数。TrafficLedRun.c:#includereg52.h#includeMicroDefine.h#includeSeg7Display.h//6个LED的接口定义sbitWestRed=P3^0;sbitWestGreen=P3^1;sbitWestYellow=P3^2;sbitNorthRed=P3^3;sbitNorthGreen=P3^4;sbitNorthYellow=P3^5;//接口宏定义,便于移植#defineNorthRedOnNorthRed=0#defineNorthRedOffNorthRed=1#defineNorthGreenOnNorthGreen=0#defineNorthGreenOffNorthGreen=1#defineNorthYellowOnNorthYellow=0#defineNorthYellowOffNorthYellow=1#defineWestRedOnWestRed=0#defineWestRedOffWestRed=1#defineWestGreenOnWestGreen=0#defineWestGreenOffWestGreen=1#defineWestYellowOnWestYellow=0#defineWestYellowOffWestYellow=1//函数声明externvoidNumToBuffer();//缓冲区数据更新externvoidTrafficInit();//交通灯状态初始化externvoidTrafficLedRun();//交通灯状态切换#endif#includeTraffic.hucharWestNum=0;//西向数码管计数变量ucharNorthNum=0;//北向数码管技术变量5.2模拟交通灯5/****************************************************************************函数名称:NumToBuffer()*功能:待显示值传递给显示缓冲区*入口参数:待显示值*出口参数:无*说明:***************************************************************************/voidNumToBuffer(){DispBuffer[0]=WestNum/10;DispBuffer[1]=WestNum%10;DispBuffer[2]=NorthNum/10;DispBuffer[3]=NorthNum%10;}/***************************************************************************函数名称:Traffic_Init()*功能:交通灯状态初始化*入口参数:无*出口参数:无*说明:**************************************************************************/voidTrafficInit(){WestNum=27;//西向数码管初始值NorthNum=30;//北向数码管初始值WestGreenOn;WestRedOff;WestYellowOff;//西向绿灯亮NorthGreenOff;NorthRedOn;NorthYellowOff;//北向红灯亮}/***************************************************************************函数名称:TrafficLed()*功能:交通灯状态切换*入口参数:无*出口参数:无*说明:用状态机实现,每隔500ms扫描一次状态**************************************************************************/voidTrafficLedRun(){staticucharTrafficState=0;//交通灯状态机staticucharCnt500Ms=0;//500ms计数器5.2模拟交通灯6staticucharCnt500Ms=0;//500ms计数器staticucharCnt1000Ms=0;//1000ms计数器staticbitSeg7TwinkleOn=0;//数码管闪烁标志switch(TrafficState){case0://西向绿灯亮,北向红灯亮{if(++Cnt500Ms=2)//1s,倒计数减1{Cnt500Ms=0;WestNum--;NorthNum--;if(++Cnt1000Ms=27)//27s后,切换到下一状态{Cnt1000Ms=0;TrafficState=1;WestNum=3;WestGreenOff;WestRedOff;WestYellowOn;//西向黄灯亮NorthGreenOff;NorthRedOn;NorthYellowOff;//北向红灯亮}}}break;case1://西向黄灯闪烁{Seg7TwinkleOn=!Seg7TwinkleOn;//黄灯闪烁if(Seg7TwinkleOn)WestYellowOff;elseWestYellowOn;if(++Cnt500Ms=2)//1秒到{Cnt500Ms=0;WestNum--;//倒计时减1NorthNum--;if(++Cnt1000Ms=3)//3秒到{Cnt1000Ms=0;5.2模拟交通灯7TrafficState=2;//切换到下一状态WestNum=30;//倒计时重新赋初值NorthNum=27;WestGreenOff;WestRedOn;WestYellowOff;//西向绿灯亮NorthGreenOn;NorthRedOff;NorthYellowOff;//北向红灯亮}}}break;case2:{if(++Cnt500Ms=2){Cnt500Ms=0;WestNum--;NorthNum--;if(++Cnt1000Ms=27){Cnt1000Ms=0;TrafficState=3;NorthNum=3;WestGreenOff;WestRedOn;WestYellowOff;//西向红灯亮NorthGreenOff;NorthRedOff;NorthYellowOn;//北向黄灯亮}}}break;case3://北向黄灯闪烁{Seg7TwinkleOn=!Seg7TwinkleOn;if(Seg7TwinkleOn)//黄灯闪烁NorthYellowOff;elseNotrthYellowOn;//1秒到,倒计时减1if(++Cnt500Ms=2){Cnt500Ms=0;WestNum--;NorthNum--;5.2模拟交通灯8程序解释:TrafficLedRun()完成两个方向的交通等控制以及数码管倒计时。在主函数中,每隔500ms调用一次该函数,函数中任务由状态机构成,共分4个状态。在状态0中完成西向绿灯亮,北向红灯亮,运行时间为27S。状态1中完成西向黄灯闪烁,运行时间为3S。状态2和状态3,同状态0和状态1完成的内容是重复的,只不过是从东西方向换成了南北方向。if(++Cnt1000Ms=3)//3秒到{Cnt1000Ms=0;TrafficState=0;//跳到下一状态WestNum=27;//倒计时重新赋初值NorthNum=30;WestGreenOn;WestRedOff;WestYellowOff;//西向绿灯亮NorthGreenOff;NorthRedOn;NorthYellowOff;//北向红灯亮}}}break;}}