如何让stateflow 图形函数函数 执行完全

stateflow入门pdf下载_爱问共享资料
stateflow入门.pdf
stateflow入门.pdf
stateflow入门.pdf
简介:本文档为《stateflow入门pdf》,可适用于高等教育领域,主题内容包含第十二章利用状态流Stateflow进行控制系统状态转换Statefolw是一种图形化的设计开发工具是有限状态机的图形实现工具有人称之为状态流。主要符等。
侵权或盗版
*若权利人发现爱问平台上用户上传内容侵犯了其作品的信息网络传播权等合法权益时,请按照平台要求书面通知爱问!
赌博犯罪类
添加成功至
资料评价:
所需积分:0您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
Stateflow使用方法.ppt 57页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:120 &&
你可能关注的文档:
··········
··········
9、嵌入式 M 函数的设置及其调用 嵌入式 MATLAB 函数使用户可以利用MATLAB 强大的功能,在Stateflow 图中编MATLAB 语言函数,调用MATLAB 的各类函数。Simulink 利用嵌入MATLAB 函数的状态流实现Simulink 模型中嵌入MATLAB 模块功能。
9、嵌入式 M 函数的设置及其调用 单击M文件图标后将其拖入工作区,在左上图中问号处单击写入MATLAB 函数名及其形参名,如MaxMin(x) 双击新建的M文件会出现函数编辑窗口,当MATLAB中自带函数不能实现所需功能,我们可以在该窗口编辑实现目标功能所需的函数。 10、真值表的设置及其使用 Stateflow 模块使用函数来处理在Stateflow 图中需反复处理的动作或判断。 在真值表中,用户可以用条件、决策和动作来做逻辑判断,并执行相应的动作。 对于纯粹的逻辑来讲,真值表比图形函数更容易编写、维护,也更容易阅读。真值表还可以告诉用户是否对于指定的条件做出了足够的或过多的决策。 10、真值表的设置及其使用 Stateflow 使用真值表函数实现逻辑决策及相应动作的执行。 Stateflow 真值表含有条件、决策和动作。 10、真值表的设置及其使用 每个Decision(决策)列隐含着各个条件的“与”操作。表12.1 中Decision1 列中,当x==1 为真,而y==1 和z==1 同时为假时,Decision1 为真。 执行过程中,Stateflow 会从Decision1 开始判断真值表中的每个决策,如果哪个Decision为真,就执行该Decision 对应的动作。如当x==1 为真,而y==1 和z==1 同时为假时,Decision1为真,执行动作将t 置为1。 表中的最后一个决策称为缺省决策,它包含着除了前面列举的决策外的所有其他决策。如果Decision1~3 都是假的,则Default Decision 自动为真,执行其对应的动作,将t 值置为4。 10、真值表的设置及其使用 单击M文件图标后将其拖入工作区,在左上图中问号处单击写入MATLAB 函数名及其形参名,如MaxMin(x) 双击新建的M文件会出现真值表编辑窗口,当内嵌窗口不能实现所需功能,我们可以在该窗口编辑所需函数 10、真值表的设置及其使用-真值表编辑窗口 单击
增添条件编辑表和动作编辑表中的行数。 单击
增添Decision 决策的列数 12、含并行执行状态的Stateflow图 单一状态(Exclusive State 或称为Or State),单一状态的边界是实线。单一状态的最大特征是同一时间,父状态中仅有一个子状态可以处于激活状态。 并行状态(Parallel State 或称为And State)的边界是虚线,并行状态的特点是父状态中的多个子状态可以同时处于激活状态。 并行状态在状态图中的位置决定着其激活的顺序。位于上部的状态较位于下部的状态较早被激活,同一高度层中,位于左边的状态较位于右边的状态较早被激活。激活的顺序依照上-下,左-右的原则。 12、含并行执行状态的Stateflow图
在Stateflow 编辑界面的空白处,右击鼠标,在弹出的下拉菜单中选择Decomposition-Parallel(AND)即可将两个状态Fan1 和Fan2 设置为并行状态,表现为该两状态的边框变为虚线,且Stateflow 按照上下左右的原则,自动给出此两个并行状态执行的顺序,并在其右上角标出顺序号。 6、图形函数的设置及其调用 前面例子中的Stateflow 图中多次利用了条件关系式[temp&=120]。对于这种多次使用的关系式,我们可以设置一个图形函数Function,使用时调用这个函数即可。 状态流的图形函数是使用交汇连接工具和状态迁移工具绘制的状态流图形。 用户可以建立一个图形函数,在里面加入流程图,然后在状态的动作和迁移过程中反复调用。 因为调用函数时,函数必须执行完全,所以图形函数中不能含有状态。一个最小的图形函数至少要包含一个缺省状态迁移和一个终止的交汇连接工具。 要在一个 Stateflow 图添加一个图形函数Function,只需点击Stateflow 图中的图形函数工具
,移动鼠标至Stateflow 图中的适当位置,再点击一下鼠标左键即可。在图形函数function 后写入函数的返回变量及函数名 格式为:返回形参=函数名(形参); 回车后即可建立该图形函数。一旦建立了图形函数,用户可以在状态流的状态动作和状态迁移中反复调用它,调用的格式与函数的格式完全相同,只是需要将形参换成实际的参数变量。 这两个 工具必 须有! * 第 * 页 7、多层状态的嵌套 继续上面的例子:当系统开始
正在加载中,请稍后...拒绝访问 |
| 百度云加速
请打开cookies.
此网站 () 的管理员禁止了您的访问。原因是您的访问包含了非浏览器特征(3c98f80e429043cb-ua98).
重新安装浏览器,或使用别的浏览器您所在位置: &
&nbsp&&nbsp&nbsp&&nbsp
基于SimulinkStateflow模型的成员开发环境的研究.pdf 47页
本文档一共被下载:
次 ,您可全文免费在线阅读后下载本文档。
下载提示
1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。
2.该文档所得收入(下载+内容+预览三)归上传者、原创者。
3.登录后可充值,立即自动返金币,充值渠道很便利
需要金币:200 &&
优秀硕士毕业论文,完美PDF格式,可在线免费浏览全文和下载,支持复制编辑,可为大学生本专业本院系本科专科大专和研究生学士硕士相关类学生提供毕业论文范文范例指导,也可为要代写发表职称论文提供参考!!!
你可能关注的文档:
··········
··········
国防科学技术大学
硕士学位论文
基于Simulink/Stateflow模型的成员开发环境的研究
姓名:田新华
申请学位级别:硕士
专业:控制理论与控制工程
指导教师:黄柯棣
国防科学技术大学研究生院学位论文
和仿真领域的体系结构,它为各种类型的仿真提供了一个通用的集成框架。联邦成员是
HLA体系中的仿真部件互操作和可重用的基础,它的开发过程包括实体模型的开发和对象
模型的开发。对象模型的开发可以使用OMDT、联邦框架生成工具等产生相应的模型代码,
但是实体模型的开发则往往需要使用各个学科领域专门的模型开发工具。将各种实体模型
开发工具集成到HLA框架中来是目前仿真界研究的热点问题之一。论文研究的主要工作
下,.文章对实现这种集成所采用的各种技术和原理以及实现的过程进行了详细介绍。
们的实现原理,并对本文选择采用的集成方式(模型中间C代码嵌入HLA运行时间框架
的方式)作了说明。接着,论文针对这种集成方式提出了研究所应采取的技术路线。然后,
论文依据此技术路线从分析模型的中间C代码结构入手,分别对描述连续和离散采样的动
的C程序的结构(包括其运行时间框架,数据结构以及其外部接口)作了深入的分析,并
根据分析的结果,提出了对模型进行HLA接口扩展的方式和实现的手段。在分析展开的
过程中,论文指出了实现HLA接口扩展必需考虑并处理的问题:包括模型外部接口的对
象化封装,模型运行时间框架的修改,时间推进的一致性问题处理;在Stateflow模型中,
还需解决并发事件的处理,接收交互后对外部导入事件的事件广播的处理,模型导出事件
骤,因此,论文也对RTW和与其关联的TLC(TargetLanguageCompiler)作了简要韵介绍。
在完成上述分析工作的基础上,论文综合对这些问题的处理方法提出了对模型tl动进
行HLA接口扩展的解决方案。该方案的核心内容是通过定义模型接口映射表来使
HLA接口扩展的软件工具知道如何进行模型外部接口的HLA扩展。然后论文对就此方案
T001)作了介绍。
国防科学技术大学研究生院学位论文
tofacilitate
Architecture),has
interoparabilityamong
resueofsimuliationand
simulations
components.Itprovides
HLAfederateiS
kindsofsimulation.A
architecture
正在加载中,请稍后...当前位置: >>
3 Stateflow建模与应用1021final
第 3 章 Stateflow 建模与应用Stateflow 是有限状态机(finite state machine)的图形工具,它通过开发有限 状态机和流程图扩展了 Simulink 的功能。 Stateflow 使用自然、 可读和易理解的形式, 可使复杂的逻辑问题变得清晰与简单,并且还与 MATLAB\Simulink 紧密集成,为包 含控制、优先级管理、工作模式逻辑的嵌入式系统设计提供了有效的开发手段,是 本书的核心内容之一。 读者在 5~8 章将看到 Stateflow 应用于 MCU 器件的嵌入式开 发,尤其显得得心应手,一些采用传统方法难于实现的算法,如果利用 Stateflow 建 模却非常容易。 大到导弹、 航空航天器的控制, 小到点亮一个发光二极管, Stateflow 都非常称职。Stateflow 状态图模型,还可利用 Stateflow Coder 代码生成工具,直 接生成 C 代码。 Stateflow 的主要功能包括: ? 使用层次化、可并行的、有明确执行语义的元素,来描述复杂的逻辑系统。 ? 采用流程图定义图形化函数。 ? 利用真值表实现表格形式的功能。 ? 使用临时逻辑处理状态转移与事件。 ? 支持 Mealy 和 Moore 有限状态机。 ? 可集成用户自定义的 C 代码。 ? 可用动画的形式显示状态图的仿真运行过程,并可记录数据。 ? 调试器使用图形化断点进行单步调试,并可观察其中的数据。 本章主要内容: ? Stateflow 工作原理与基本概念 ? 建立 Stateflow 状态图与流程图 ? Stateflow 的层次结构与并行机制 ? Stateflow 应用3.1Stateflow 基本概念Stateflow 对象可分为图形对象与非图形对象。 图形对象有状态、历史节点、迁移、默认迁移、连接节点、真值表、图形函数、 Embedded MATLAB 函数、盒函数、Simulink 函数;非图形对象有事件、数据、目 标。本节首先介绍常用的对象:状态、迁移、数据、事件的概念和使用,连接节点 留待 3.3 节、历史节点留待 3.4 节,其余对象留待 3.5 节说明。 Stateflow 状态机使用一种基于容器的层次结构管理 Stateflow 对象,也就是说, 一个 Stateflow 对象可以包含其他 Stateflow 对象。 最高级的对象是 Stateflow 状态机,它包含了所有的 Stateflow 对象,因此也就 包含了 Simulink 中的所有 Stateflow 状态图,以及数据、事件、目标对象。 同样地,状态图包含了状态、盒函数、函数、数据、事件、迁移、节点与注释 事件(note events) 。用户可以使用这一系列对象,建立一个 Stateflow 状态图。而 具体到一个状态,它也可以包含上述的对象。 图 3.1.1 抽象地说明了这样的关系,而图 3.1.2 则具体地说明了 Stateflow 状态 机的组成。状态机数据/ 数据/ 事件 事件 目标 目标状态图迁移 迁移 数据/ 数据/ 事件 事件 节点 节点 标注 标注状态/盒函数/函数状态/ 状态/ 盒函数/ 盒函数/ 函数 函数数据/ 数据/ 事件 事件标注 标注迁移 迁移节点 节点图 3.1.1Stateflow 层次机构(数据字典) 图 3.1.2 Stateflow 状态机的组成3.1.1 状态图编辑器在 Simulink 模块库浏览器,找到 Stateflow 模块,如图 3.1.3 所示,添加入模型 窗口,如图 3.1.4 所示。图 3.1.3 Stateflow 模块 用户也可以使用以下命令,建立带有 Stateflow 状态图的 Simulink 模型,如图 3.1.4 所示,同时打开 Stateflow 模块库,如图 3.1.5 所示。 &&sf 图 3.1.4 带有 Stateflow 状态图的 Simulink 模型图 3.1.5 Stateflow 模块库 用户还可以直接使用以下命令,快速建立带有 Stateflow 状态图的 Simulink 模 型。 &&sfnew 双击 Chart 模块,打开 Stateflow 编辑器窗口,如图 3.1.6 所示,左侧工具栏列 出了 Stateflow 图形对象的按钮。 图 3.1.6 Stateflow 编辑器窗口3.1.2 状态状态可以理解为事件驱动系统中的模式,可分为激活与非激活状态,而状态是 否激活则是由状态图中的事件与条件决定的,若没有预先定义的事件或条件发生, 状态将一直保持其原先的激活或非激活状态。 1. 状态的层次结构 状态可以包含除了目标(详见第 3.6.6 节)以外的所有 Stateflow 对象,所以状 态内部可以有其他状态,如图 3.1.7 所示,处于外层的 A 称作超状态(或父状态), 处于内部的 B 称作子状态。 每一个状态都有其父状态,图 3.1.7 中,状态 A 的父状态就是 Stateflow 状态图 本身。图 3.1.7 超状态与子状态 2. 状态的横向结构 在 Stateflow 状态图的顶层或某一超状态下, 通常并存有多个状态, 它们之间的 关系可分为互斥与并行。 (1) 互斥状态(OR) 互斥状态的矩形框边缘显示为实线,同一级的互斥状态,至多允许激活一个状 态。如图 3.1.8 所示的状态图,状态 A 与状态 B 是互斥的,它们只能有一个处于激 活状态;当状态 A 被激活时,同样其子状态 A1 与 A2 也只能有一个处于激活状态。 图 3.1.8 互斥状态 (2) 并行状态(AND) 并行状态的矩形框边缘显示为虚线,同一级的并行状态,可在同一时刻被激活。 如图 3.1.9 所示的状态图。状态 A 与状态 B 是并行的,它们可同时处于激活状态; 子状态 A1 与 A2 也同时处于激活状态,而子状态 B1 与 B2 只能有一个处于激活状 态。图 3.1.9 并行状态 状态层次结构与并行机制的详细概念与应用,见 3.4 与 3.5 节。 3. 状态标签 状态名仅是状态标签的一部分,完整的标签格式如下,第一行是状态名,以下 若干行是各类动作,用户可以设置全部或部分的状态动作,当然也可以不设置任何 动作。 name/ 状态名 entry: entry actions 进入该状态时的动作 during: during actions 处于该状态时的动作 exit: exit actions 退出该状态时的动作 on event_name: on event_name actions 某事件发生时的动作 bind: events, data 指定需要限制作用范围的事件与数据 ①状态名 状态名可由字母、数字、下划线组成,如果状态名后跟随的是回车符,则斜线 是可有可无的。根据 Stateflow 的分层结构,同级的各个子状态不允许重名,但不同 级的状态则不受限制。 图 3.1.10 所示的 Stateflow 状态图是有效的,尽管看上去状态 C1、C2 有重名 现象,但在 Stateflow 分层结构中,它们的全名分别是: A.On A.Off B.On B.Off 图 3.1.10 状态名 ②状态动作 状态动作如表 3.1.1 所列。 表 3.1.1 状态动作类型 动作类型 entry during exit bind on event_name on after(n,event_name) on before(n,event_name) on at(n, event_name) on every(n,event_name) 缩写 en du ex 无 无 无 无 无 无 说明 进入当前状态时的动作 处于当前状态,并且某事件发生时的动作 Executes when the state isactive and a specific eventoccurs 离开当前状态时的动作 约束一个事件或数据,使得仅当前状态及 其子状态有权限广播该事件或修改该数据 当前状态接收 1 次广播事件时的动作 当前状态完整接收 n 次广播事件后的动作 当前状态完整接收 n 次广播事件前的动作 当前状态完整接收 n 次广播事件时的动作 当前状态每接收 n 次广播事件时的动作每个动作类型,用户可指定多个具体动作,每个动作之间以回车、分号、逗号 区隔,动作类型关键词后必须跟随一个半角冒号。 (1) entry 动作 关键词为 entry(或缩写为 en) 。如果用户在状态名后加入斜线,并直接跟随具 体动作,则该动作默认为进入动作。如图 3.1.11 所示,进入状态 A 时,y=3,同时 又执行 y++,最终的结果 y=4。 图 3.1.11 entry 动作 (2) during 动作 关键词为 during(或缩写为 du) 。如图 3.1.12 所示,进入状态 A 时,y=3,同 时不断执行 y++。若求解器的定点步长取 0.2,仿真时长取 2,则最终的结果 y=13。图 3.1.12 during 动作 (3) exit 动作 关键词为 exit(或缩写为 ex) 。如图 3.1.13 所示,系统处于状态 A,当 A 的激 活时间达到 5 个仿真步长,退出状态 A,进入状态 B,最终的结果 y=4,如图 3.1.14 所示。图 3.1.13 exit 动作图 3.1.14 输出结果 (4) 广播事件动作 表 3.1.1 所列的广播事件动作,能实现各种的事件触发。 以单次广播事件动作为例,关键词为 on event_name,其中 event_name 表示 某一广播事件名,事件名应是唯一的。如图 3.1.15 所示,系统处于状态 A,当检测 到事件 stop,立即执行 c()。 图 3.1.15 广播事件动作 (5) bind 动作 关键词为 bind。如图 3.1.16 所示,变量 y、事件 start 被绑定在状态 A,这表示 仅有 A 状态及其子状态有权限修改变量 y 并广播事件 start, 其他状态 B 能够读取变 量 y、监听到事件 start,但无权修改变量 y、广播事件 start。图 3.1.16 bind 动作 若运行该状态图,系统提示变量 y 仅能由状态 A 及其内部的状态迁移修改,事 件 start 仅能在状态 A。图 3.1.17 错误提示 与其他动作不同,bind 动作不需要判断当前状态是否已激活,也就是说它在整 个 Stateflow 状态图范围内都是有效的,因此不同状态不允许约束同一个变量与事 件。 如图 3.1.18 所示,状态 A、B 同时约束了变量 y,系统提示这是不允许的。 图 3.1.18 无效的 bind 动作图 3.1.19 错误提示3.1.3 迁移1.迁移 Stateflow 状态图使用一条单向箭头曲线表示迁移,它将两个图形对象连接起 来,多数情况下,迁移是指系统从源状态向目标状态的转移。 在迁移曲线上加上标签, 可以指定系统在何种条件下从源状态向目标状态转移。 如图 3.1.20 所示,当系统处于状态 A1 时间达到 1 秒,即向状态 A2 迁移。图 3.1.20 状态迁移 2. 默认迁移 默认迁移是一种特殊的迁移形式,它没有源对象。用于指定同一级有多个互斥 状态并存时,首先激活的状态。 某些情况下,默认迁移也可以加入标签,限制其所指向目标状态的激活。 如图 3.1.21 所示,状态 A1 与 A2 是互斥的,当它们的父状态 A 激活时,状态 A1 也同时激活。 图 3.1.21 默认迁移 3. 迁移标签 迁移标签的完整格式如下,它可用于一般迁移与默认迁移,如图 3.1.22 所示。 event[condition]{condition_action}/transition_action图 3.1.22 完整的迁移标签 各字段的意义如表 3.1.2 所示: 表 3.1.2 迁移标签字段 标签字段 event [condition] {condition_action} /transition_action 引发迁移的事件 条件动作与迁移的发生条件 当条件为真时,执行的动作 发生迁移,进入目标状态前所执行的动作 说明① 事件 指定迁移的触发事件。如果用户另行指定了触发条件,则当条件为真,且发生 该触发事件时,即发生迁移。这是个可选项,如果用户不指定触发事件,则任何事 件都能够引发该迁移。多个触发事件之间使用逻辑或运算符“|”分隔。 如图 3.1.20, 当条件 after(1,sec)为真时, 触发了迁移, 系统状态从 A1 变成 A2。 ②条件 条件是一个布尔表达式,当它为真时,一旦发生指定的触发事件,则发生迁移。 条件表达式的前后必须使用方括号“[ ]”包围。 如图 3.1.23 所示,当条件[ y&=3 ]为真时,发生迁移。 ③条件动作 当条件表达式为真时,立刻执行条件动作。若事先未指定条件,系统则假设条 件为真,并执行该条件动作。 如图 3.1.23 所示,当条件[ y&=3 ]为真,条件动作{ y=10 }立刻执行。 ④迁移动作 当迁移目标有效时,执行迁移动作。若迁移标签由多个字段组成,则当整个标 签有效时,执行迁移动作。 如图 3.1.23 所示,当条件[ y&=3 ]为真,且目标状态 B 有效时,发生迁移,并 执行迁移动作 z=20。运行结果如图 3.1.24 所示:图 3.1.23 迁移条件与动作图 3.1.24 输出结果 4. 迁移有效条件 对于非默认的迁移,当源对象处于激活状态的且迁移标签有效时,发生迁移; 对于默认迁移,当其父状态被激活时,发生迁移。 表 3.1.3 列出了迁移标签的有效条件,用户可以根据需要,选择性地输入迁移 标签的部分或全部字段。 表 3.1.3 迁移标签有效条件 标签内容 仅事件 事件与条件 仅条件 仅行动 空 标签有效条件 该事件发生 该事件发生及条件为真 任何事件发生及条件为真 任何事件发生 任何事件发生 3.1.4 数据与事件图 3.1.1 所示的数据字典中,数据与事件是合并在一个圆圈内的,这表明他们 有相似之处,这里合并介绍。1. 数据数据是非图形的对象,它有一个很重要的特性:作用域,用户在使用数据时必 须明确定义该特性。 根据作用域的不同,数据可分为: ? Stateflow 状态图本地数据(Local) ; ? 自外部 Simulink 模块输入的数据(Input from Simulink) ; ? 向外部 Simulink 模块输出的数据(Output from Simulink) ; ? 临时数据 ? 定义在 MATLAB 工作空间的数据; ? 常数(Constant) ; ? 向 Simulink 模型与 Stateflow 状态图外部的目标(代码)导出的数据; ? 自 Simulink 模型与 Stateflow 状态图外部的源代码导入的数据。 数据的简单使用,见 3.2.4 小节。2. 事件事件也是非图形的对象,它驱动着整个 Stateflow 状态图的运行。如同数据,事 件同样有它的作用域, 根据作用域的不同,事件可分为: ? Stateflow 状态图本地事件; ? 自外部 Simulink 模块输入的事件; ? 向外部 Simulink 模块输出的事件; 事件的简单使用,见 3.2.4;事件的分类,见 3.5 各小节。3. 动作Stateflow 状态图支持状态动作、 条件动作、 迁移动作, 已在上文做了简要介绍。 这里所说的动作可以是一个函数调用,广播事件,数学运算等等。 例如: 函数调用:ml.log10(x);?? 事件广播:SS?? 数学运算:x=1;y=2;z=x+y;??3.1.5 对象的命名规则以上简要介绍了常用对象的概念,用户可以使用任意的字母、数字与下划线的 组合为这些对象命名,但名称不能以数字开头,中间也不能有空格。 由于 Real-Time Workshop 代码生成工具的限制,对象的名称不能超过一定长 度, 用户可以在模型参数设置对话框的 Real-Time Workshop→Symbols 面板进行修 改,默认的长度是 31,最大的长度是 256,如图 3.1.25 所示。图 3.1.25 设置对象名称的长度 表 3.1.4 列出了一些关键字,它们是 Stateflow 动作语言的组成部分,因此是不 能用来为对象命名的。 表 3.1.4 关键字 关键字 hasChanged,hasChangedFrom,hasChangedTo complex, imag, real boolean, double, int8,int16, int32, single,uint8, uint16, uint32 cast, fixdt, type send change, chg, tick, wakeup false, inf, true, t matlab, ml bind, du, during, en,entry, ex, exit, on in after, at, before, every,sec, temporalCount 在 Stateflow 中的用途 变更监测 复数数据 数据类型 数据类型操作 明确事件 隐含事件 标志位 MATLAB 函数与数据 状态动作 状态激活 时间逻辑3.2Stateflow 状态图长跑比赛时,通常要用到以圈计时的方法,它的意思是:计时器初次开启时,2 组数码管皆清零; 运动员出发时, 按下 Start 按钮开始计时, 数码管 1 显示实时时间; 第一次回到起点, 表示跑完一圈, 这时按下 LAP 按钮, 数码管 2 显示当前的时间值, 表示一圈所花费的时间,但比赛仍在进行,因此计时器仍然在计时;再次按下 Start 按钮,2 组数码管同时显示最后的时间;第三次按下 Start 按钮,2 组数码管清零, 回到初始状态。本节以此为例,说明 Stateflow 状态图的建立过程。3.2.1 状态1.添加状态 新建一个空白的 Stateflow 模型,单击状态按钮,并在 Stateflow 窗口的适当位 置再次单击,加入一个状态,如图 3.2.1 所示。 在加入之前,用户可随时按下键盘的 ESC 键,或再次单击按钮,取消添加。图 3.2.1 添加状态 2.状态命名 在状态矩形框左上角的编辑提示符后,输入状态的名称,如 stop,如图 3.2.2 所示。若需要修改状态名,可将鼠标移至名称附近,待光标变成编辑样式时,再单 击修改,如图 3.2.3 所示。图 3.2.2 状态命名图 3.2.3 状态名修改3.添加子状态 将鼠标移至状态矩形框 4 个角落的任意一个,调整其大小,如图 3.2.4 所示。图 3.2.4 调整状态框 再按步骤①、②,添加状态 Reset、Finished,放置在状态 Stop 的矩形框内, 这时 Stop 为超状态,Reset、Finished 为子状态,如图 3.2.5 所示。图 3.2.5 父状态与子状态3.2.2 迁移1. 添加迁移 将鼠标移至源状态矩形框的边缘,当光标变成十字时,如图 3.2.6 所示,按下 左键并拖向目标状态的边缘,然后释放,如图 3.2.7 所示,即添加了一个迁移。图 3.2.6 迁移起点 2. 添加默认迁移 单击图 3.2.7 迁移终点,将鼠标移至默认状态矩形框的水平或垂直边缘,如图 3.2.8 所示。 图 3.2.8 选择默认迁移 再次单击,即添加了一个默认迁移,如图 3.2.9 所示。图 3.2.9 添加默认迁移 由于 Stop 是父状态,还需要针对其中的子状态,设置默认迁移,如图 3.2.10 所示,关于 Stateflow 的层次结构,详见 3.4 节。图 3.2.10 添加子状态默认迁移 3. 迁移变更 鼠标放置在迁移的起点或终点, 当光标变成圆圈时 (图 3.2.11) 按住鼠标左键, , 可将该端点移至其他状态,如图 3.2.12 所示。 图 3.2.11 开始迁移变更图 3.2.12 完成迁移变更将默认迁移的起点移至某一状态,即转换为一般迁移;将一般迁移的起点悬空, 即转化为默认迁移, 如图 3.2.13 所示, 若迁移终点悬空, 则该迁移无效, 如图 3.2.14 所示。图 3.2.13 迁移起点变更 图 3.2.14 迁移终点变更 4. 迁移标签 新建的迁移标签不包含任何文字信息,用户单击迁移曲线一次,曲线上方显示 “?”如图 3.2.15 所示:图 3.2.15 添加迁移标签 将鼠标移至“?”附近,再次单击,当显示编辑光标时,可编辑迁移标签,如图 3.2.16 所示。 图 3.2.16 编辑迁移标签 完成编辑后,将鼠标放在标签的任意位置,按住左键并拖动,调整标签的位置, 如图 3.2.17 所示。图 3.2.17 移动迁移标签3.2.3 计时器状态图根据以圈计时的特点,整个系统可分为 2 个父状态:停止与运行。停止状态包 含 2 个子状态:计时器清零 Reset、计时器停止 Finished;运行状态也包含 2 个子 状态:计时器运行 Running、以圈计时 LAP。如图 3.2.18 所示:图 3.2.18 添加 4 个状态 再根据各状态之间的联系,添加默认迁移、迁移以及迁移标签,如图 3.2.19 所 示。图中的迁移标签 start 表示按下 start 按钮这个事件,而 LAP 则表示按下 LAP 按钮。 图 3.2.19 添加迁移及迁移标签3.2.4 数据与事件以圈计时需要 2 组数码管显示当前以及记录的分、秒、百分秒,另有两个按钮, 为此需要添加 6 个数据与 2 个事件。数据是向外输出的,而事件是自外输入的。 添加数据或事件的方法有两种:使用菜单项 Add 或使用模型浏览器(Model Explorer)。前者的优势是添加方便,但菜单项仅提供了添加功能,无法通过菜单 删除已添加的数据或事件,因此我们推荐用户使用模型浏览器。 为了照顾读者的不同需求,本文仍旧介绍两种添加方式。 1. 菜单项 在 Stateflow 编辑器窗口,选择菜单项 Add→Data→Output to Simulink,如图 3.2.20 所示。图 3.2.20 添加输出数据 在 Name 栏填入输出变量名 min,另外用户在 scope 栏还可以再次决定变量的 作用域,如图 3.2.21 所示。 图 3.2.21 修改数据名及作用范围 2. 模型浏览器 在 Stateflow 状态图的顶层(即不选中任何图形对象),选择菜单项 Tools→ Explore,或直接按下 Stateflow 编辑器窗口的工具栏按钮 ,打开模型浏览器,并确认已选中左侧模型结构图中的 Chart 节点,如图 3.2.22 所示。图 3.2.22 模型浏览器 在浏览器窗口的工具栏找到按钮 、 与 ,添加一个数据/事件或删除对应项。在中部窗口选中数据/事件的条目,右侧窗口即显示它的属性,如图 3.2.23 所 示。与菜单项方法不同的是,使用浏览器添加的数据/事件,默认的作用域是本地 (Local),用户需要手动修改为外部输入或外部输出。 图 3.2.23 利用模型浏览器修改数据 对于事件,用户还需指定它的触发方式,Rising 表示上升沿、Failing 表示下降 沿,而 Either 表示上升或下降沿皆可触发,本例的两个输入事件 start 与 LAP 皆选 用 Either 方式触发,如图 3.2.24 所示。图 3.2.24 利用模型浏览器修改事件 有多个数据或事件时,用户还可以指定它们的端口号,合理地排列这些端口, 将有利于以后的 Simulink 模块连线。如图 3.2.25 所示,是完整的数据与事件列表。 图 3.2.25 数据与事件列表3.2.5 动作上文提到,显示时间值可以定义为状态动作,也可以定义为迁移动作。为不失 一般性,本小节分别说明这两种动作的定义方法。 计时器复位时,2 组数码管皆应清零,因此设置子状态 Reset 的进入动作为: Reset entry: min=0;sec=0;percent=0; minbuf=0;secbuf=0;percentbuf=0; 按下 LAP 按钮或再次按下 start 时,数码管 2 都必须显示当前时刻,因此设置 子状态 LAP 与 Finished 的进入动作为: Finished entry: minbuf = secbuf = percentbuf = 添加了动作的状态图如图 3.2.26 所示: 图 3.2.26 动作定义在状态 当然用户可以将显示时间值定义为迁移动作。为此按图 3.2.27 调整状态图,添 加节点与迁移动作。对照图 3.2.26,用户应很容易理解图 3.2.27 的意义。图 3.2.27 动作定义在迁移 不过目前的 Stateflow 状态图还缺少最关键的时钟程序,该过程详见 3.3 节。3.2.6 自动创建对象实际建模时,随着思路的不断扩展与成熟,状态、迁移、数据、事件、动作等 等各种图形与非图形对象,总是交替着添加,很少按照上述过程逐步进行。这就难 免发生遗漏,尤其是大型、多层次的 Stateflow 状态图。 当用户完成状态图的编辑,按下仿真按钮时,系统首先要进行语法检查,如果 发现错误,则给出提示。如果是某些数据或事件未定义,用户可使用随后出现的 Symbol Autocreation Wizard 向导,自动创建缺失的对象。 例如,用户可以在图 3.2.26 中,任意添加一个状态动作 y=1,任意添加一个迁 移事件 stop,如图 3.2.28 所示。 图 3.2.28 添加一个状态动作 按下仿真按钮,系统首先给出语法错误提示,如图 3.2.29 所示:图 3.2.29 错误提示 系统进一步分析该语法错误,是由于状态图中存在无法处理的符号,因此弹出 Symbol Autocreation Wizard 向导与向导使用说明,如图 3.2.30 所示,若用户已能 够熟练使用,可径自忽略该说明。 图 3.2.30 向导使用说明 Symbol Autocreation Wizard 向导建议,应另行创建数据 y 与事件 stop,如图 3.2.31 所示。图 3.2.31 自动创建对象向导 用户可以不断单击 Scpoe 与 Proposed Parent 的内容, 修改数据/事件的作用域 与父对象,如图 3.2.32 所示。 图 3.2.32 修改作用域与父对象 用户若接受向导的建议,则单击数据/事件前的空白处,选中该条目,之后按下 Create,创建对象,如图 3.2.33 所示。图 3.2.33 创建对象3.3 Stateflow 流程图 3.3.1 流程图与节点3.1 与 3.2 节介绍了 Stateflow 状态图的基本概念与创建过程。状态图的一个特 点是,在进入下一个仿真步长前,它会记录下当前的本地数据与各状态的激活情况, 供下一步长使用。而流程图只是一种使用节点与迁移来表示条件、循环、多路选择 等逻辑的图形,它不包含任何的状态。 由于迁移(除了默认迁移)总是从一个状态到另一个状态,节点之间的迁移只 能是一个迁移段。因此流程图可以看作是有若干个中间支路的一个迁移,一旦开始 执行, 就必须执行到终节点 (没有任何输出迁移的节点) 不能停留在某个中间节点, , 也就是说必须完成一次完整的迁移。 从另一个角度来看,节点可以认为是系统的一个判决点或汇合点,它将一个完 整的迁移分成了若干个迁移段。因此可以将几个相同的迁移段合并为一个,用一个 迁移表示多个可能发生的迁移,简化状态图,由此生成的代码也更加有效 对于以下情况,用户应首先考虑使用节点: ? if-else 判断结构、自循环结构、for 循环结构; ? 单源状态到多目标状态的迁移; ? 多源状态到单目标状态的迁移; ? 基于同一事件的迁移; 注意:事件无法触发从节点到状态的迁移。 建议: 用户可以把流程图封装成一个图形函数 (详见 3.6.2 节) 便于在 Stateflow , 的任意位置调用。 3.3.2 建立流程图1. 手动建立 建立流程图的过程与建立状态图的过程相似,以一段简单的代码为例,手动建 立流程图。 if percent==100 {percent=0; sec=sec+1;} else if sec==60 {sec=0; min=min+1;} end end ① 起始节点 单击 按钮,添加起始节点。如图 3.3.1 所示:图 3.3.1 添加节点 ② 条件节点与终节点 根据代码的执行过程,逐一添加条件节点 A1、B1、C1,终节点 A2、B2,以及 节点间的迁移与迁移标签,如图 3.3.2 所示。 图 3.3.2 流程图 流程图运行过程如下: 1. 系统默认迁移进入节点 A1,如果条件[percent==100]为真,执行 {percent=0;sec=sec+1;},并向终节点 A2 迁移; 2. 如果条件[percent==100]不为真,向 B1 节点迁移,继续判断如果条件 [sec==60]为真,执行{sec=0;min=min+1;},并向终节点 B2 迁移; 3. 如果不满足任何条件,则向终节点 C1 迁移。 ③ 节点与箭头大小 对于某些重要的节点或迁移,用户可以调整其节点大小与迁移箭头的大小,突 出其地位。例如,选择节点 C1 的右键菜单项 Junction Size→16,如图 3.3.3 所示, 放大节点;选择节点 A1 的右键菜单项 Arrowhead Size → 20,放大指向该节点的 所有迁移箭头,如图 3.3.4 所示。图 3.3.3 节点大小 图 3.3.4 箭头大小 ④ 优先级 两个判断节点 A1、B1,均有两条输出迁移,分别标记了数字 1、2,这表示迁 移的优先级。默认情况下,Stateflow 状态图使用显性优先级模式,用户可以自行修 改各个迁移优先级。 例如,选择迁移曲线的右键菜单项 Execution Order,将优先级由 1 降低为 2, 如图 3.3.5 所示。修改了某一输出迁移的优先级,系统会自动调整同一节点另一迁 移的优先级。图 3.3.5 迁移优先级 为避免用户错误地设置优先级,Stateflow 提供了另一种模式:隐性优先级。选 择编辑器菜单项 File → Chart Properties,取消 User specified state/transition execution order 前的复选框,启用隐性模式,如图 3.3.6 所示。 图 3.3.6 自动设置迁移优先级 使用这种模式时,系统根据以下规则,自动设置迁移优先级,从高到低排列为: 1. 既有事件又有条件的迁移 2. 仅有事件的迁移 3. 仅有条件的迁移 4. 不含任何限制的迁移 注意:同一个 Stateflow 状态图,只能选用一种优先级模式,但对于有多个状态 图的 Simulink 模型,则不受此限制。 2. 自动建立 对于简单的流程图,手动建立难度不大,而对于稍复杂的逻辑,用户难免会感 到无从下手。Stateflow 提供了快速建立流程图的向导,它可以生成 3 类基本逻辑: 判断、循环、多条件。本小节使用向导,重建图 x 的流程图。 ① 单击编辑器菜单项 Patterns→Add ..., 选择流程图的类型, 如图 3.3.7 所示。图 3.3.7 流程图向导菜单 ② 这里选择 Patterns → Add Decision → If-Elseif-Else...,在随后打开的对 话框中输入判断条件与对应的动作,如图 3.3.8 所示。 图 3.3.8 新建流程图对话框 ③ 生成的流程图如图 3.3.9 所示:图 3.3.9 流程图 3. 两种方式的对比 尽管用户可以手动建立流程图,但使用流程图向导的优势也是显而易见的: ? 任何一种流程图都可归结为判断、循环、多条件,或者三者的组合,因此 皆可以使用向导自动生成; ? 使用向导生成的 流程图符 合 MAAB(MathWorksAutomotive Advisory Board)规则,这有利于后期模型检查; ? ?各种流程图的外观基本一致; 将设计好的流程图,另存为模板,便于重用。3.4 层次结构 3.4.1 层次的概念Stateflow 的对象具有层次性, 一个 Stateflow 对象可以包含其他 Stateflow 对象, 例如状态内若包含其他状态,则形成父状态,其内部状态称为子状态。当状态具有 第二个层次时,状态就构成了层次。 状态具有了层次,迁移自然也具有了层次,Stateflow 允许在不同层次状态之间 存在转移。如果迁移穿越了父状态的边界直接到达了低层次的子状态,则被称之为 超迁移。 在状态图中使用层次有如下几个目的: ? 使用层次,可以将相关的对象组合在一起,构成族群; ? 可以将一些通用的迁移路径或者动作组合成为一个迁移动作或路径,简化 模型; ? 适当地使用层次,可以有效地缩减生成代码的大小,也能够提高程序执行 的效率和可读性。3.4.2 迁移的层次1 内部迁移 内部迁移是指从父状态边缘内部出发,终止于子状态外边缘的迁移,迁移始终 处于父状态的内部,不会退出源状态。 在交通灯系统中,同一个父状态 PowerOn 存在红黄绿三个子状态,它们需要不 停地转换,但除非发生 PowerOff 事件,不会退出父状态,对于这样的逻辑过程,读 者可能习惯使用节点将三种状态的迁移联系起来,如图 3.4.1 所示。 图 3.4.1 带有节点的迁移 使用了内部迁移,可直接从父状态激活相应的子状态,不必经过节点,大大简 化状态图,如图 3.4.2 所示。图 3.4.2 内部迁移状态图 2 层次化迁移的优先级 与状态类似,迁移也具有层次性,迁移所属的层次是由其父状态、源状态和目 标状态决定的。因此,当多个迁移同时有效时,Stateflow 需要有一个层次化迁移优 先级机制来判断迁移顺序。 层次化迁移的优先级规则为:从高层次到低层次检测;从外部迁移到内部迁移 检测;同一层次内,超转移优先。 如图 3.4.3 所示,图表激活时,默认迁移激活状态 A,继而状态 A.a1 被次级默 认迁移激活,这时按以下优先级检测迁移是否有效: ① 检测高层 A,B 状态的外部迁移是否有效(event1,event2) ; ② 检测高层 A,B 状态的内部迁移是否有效(event3) ; ③ 检测低层 a1,a2,b1 状态的超迁移是否有效(event4) ; ④ 检测父状态 A 内部子状态间的迁移是否有效(event5,event6) 。 图 3.4.3 层次化的迁移3.4.3 历史节点在状态图的顶层或一个父状态里或放置一个历史节点,它便能能记录退出父状 态时,正处于激活状态的子状态,当再次进入父状态时,则默认激活上一次所记录 的子状态,而不是激活默认迁移的状态。 历史节点的作用域仅限于它所存在的层级。 如图 3.4.4,父状态 A2 中加入了历史节点,因此当第 1 次激活 A2 状态时子状 态 C1 被激活,满足迁移条件时 C2 被激活,但此后 A2 状态向 A1 状态的迁移将优 先发生,C2 状态不再向 C1 状态迁移。于是第 1 次激活 A2 状态时,被激活的子状 态是 C2,而不是 C1。读者可以从图 3.4.5 所示的输出看出上述的迁移过程。图 3.4.4 历史节点 图 3.4.5 运行结果 图 3.4.6 与图 3.4.7 是不包含历史节点的状态图及其运行结果,用户应详细比较 两者的区别。图 3.4.6 不含历史节点的状态图图 3.4.7 运行结果 3.4.4 子状态图子状态图其实就是其内部所包含的状态图的父状态。用户可以像操作父状态一 样为子状态图定义状态动作,迁移和默认迁移。与 Simulink 中的子系统类似,子状 态图隐藏了模型的细节,简化了图表。 以图 3.4.8 为例,在状态 A 中单击右键,在菜单中选择 Make Contents→ Subcharted。此时,A 状态变成了灰色,隐藏了内部细节,成为子状态,如图 3.4.9 所示。用户再次进行 Make Contents→Subcharted 操作,则可取消子状态图。图 3.4.8 建立子状态图图 3.4.9 子状态图 双击子状态图 A 可以看到其内部细节。利用 Stateflow 编辑器上的三个箭头工 具按钮,用户可以方便的在个层次图表间进行切换,如图 3.4.10 所示。 图 3.4.10 子状态图内部细节3.4.5 层次状态图中的流程图流程图中不包含任何状态,也不保留任何状态信息。流程图一旦激活,即由默 认迁移一直运行到终止节点为止。 如图 3.4.11 所示,当状态 A 处于激活状态时,B 事件发生则激活状态 B,这时 便执行状态 B 中的流程图,并且只执行一次,执行完成后 B 状态仍保持激活,直到 发生事件 A,退出 B 状态。图 3.4.11 状态中的流程图 3.5 并行机制状态可分为两大类: 互斥状态 exclusive (OR)和并行状态 parallel (AND)。 若在同 一个层次中含有多个互斥的状态, 状态不能同时被激活, 不能同时执行, Stateflow 在 中用实线框表示。相反,若同一层次中含有多个并行状态,则一旦父状态处于激活 状态,其并行子状态同时处于激活状态。3.5.1 设置状态关系在状态图编辑窗口的空白处,选择右键菜单项 Decomposition→Exclusive(OR) 或 Parallel(AND),可设置顶级状态的关系。如图 3.5.1 所示,状态 A 与状态 B 是并 行的。图 3.5.1 设置顶级状态关系 状态关系的设置仅对本级起作用,尽管状态 A 是并行的,但子状态 A1、A2 仍 是互斥的,若要修改,用户需要在状态 A 矩形框内的空白处,单击右键选择菜单项, 如图 3.5.2 所示。 图 3.5.2 修改状态关系3.5.2 并行状态活动顺序配置处于同一层次下的所有并行的状态应该在其父状态被激活的时候同时被激活, 但是它们的激活是按照一定顺序进行的。其默认激活顺序为:从上到下,从左到右。 并且在每个状态的右上角用数字标注,如图 3.5.3 所示。图 3.5.3 默认激活顺序 若用户希望改变其激活顺序。 例如将 LED 状态放在 Fan 之后激活, 可以先选中 LED 状态,在右键菜单中的 Excution Order 子菜单中改变激活顺序,如图 3.5.4 所 示。 图 3.5.4 改变激活顺序3.5.3 本地事件广播使用事件广播,可以在某个状态内部触发其他并行状态的执行,这样就可以在 系统的不同状态之间实现交互,让一个状态的改变影响其他状态。事件广播可以触 发状态动作、迁移动作和条件动作。使用广播之前,需要预先定义事件。 如图 3.5.5 所示,Led 状态和 Fan 状态为并行关系。 ① 当父状态 PowerOn 激活时, Led.Off 状态和 Fan.Off 状态同时被激活, Fan.Off 状态广播事件 ledon,于是 Led.Off 状态向 Led.On 状态迁移; ② 当 Led.On 状态满足迁移条件退出时,广播事件 fanoff,而此时 Fan.Off 状态 已向 Fan.On 迁移,于是响应事件 fanoff,向 Fan.Off 状态迁移。 图 3.5.5 本地事件广播3.5.5 直接事件广播使用直接事件广播可以避免在仿真过程中出现不必要的循环或递归、并能有效 的提高生成代码的效率。 用 send 函数直接事件广播 send 函数的完整格式为:send(event_name, state_name),使用该函数进行直接事 件广播,如图 3.5.6 所示。Stateflow 执行过程如下: ① 当并行超状态 Led 和 Fan 激活时,对应的子状态 Led.L1 和 Fan.F1 被激活, 子状态 Led.L1 执行状态动作 flag=1; ② Led.L1 至 Led.L2 的 迁 移 条 件 [flag==1] 为 真 , 于 是 执 行 条 件 动 作 send(event_1,Fan),向状态 Fan 广播事件 event_1,由于状态 Fan 与子状态 Fan.F1 已 激活,Fan.F1 到 Fan.F2 的迁移有效,Fan.F2 被激活。图 3.5.6 send 函数直接事件广播 用事件名直接事件广播 将图 3.5.6 稍作修改,即可用事件名直接事件广播,如图 3.5.8 所示。 ① 除事件 event_1,另行定义 Fan 状态的本地事件 event_1。 点击模型工具栏图标 ,在左侧 model hierarchy 区域中选择状态 Fan,并点击add→Event 按钮,为 Fan 状态添加本地事件,如图 3.5.7 所示。同样的方法可以定义 状态的本地数据。图 3.5.7 定义本地事件 ②将条件动作{send(event_1,Fan)}替换为迁移动作/Fan.event_1。 本例与用 send 函数直接事件广播的区别在于: ① event_1 属于状态 Fan 的本地事件,作用范围限制在该状态内部,对 Fan 状态可见,对 Led 为不可见。 ② 迁移动作 Fan.event_1 替换了{send(event_1,Fan)}。图 3.5.8 事件名直接事件广播 3.5.6 隐含事件和条件隐含事件是一种内置事件,它不是由用户显式的定义或触发,而是当状态图执 行时就会自动发生。例如状态图被唤醒、进入一个状态、退出一个状态或向内部数 据对象赋值。隐含事件是它们发生时所在的状态的子对象,并且只对其父状态可见。 使用隐含事件和条件有助于简化并行状态之间的依赖关系,也可以减少数据字 典中定义的事件数量,降低状态图的复杂程度。 表 3.5.1 列出了隐含事件/条件的表达式和对应的含义。 表 3.5.1 各隐含事件/条件的含义 隐含事件/条件 change(data_name) or chg(data_name) enter (state_name) or en(state_name) exit (state_name) or ex(state_name) tick wakeup [in(state_name)] 含义 对指定变量(data_name)写入数据时,隐含的产生一个本地信 号。该变量不能为 machine 的子数据,此隐含事件只对 Chart 或更低的层次有效。对于 machine 的子数据,用变化监测运算 符决定其数据是否改变 进入指定状态(state_name)时,隐含的产生一个本地信号 退出指定状态(state_name)时,隐含的产生一个本地信号 评估动作所在的状态图被唤醒时,隐含的产生一个本地事件 与 tick 相同 当指定状态(state_name)处于激活状态,条件为真如图 3.5.9 所示, Led 和 Fan 是两个并行状态, PowerOn 激活时, 当 状态 Led.Off 和 Fan.Off 被激活。当隐含事件 tick 事件广播 6 次后,状态 Led.Off 向状态 Led.On 迁移,状态 Led.Off 退出,广播隐含事件 exit(Led.Off),于是状态 Fan.Off 向状态 Fan.On 迁移。 图 3.5.9 隐含事件的使用3.6Stateflow 其他对象 3.6.1 真值表(Truth table)熟悉数字电路的用户,一定了解表 3.6.1 所列的异或门真值表。 表 3.6.1 异或门真值表 输入 A H H L L B H L H L 输出 Y L H H L由于在 Stateflow 中,真值表的表达形式为条件,决策和动作,为了后面使用方 便,可将异或门的真值表改写为如表 3.6.2 的形式: 表 3.6.2 条件 A==0&&B==0 A==0&&B==1 A==1&&B==0 A==1&&B==1 动作 决策 1 T y=0 决策 2 T y=1 决策 3 T y=1 T y=0 决策 4 决策 5(默 认决策) y=-1条件栏输入的每一个条件需判断真假,判断完结果为 T(逻辑真),F(逻辑假) 或-(逻辑真或逻辑假)。当所列的条件满足某一决策时,执行该决策所对应的动作, 而动作的具体内容则另外在动作表中定义。默认决策定义了除决策 1~4 之外的所有 情况。 将表 3.6.2 中的内容填写到 Stateflow 真值表中。需要注意的是动作的具体内容 在 Action Table 中定义,并给每个动作赋予一个标号,在 Condition Table 的动作栏 引用动作的标号即可,如图 3.6.1 所示。 图 3.6.1 建立真值表 在每一个仿真步长内,系统首先逐一判断各个条件的输出结果,将输出结果组 合起来,再与各个决策逐一比较,当结果完全满足某一决策时,即执行对应的动作, 同时不再判断后续的决策,如图 3.6.2,3.6.3 所示。图 3.6.2 Stateflow 流程图图 3.6.3 Simulink 模型 3.6.2 图形函数(Graphical function)图形函数是用包含 Stateflow 动作的流程图定义的函数,是流程图的延伸,使用 图形方式定义算法,并在仿真过程中跟踪它的运行。 图形函数与 MATLAB 函数、C 函数有一定的相似之处,例如:图形函数同样需 要接收参数并返回结果;用户可以在状态/迁移动作中调用图形函数。不同之处在于 图形函数是 Stateflow 自身的图形对象, 因此可以直接通过 Stateflow 编辑器创建并调 用,不必像文本函数一样需要用外部工具创建,在外部定义。 下面将通过图形函数完成异或的功能,使读者了解图形函数的用法。 ① 先创建一个包含 Stateflow 图表的 Simulink 模型,然后单击图表编辑器中图 形工具栏的图形函数按钮 3.6.4 所示。 ,即可在编辑器空白位置添加图形函数,如图图 3.6.4 添加图形函数 ② 单击“?”处进入编辑状态,用户可以在此定义所需要的函数。函数名的 语法规则为:[n1,n2,n3…]=函数名(a1,a2,a3…),其中 n1,n2,n3 为返回值, a1,a2,a3 为参数值,如图 3.6.5 所示。图 3.6.5 定义函数 ③ 用户可以在图形函数内部用图形对象完成所需的函数逻辑。在本例中,我 们使用 Stateflow 提供的“if-elseif-else…”模板完成函数,使问题更加简单。 右键单击图形函数,选择 Pattern→add design→if-elseif-else…如图 3.6.6 所 示。 图 3.6.6 选择逻辑图样模板 ④ 根据 3.6.1 节的内容不难得出异或函数的实现逻辑。在 Stateflow Pattern: IF-ELSEIF-ELSE 对话框中完成异或逻辑,如图 3.6.7 所示。图 3.6.7 流程图对话框 ⑤ 确认后,自动生成实现该函数的图形函数,如图 3.6.8 所示。 图 3.6.8 流程图 由于该图形函数较复杂,可以用先将图形完全包含在函数框中,如图 3.6.9 所 示,然后用右键菜单中的 Make Contents→subcharted 功能简化图形函数,如图 3.6.10 所示。图 3.6.9 简化图形函数 图 3.6.10 简化后的图形函数 ⑥ 图表添加相应的数据、事件后,就可以通过状态动作或迁移动作实现图形 函数的调用了,如图 3.6.11 所示。图 3.6.11 调用 Stateflow 图形函数3.6.3Embedded MATLABEmbedded MATLAB 函数可以为 Stetaflow 添加 MATLAB 函数。在描述代码算 法方面,文本形式的 MATLAB 语言比图形化的 Stateflow 动作语言更加优越,因此, 选择 Embedded MATLAB 函数较为有效。 Embedded MATLAB 函数通过调用 MATLAB 语言中的一个子集 Embedded MATLAB 实现其功能。Embedded MATLAB 子集能够有效优化了生成代码,提高代 码效率,为编译目标生成产品级 C 代码。 Embedded MATLAB 函数可以调用子函数、 Embedded MATLAB 运行时库函数、 Stateflow 函数以及部分 MATLAB 函数和定点工 具箱运行时库函数。 ① 创建一个包含 Stateflow 图表的 Simulink 模型,然后单击图表编辑器中图形 工具栏的 Embedded MATLAB 函数按钮 ,即可在编辑器空白位置添加Embedded MATLAB 函数,如图 3.6.12 所示。 图 3.6.12 添加 Embedded MATLAB 函数 ② 单击“?”处可以编辑 Embedded MATLAB 函数名称,命名规则与图形函 数类似,此处命名为[len,area]=rectangle(length,width),如图 3.6.13 所示。图 3.6.13 Embedded MATLAB 函数命名 ③ 在 Stateflow 中定义 len,area,length,width 四个数据对象作为函数的输 出,图 3.6.14 所示。图 3.6.14 定义数据对象 ④双击 Embedded MATLAB 函数对象,打开 Embedded MATLAB 函数编辑器, 此时函数定义行已定义,只需添加算法代码即可。function [len,area]=rectangle(length,width) %#eml len=2*(length+width); //计算矩形周长 area=length* end //计算矩形面积关于 Embedded MATLAB 的编写与调试在第一章有详细介绍,这里不再赘述。 ⑤在图表中添加默认迁移和终止节点,通过迁移动作调用 Embedded MATLAB 函数,如图 3.6.15 所示。图 3.6.15 调用 Embedded MATLAB 函数 3.6.4 图形盒(Box)图形盒时 Stateflow 的一种图形对象,可以用来组织图表中的图形对象。添加图 形盒后,图形盒中图形对象的可视性以及并行状态的激活顺序都会有所变化。 图形盒中图形对象的可视性。引入图形盒可以为图表新增一个层次,因此,对 于图形盒外部的对象来说,图形盒内部对象的可见性发生了变化。用户若需要在图 形盒外部引用位于图形盒内部的函数或状态,则应该在引用路径中添加图形盒的名 称。 引入图形盒会改变并行状态的激活顺序。图形盒内部并行状态激活顺序为从上 到下,从左到右;若图形盒外部也存在并行状态,则图形盒内部的状态优先于外部 状态激活。 图形盒的使用有如下规则: ? 若在图形盒外部引用图形盒内部的函数或状态,必须在路径上加入图形盒的名 称; ? 在图形盒内部可以添加图形对象,如函数、状态; ? 内部包含若干对象的状态可以转换为图形盒; ? 为图形盒添加数据对象可以使其内部所有对象共享该数据; ? 图形盒及其内部对象可以打包称为 1 个图形对象; ? 图形盒可通过“subchart”功能简化其内部元素; ? 图形盒无法定义状态动作,如 entry, during, 和 exit 动作; ? 无法定义始于或终于图形盒的迁移。 在 Stateflow 编辑窗口中点击图形盒按钮,再点击编辑窗口中的空白处即可添加 图形盒。单击“?”处编辑图形盒名称,如图 3.6.16 所示。图 3.6.16 添加图形盒 如图 3.6.17 所示,图形盒命名为 status,其中有两个 Embedded MATLAB 函数, 若要调用 msgCold, 其语法为 Status.msgCold(), 若要调用 msgWarm, 其语法为 Status. msgWarm()。图 3.6.17 调用图形盒中的对象3.6.5 Simulink 函数调用Simulink 函数是 Stateflow 图表中的一种图形对象,用户可以在该对象中添加 Simulink 模块来实现预期的功能,并在状态/迁移动作中调用,从而实现了 Simulink 与 Stateflow 间的无缝连接。Simulink 函数通过减少图形和非图形对象的方式,使模 型设计更加高效,更具可读性。 Simulink 函数一般应用于: ①需要用到 lookup tables 等 Simulink 模块的函数; ②多控制器的调度执行。 Simulink 函数的调用与 Simulink 模型中的函数调用子系统模块类似,但是有表 3.6.3 所列出的区别。 表 3.6.3 两种函数调用的差别 行为 执行中是否需要函数调用输出事件 是否需要信号线 是否支持基于帧的输出信号 函数调用子系统 是 是 是 Simulink 函数 否 否 否Simulink 函数的定义位置则决定了其影响范围,如表 3.6.4 所列。 表 3.6.4 Simulink 函数作用范围 Simulink 函数定义于 调用 Simulink 函数的范围 状态 图表该状态本身及其子状态 该图表内皆可调用。以下说明 Simulink 函数的用法。 ① 创建一个包含 Stateflow 图表的 Simulink 模型, 然后单击图表编辑器中图形 工具栏的 Simulink 函数按钮 数,如图 3.6.18 所示。 , 即可在编辑器空白位置添加 Simulink 函图 3.6.18 添加 Simulink 函数 ② 单击“?”处进入编辑状态,用户可以在此定义所需要的函数。函数命名 形式与图形函数相同。此处将 Simulink 函数命名为 x=sim_fun(a,b),如图 3.6.19 所示。图 3.6.19 定义函数 ③ 双击 Simulink 函数对象,定义 Simulink 函数的子系统元素。在子系统中有 与命名的函数对应的输入输出端口和一个函数调用触发端口,如图 3.6.20 所示。 图 3.6.20 打开 Simulink 函数 向模型中添加模块,完成如图 3.6.21 所示的子系统模型。注意应保留模型中的 触发端口。图 3.6.21 添加模块 ④ 定义两个“input from Simulink”属性的数据对象作为函数的输入;定义 一个“output to Simulink”属性的数据对象作为函数的输出, 如图 3.6.22 所示。图 3.6.22 定义数据对象 ⑤ 向图表中添加状态,并定义其 entry 动作为 sim_fun(m,n) ,则当该状态被 激活时,即调用 Simulink 函数 sim_fun(),如图 3.6.23 所示。 图 3.6.23 调用 Simulink 函数3.6.6 目标目标是一个用来执行 Stateflow 图表或包含 Stateflow 状态机的 Simulink 模型的 程序。 若用户并不想为应用建立快速原型或产品,而是要生成其独立代码,则可以使 用代码生成软件 Stateflow Coder 建立用户目标, 但该软件生成的代码并未经过 RTW 的优化。 ① Stateflow 编辑窗口点击 add→targets 会弹出用户目标对话框如图 3.6.24 所 示:图 3.6.24 用户目标对话框 在 Name 区域内输入目标名称并设置完毕后,点击 OK 即完成用户目标的添加。 ②若用户需要进一步修改对目标的配置,可以单击 按钮,在模型浏览器中进行操作。 在模型浏览器的 Model Hierarchy 面板内选择含有用户目标的主模型,然后在 Contents 面板中选择目标,则右侧的动态面板即出现用户目标的配置对话框,如图 3.6.25 所示。图 3.6.25 用户目标的配置对话框? ? ? ? ? ?③用户目标配置对话框的 General 面板内可做如下设置: User Comments in generated code:在生成代码中包含用户自定义的注释。 Auto-generated Comments in generated code:在生成代码中包含自动生成的注释。 State/Transition Descriptions in generated code:在生成代码中包含状态和迁移的 描述。 Use bitsets for storing state configuration:减少存储变量的内存用量。但是当目标 处理器不包含操作 bitsets 的说明时,能够增加存储目标代码的内存用量。 Use bitsets for storing boolean data:减少存储布尔型变量的内存用量。 但是当目标 处理器不包含操作 bitsets 的说明时,能够增加存储目标代码的内存用量。 Compact nested if-else using logical AND/OR operators:通过使用逻辑运算符压缩 多层嵌套的 if-else 结构来提高代码的可读性。 例如,生成代码: if(c1) { if(c1) { a1(); } } 被表示为: if(c1 && c2) { a1(); } Recognize if-elseif-else in nested if-else statements:通过使用 if-elseif-else 结构提高? ??多层次嵌套的 if-else 代码的可读性。 例如,生成代码: if(c1) { a1(); }else{ if(c2) { a2(); }else{ if(c3) { a3(); } } } 被表示为: if(c1) { a1(); }else if(c2) { a2(); }else if(c3) { a3(); } Replace constant expressions by a single constant:通过对常量表达式估值,用单个 常量代替常量表达式来提高代码可读性。此优化功能还能消除无效代码。 例如,生成代码: if(2+3&2) { a1(); }else { a2(4+5); } 被表示为: if(0) { a1(); }else { a2(9); } Minimize array reads using temporary variables:在条件允许时, 通过暂时变量最小 化矩阵的读操作。 例如,生成代码: a[i] = foo(); if(a[i]&10 && a[i]&1) { y = a[i]+5; }else{ z = a[i]; } 被表示为: a[i] = foo(); temp = a[i]; if(temp&10 && temp&1) { y = temp+5; }else{ z = } ? Use chart names with no mangling:保留图表 entry 函数名, 以便用户可以在手写 C 代码中调用。选中该复选框时,生成代码并不通过 mangle 图表的名称来使其唯 一化。由于该复选框不检测生成代码中的名称冲突性,因此只有当模型中图表 名称唯一时可用。 I/O data format: ? Use global input/output data :生成图表的输入输出数据并作为全局变量。 ? Pack input/output data into structures:为图表输入输出数据生成结构。 Generate chart initializer function:生成数据初始化函数。 Multi-instance capable code:生成多实例图形对象代替静态定义。 Build Options: ? Generate Code Only (non-incremental) :为模型中的所用图表生成代码。 ? Rebuild All (including libraries) :重建目标。 若用户建立目标后更换了编译器 或更新了目标文件,可选择该选项。 ? Make without generating code:调用创建程序,但并不生成代码。?? ? ?3.7 综合应用 3.7.1 计时器1. Stateflow 状态图 在图 3.3.2 的基础上,添加默认迁移的事件与条件动作,每当事件 TIC 发生, 执行{percent = percent +1 },之后再判断是否进行分秒进位,此即可作为一个计时 流程。事件 TIC 可由脉冲模块模拟,触发条件为上升沿,如图 3.7.1 所示。 图 3.7.1 时钟流程图 为了实现以圈计时的功能,将图 3.7.1 的默认迁移起点,移到父状态 Run,这 表示只要 Run 处于激活状态,就不断执行计时流程,不受 LAP 状态的影响,如图 3.7.2 所示。图 3.7.2 计时器状态图 2. Simulink 模型 以脉冲模块模拟输入时钟信号, 两个开关分别模拟 Start 与 LAP 按钮, 按图 3.7.8 建立 Simulink 模型。由于每个 Stateflow 模块只能有一个事件输入口,有多个外部 输入事件时,必须使用 Mux 模块将它们组合成向量。水平放置的 Mux 模块,其输 入端口号从左往右对应事件端口号,而垂直放置的 Mux 模块,其对应关系则是从上 到下。 在 Simulink 模块库中找到如图 3.7.3-3.7.7 所列模块,并按图 3.7.8 连接。 图 3.7.3 脉冲发生器模块图 3.7.4 常数模块图 3.7.5 合路器模块图 3.7.6 手动开关模块图 3.7.7 数字 LED 模块 图 3.7.8 功能验证模型 双击 Start 开关,系统开始计时,如图 3.7.9 所示:图 3.7.9 开始计时 双击 Lap 开关,系统记录当前计时值,并继续计时,如图 3.7.10 所示。 图 3.7.10 以圈计时 再次双击 Start 开关,系统停止计时,显示最后计时值,图 3.7.11 所示:图 3.7.11 最后计时值 3. 创建 GUI 界面 利用 Simulink 模块库提供的开关模块,已能实现本例的功能,但若模型需要大 量的开关,必然导致常数模块或连线间的交叉点增多,人为使得模型变得复杂。为 此使用 GUI 用户图形界面,简化模型,同时提高仿真的舒适度。 MATLAB 的 GUI 界面与 VC,VB 等软件的类似,因此本文仅叙述创建过程, 不做功能介绍。 ① 删除图 3.7.8 模型的开关以及常数模块,另外新增常数 Start 与 Lap,按图 3.7.12 调整。图 3.7.12 调整功能验证模型 ② 选择 MATLAB 界面的菜单项 File→New→GUI, 在打开的对话框中选择 GUI 模板为 Blank GUI,勾选下方的 Save new figure as…,指定 GUI 文件名, 并确保文件路径与 Simulink 模型的一致,如图 3.7.13 所示。图 3.7.13 新建 GUI 界面选项 ③ 确定后,系统打开 GUI 编辑窗口,如图 3.7.14 所示与回调函数编辑窗口, 如图 3.7.15 所示。图 3.7.14GUI 编辑窗口图 3.7.15 回调函数编辑窗口④ GUI 编辑窗口里加入两个按钮,图 3.7.16 所示:图 3.7.16 添加按钮 ⑤双击按钮, 修改属性对话框 String 栏目的内容, 将显示文字修改为 Start/Reset 与 LAP,如图 3.7.17 所示。 图 3.7.17 修改 String 栏目显示文字内容 ⑤ 选择 Start/Reset 按钮的右键菜单项 View Callbacks→Callback,系统自动 定位到回调函数编辑窗口的对应位置,并高亮显示,如图 3.7.18 所示。图 3.7.18 编辑回调函数 ⑦添加 Start/Reset 按钮的回调方法代码如下,其中 stopwatch_state 表示模型 名称,用户应按实际调整。function pushbutton1_Callback(hObject, eventdata, handles)??start = str2num(get_param('stopwatch_state/Start', 'Value')); if start==0 start=1; else start=0; end set_param('stopwatch_state/Start', 'Value', num2str(start));同样的方法,添加 LAP 按钮的回调方法代码如下: function pushbutton2_Callback(hObject, eventdata, handles) ?? Lap = str2num(get_param('stopwatch_state/Lap', 'Value')); if Lap==0 Lap=1; else Lap=0; end set_param('stopwatch_state/Lap', 'Value', num2str(Lap));⑦ 按下 GUI 界面编辑器的工具栏按钮,执行该 GUI,如图 3.7.19 所示:图 3.7.19 执行 GUI 这时 Start/Reset 与 LAP 按钮即可实现原先的开关功能,即使不运行模型,按 下这两个按钮,模型窗口的 Start 与 Lap 常数模块的数值已能够实时变化。 ⑨选择 Simulink 模型窗口的菜单项 File→Model Properties, Callbacks 页的 在 PostLoadFcn 条目,添加文字 stopwatch,如图 3.7.20 所示。这样重新打开模型窗 口时,GUI 界面即可自动打开。图 3.7.20 Callbacks 页 3.7.2 交通灯1. Stateflow 状态图 一个小型路口的交通灯亮灭过程可以用以下文字简单表示:南北向禁行时红灯 亮起并保持 50 秒,同时东西向通行,绿灯亮起,但只保持 45 秒,45 秒时东西向缓 行,黄灯亮起,保持 5 秒;之后东西向禁行,红灯亮起并保持 50 秒,同时南北向通 行,绿灯亮起,同样只保持 45 秒,45 秒时南北向缓行,黄灯亮起,保持 5 秒,如 此循环反复。 用户根据上述各节的介绍, 应能快速地建立图 3.7.21 所示的简单交通灯状态图。图 3.7.21 简单交通灯状态图 图 中 4 个 状 态 RedNorthSouth 、 YellowEastWest 、 RedEastWest 、 YellowNorthSouth 分别代表南北向禁行、东西向缓行、东西向禁行、南北向缓行。 变量 nsred、nsyell、nsgreen、ewred、ewyell、ewgreen 分别代表南北向与东西向 的红灯、黄灯、绿灯,在不同的状态中,它们的亮灭以 1 或 0 表示。 简便起见,可以设置任意一个状态作为默认迁移状态,进入该状态时,便开始 倒数计时,显然处于不同的状态,每个方向的倒数计时起始值是不一样的:例如红 灯 50 秒、 黄灯 5 秒、 绿灯 45 秒。 Stateflow 状态图中, 在 添加一个 Embedded MATLAB 函数 time(flag)实现该功能,如图 3.7.22 所示,代码如下。 图 3.7.22 Embedded MATLAB 函数 time(flag) function time(flag) timeout=0; % 计时终了标志清零 switch flag % 判断当前所处的通行状态 case 1 % 南北向禁行时 nssec= % 取变量red作为南北向计时起始值 ewsec= % 取变量green作为东西向计时起始值 sec=green*10; % 提高计时精度,放大倒数计时变量 case 2 % 东西向缓行时 ewsec=red- % 取变量red-green作为东西向计时起始值 sec=(red-green)*10; case 3 ewsec= nssec= sec=green*10; % 东西向禁行时 % 取变量red作为东西向计时起始值 % 取变量green作为南北向计时起始值case 4 % 南北向缓行时 nssec=red- % 取变量red-green作为南北向计时起始值 sec=(red-green)*10; end 读取了计时起始值,即开始倒数计时,这里沿用 3.7.1 节的计时流程图,稍作 改造并封装为图形函数 count(),供各状态调用,如图 3.7.23 所示。每当事件 TIC 发生,倒数计时变量 sec 减 1,当 sec=0 时,计时终了标志置 1,状态应发生迁移。图 3.7.23 图形函数 count() 为了提到计时精度,函数 time(flag)曾将计时变量 sec 放大了 10 倍,只有当计 时变量的个位为 0 时,才表示计得 1 秒,南北向、东西向的计时值才可以减 1,因 此需要用到取余函数 rem()。 不过在流程图的迁移条件里不能直接使用该函数, 为此 将其封装成 Embedded MATLAB 函数 remain(x),如图 3.7.24 所示,代码如下。图 3.7.24 Embedded MATLAB 函数 remain(x)function y=remain(x) y = rem(x,10);状态迁移过程如图 3.7.25 所示:图 3.7.25 状态迁移过程 完整的状态图如图 3.7.26 所示: 图 3.7.26 完整的状态图 图 3.7.27 列出了整个 Stateflow 状态图的所有变量与事件,南北向、东西向的 三盏指示灯以及计时值 nssec、ewsec 均设置为输出变量,而状态标志 flag、计时 变量 sec、计时终了标志 timeout 只需作为内部变量,TIC 作为时钟信号触发类型选 为上升沿。图 3.7.27 变量与事件列表 2. Simulink 建模 完成 Stateflow 状态图之后,在 Simulink 模块库中找到图 3.7.28-3.7.31 所示的 模块,添加到模型。 图 3.7.28 脉冲发生器模块图 3.7.29 常数模块图 3.7.30 合路器模块图 3.7.31 Goto 模块 按图 3.7.32 连接,任意设置常数 red 与 green 的值,例如 10、7,这代表红灯 与绿灯的点亮时长。 图 3.7.32 Stateflow 部分模块连接 继续在模型中添加以下图 3.7.33-3.7.36 所示模块。图 3.7.33 From 模块图 3.7.34 分路器模块 图 3.7.35 红色方块模块图 3.7.36 数字 LED 模块 该状态图的连线过多,如果仍使用连线直接相连,必导致图形杂乱无章,信号 流向难以分辨。 使用 From、 Goto、 Demux 模块, 可以大大地简化图形, 如图 3.7.37 所示。 图 3.7.37 显示部分模块连接 Red Rect 模块若不做任何修改,它只能显示红色,用户可以根据需要设置模块 的背景色、外框、亮灯颜色、灭灯颜色等,如图 3.7.38、图 3.7.39 所示。图 3.7.38 修改红色方块模块的背景色图 3.7.39 修改红色方块模块的亮灭色 南北、东西两向的倒数计时最多为两位十进制数,因此设置数码管其显示位数 为 2 位整数、0 位小数,如图 3.7.40 所示。图 3.7.40 修改数字 LED 模块的显示位数 3. 模型设置及仿真 选择模型主窗口的菜单项 Simulation→Configuration Parameters…,如图 3.7.41 所示,打开模型参数对话框,如图 3.7.42 所示。图 3.7.41 模型参数设置菜单图 3.7.42 参数设置对话框 在 Solver 面板,设置求解器为定步长离散求解器,步长为 0.01,如图 3.7.43 所示。图 3.7.43 求解器设置 双击脉冲发生器模块,根据实际需要设置脉冲周期与脉冲宽度,如图 3.7.44 所 示。 图 3.7.44 脉冲发生器参数 完成以上设置后执行仿真,模型即按设计开始运行,如图 3.7.45-3.7.48 所示:图 3.7.45 南北向禁行 图 3.7.46 东西向缓行图 3.7.47 东西向禁行 图 3.7.48 南北向缓行
8 基于ARM的快速代码生成1021final_计算机软件及应用_IT/计算机_专业资料。基于...3 Stateflow建模与应用1... 4 设备驱动模块的编写10... 5 基于单片机的快速...
All rights reserved Powered by
copyright &copyright 。文档资料库内容来自网络,如有侵犯请联系客服。

我要回帖

更多关于 c 让主线程执行函数 的文章

 

随机推荐