第3章第4节 使用Wanlix编写交通红…

来源:互联网 发布:top域名有什么用 编辑:程序博客网 时间:2024/06/06 10:07


目前更新到5.3节,请在
http://dl.dbank.com/c02ackpwp6下载5.3节的全部文档

 

本节源代码请在http://dl.dbank.com/c0sw8nca9k下载

 

第4节 使用Wanlix编写交通红绿灯控制系统

至此我们已经实现了一个非常简单、小巧的操作系统——Wanlix,简单到它只具备任务切换这一项任务管理功能,而且需要用户自己主动切换,实时性较差。但无论如何,它确实是实现了任务的切换,这是不争的事实,从前面打印的例子就可以证明。

本节我们将使用Wanlix开发一个交通红绿灯的控制程序,通过这个稍微复杂点的程序来应用Wanlix操作系统。

 

首先,先来了解一下这个交通红绿灯的功能,然后再设计软件结构、编码,最后在单板上运行,观察结果,展示使用Wanlix操作系统开发的第一个嵌入式系统。

 

功能说明:

第3章第4节 <wbr>使用Wanlix编写交通红绿灯控制系统

图 20  十字路口交通红绿灯示意图

20是我们这节所要编写的交通红绿灯控制系统的应用场景,左右方向是主干道,上下方向是从干道,主干道行驶机动车辆,从干道为行人斑马线。主干道上的车多,通行时间长,从干道行人少,通行时间短,主从干道交替通行。顺着前进的方向看,主干道上的3个灯分别是红黄绿,从干道上的2个灯分别是红绿。上下的两个方块是行人横跨主干道时的应急按钮,当行人按下应急按钮时,无论主干道处于什么状态,主干道都会变为停止通行状态,从干道变为通行状态,行人可以从从干道通行,过一会主从干道又恢复为正常的交替通行状态。

3描述了上述十字路口各个灯的状态运行情况: 

 

主干道红灯

主干道黄灯

主干道绿灯

从干道红灯

从干道绿灯

状态1:主干道通行,从干道停止,30秒。

状态2:主干道将停,从干道将通行,5秒。

状态3:主干道停止,从干道通行,10秒。

状态4:主干道将通行,从干道将停,5秒。

闪烁

表 3  十字路口状态表

状态1持续30秒,主干道绿灯亮,从干道红灯亮,指示主干道通行从干道停止;此后转换为状态2持续5秒,主干道黄灯亮,从干道红灯亮,指示主干道将停止,从干道将通行;此后转换为状态3持续10秒,主干道红灯亮,从干道绿灯亮,指示主干道停止从干道通行;此后转换为状态4持续5秒,主干道红灯亮,从干道绿灯闪烁,指示主干道将通行,从干道将停止;此后再转换到状态1,如此周而复始的运行。

另外,当行人按下应急按钮时,无论当前处于什么状态都会转换为从干道通行状态,此后仍按上述4个状态循环运行。

   十字路口各个灯状态图转换如图21所示:


第3章第4节 <wbr>使用Wanlix编写交通红绿灯控制系统

图 21  十字路口运行状态切换图

软件设计:

在任务设计上,需要尽可能做到任务间的耦合性小,任务之间仅通过少量的接口传递消息。在这个交通灯系统中,我们可以将其功能拆分成2任务,任务1用来控制十字路口的状态,并根据十字路口的状态改变各个灯的状态,任务2用来将各个灯的状态输出到灯上,这样分解的两个任务之间的耦合性小,当我们修改方案,需要改变十字路口各个灯的控制策略时,只需要修改任务1的代码,任务2几乎不受影响,这点在后面的例子中可以看到。

当行人按下应急按钮时会触发中断,在中断里面改变十字路口的状态,退出中断后,任务1会根据十字路口的状态重新更新各个灯的状态,任务2又会将灯的状态输出到灯上,这样就可以完成这个十字路口的软件功能了。

当然,也可以有其它的任务设计方式,但不管如何设计,必须要遵守的是:各个任务之间层次分明,耦合性要小,避免多个任务互相干扰。最差劲的设计是几个任务互相影响,比如一个任务控制主干道的灯,另一个任务控制从干道的灯,每个任务不仅要考虑到自己如何运行,还要考虑与另外一个任务的配合,当任务多的时候,这种配合将变的非常复杂,错误百出,即使功能实现了,这对于以后的维护、功能修改、扩展也将是巨大的考验。

 

在这个软件系统里,难点在于控制各个灯的状态变化。在所有的十字路口状态中,灯有亮、灭、闪烁3种状态,每种十字路口状态中每个灯有不同的持续时间,为此,我们可以用一个结构体来表示灯的这些状态:

typedef struct crossstatestr

{

    U32 uiRunTime;

    LEDSTATE astrLed[LEDNUM];

}CROSSSTATESTR;

其中uiRunTime是该状态运行的时间,LEDSTATE结构体是每个灯的状态结构体,LEDNUM是灯的数量,为每个灯定义一个状态变量。

LEDSTATE结构体为:

typedef struct ledstate

{

    U32 uiLedState;

    U32 uiBrightness;

}LEDSTATE;

uiLedState表示灯的状态,是亮、灭还是闪烁状态,uiBrightness表示当灯处于闪烁状态时当前的亮度,是亮还是灭。

使用上面的这2个结构体就可以表示十字路口的一个状态。使用该结构体,我们定义一个十字路口的当前运行状态:

CROSSSTATESTR gstrCurCrossSta;

当十字路口状态发生变化时,需要重新获取新状态的各个参数,为此,我们再定义一个结构体数组用来存放十字路口的各个状态初始值:

CROSSSTATESTR gastrCrossSta[CROSSSTATENUM] CROSSINITVALUE;

其中CROSSSTATENUM是十字路口状态的数量,这样变量gastrCrossSta中包含了所有灯的所有状态,CROSSINITVALUE是变量gastrCrossSta的初始值,包含了表3中各个灯的所有状态,当程序运行时,各个灯的初始状态就全部被放到了gastrCrossSta变量中。

任务1运行时,若发现当前运行状态变量gstrCurCrossSta中的状态时间参数uiRunTime耗尽,gstrCurCrossSta变量则从gastrCrossSta变量中获取下个状态的初始值,根据图21的状态切换关系改变状态,任务2再将灯的状态输出到灯上,如此循环。

在这个软件系统里,需要根据时间来改变各个灯的状态,我们可以使用硬件定时器每隔100ms产生一次中断,这个中断时间叫做tick,是软件系统的时间单位,由软件在每个tick中断里对时间变量累计,这样在程序里对只要对时间变量进行判断就可以确定时间了。

 

   软件流程如图2223所示,软件开始运行时,初始化十字路口的各个状态,然后任务1和任务2交替运行。期间发生的定时器中断会更新时间变量计数,行人中断会改变十字路口的状态变量,任务1需要根据这些变量判断各个状态是否需要改变,如需改变时则发生状态切换,任务2再根据这些灯的状态更新灯的输出。注意一点,任务1在判断这些变量时需要锁中断,判断结束后再开中断,这样做是为了防止在判断状态变量时发生了中断,修改了这些变量,从而产生错误的判断。

第3章第4节 <wbr>使用Wanlix编写交通红绿灯控制系统

图 22  十字路口主流程图

第3章第4节 <wbr>使用Wanlix编写交通红绿灯控制系统

第3章第4节 <wbr>使用Wanlix编写交通红绿灯控制系统

图 24  十字路口红绿灯演示

大家也可以到网站上去下载视频观看,可以看到各个灯按照我们的设计循环亮灭,当行人按下应急按钮时,可以中断主通道的通行,让行人先过马路,可以看到这个小系统实现了我们设计的要求。

 

最后,我们来做个小改动,在状态1和状态2之间增加一个状态:主干道绿灯闪烁,从干道红灯亮,用来表示主干道通行状态将要结束,姑且称之为状态11,来看增加状态11后的表4

 

主干道红灯

主干道黄灯

主干道绿灯

从干道红灯

从干道绿灯

状态1:主干道通行,从干道停止,30秒。

状态11:主干道通行,从干道停止,5秒。

闪烁

状态2:主干道将停,从干道将通行,5秒。

状态3:主干道停止,从干道通行,10秒。

状态4:主干道将通行,从干道将停,5秒。

闪烁

表 4  增加状态后的十字路口状态表

增加了状态11,我们在原有代码上需要做如下修改:

1.CROSSSTATENUM枚举变量中增加一个新状态11

2.CROSSINITVALUE宏定义中增加表4中状态11的初始值。

3.在行人中断函数ISR_PassengerIsr里增加对状态11的处理。

可以看到在这个软件结构上只要做很少的代码改动就增加这个新功能。大家切记,编码只是软件中的一部分工作,软件编码前的设计也非常重要!

阅读全文
0 0
原创粉丝点击