我是靠谱客的博主 狂野香烟,最近开发中收集的这篇文章主要介绍matlab状态机stateflow生成C语言代码解析1. 简介2. 事件3. 状态4. 流程5. 总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1. 简介

simulink的stateflow采用的是单事件触发的同步状态机模式。本文介绍了一种可行的状态机的实现方法,可根据stateflow由C code generator直接生成。

1.1 状态

状态(State)拥有Entry,During,Exit三个方法,分别在进入循环退出状态时发生。

1.2 转移

转移(Transition)的形式为:

event[guard]{action}

事件(event)触发状态转移。
守卫条件(guard condition)一般是一个返回bool类型的函数,如果不满足条件,事件会被“安静地丢弃”(discard silently)。
转移动作(action)是在转移过程中执行的函数。

1.3 伪状态

节点伪状态(Junction PseudoState)因为可以用相同方式处理,因此将条件、合并、分支伪状态统称。
历史伪状态 (History PseudoState)再一次进入子状态时,将上一次退出时的状态作为默认状态。
初始伪状态 顾名思义,状态机起点。

2. 事件

用宏定义的方式定义事件。-1表示没有事件发生。

#define untitled_CALL_EVENT
(-1)
#define untitled_event_goGreen
(0)
#define untitled_event_goOff
(1)
#define untitled_event_goOn
(2)
#define untitled_event_goQuickly
(3)
#define untitled_event_goRed
(4)
#define untitled_event_goSlowly
(5)
#define untitled_event_goSteady
(6)
#define untitled_event_goYellow
(7)

3. 状态

3.1 一级状态

一级状态也使用用宏定义,从1开始。

#define untitled_IN_Off
((uint8_T)1U)
#define untitled_IN_On
((uint8_T)2U)

3.2 嵌套子状态

嵌套子状态多一个无激活的0状态。
Color状态的子状态:

#define untitled_IN_NO_ACTIVE_CHILD
((uint8_T)0U)
#define untitled_IN_Green
((uint8_T)1U)
#define untitled_IN_Red
((uint8_T)2U)
#define untitled_IN_Yellow
((uint8_T)3U)

Rate状态的子状态:

#define untitled_IN_NO_ACTIVE_CHILD
((uint8_T)0U)
#define untitled_IN_Flashing_Quickly
((uint8_T)1U)
#define untitled_IN_Flashing_Slowly
((uint8_T)2U)
#define untitled_IN_Steady
((uint8_T)3U)

3.3 状态结构体

状态结构体:

typedef struct {
real_T data;
/* '<Root>/Chart' */
int32_T sfEvent;
/* '<Root>/Chart' */
uint8_T is_active_c3_untitled;
/* '<Root>/Chart' */
uint8_T is_c3_untitled;
/* '<Root>/Chart' */
uint8_T is_COLOR;
/* '<Root>/Chart' */
uint8_T was_COLOR;
/* '<Root>/Chart' */
uint8_T is_active_COLOR;
/* '<Root>/Chart' */
uint8_T is_RATE;
/* '<Root>/Chart' */
uint8_T was_RATE;
/* '<Root>/Chart' */
uint8_T is_active_RATE;
/* '<Root>/Chart' */
} DW_untitled_T;

结构体包括状态机中的使用的变量:


real_T data;
/* '<Root>/Chart' */

事件变量。由于是单事件同步模式,所以只需要一个事件。

int32_T sfEvent;
/* '<Root>/Chart' */

一级状态。is_c3储存当前状态,is_active_c3储存当前是否激活(为了entry事件)


uint8_T is_active_c3_untitled;
/* '<Root>/Chart' */
uint8_T is_c3_untitled;
/* '<Root>/Chart' */

嵌套事件。is储存当前状态,is_active储存当前是否激活,was储存上一次退出时的状态,如果没有历史伪状态则不需要。


uint8_T is_COLOR;
/* '<Root>/Chart' */
uint8_T was_COLOR;
/* '<Root>/Chart' */
uint8_T is_active_COLOR;
/* '<Root>/Chart' */

4. 流程

以下代码均为伪代码。

main函数调用如下。OverrunFlag标志进入临界区,保证线程安全。StateMachine_Step()为状态机更新调用函数。


OverrunFlag = true;
/* Save FPU context here (if necessary) */
/* Re-enable timer or interrupt here */
/* Set model inputs here */
/* Step the model */
StateMachine_Step();
/* Get model outputs here */
/* Indicate task complete */
OverrunFlag = false;

4.1 StateMachine_Step()

设置当前事件为无事件。事件可以由外界更改,也可由内部更改。

CurEvent = untitled_CALL_EVENT;

通过is_active判断是否执行entry任务。状态由初始伪状态变为第一个状态,同时初始化输出值。一级状态不可以有历史伪状态。

if (is_active_c3 == 0U) {
is_active_c3 = 1U;
is_c3 = InitState;
InitState_Entry();
}
else {
StateMachine_Select();
}

4.2 StateMachine_Select()

如果已经激活一级状态机。那么根据is_c3判断当前状态。每个状态都有一个处理函数。

switch (is_c3) {
case State1:
State1_Proc();
break;
case State2:
State2_Proc();
break;
...
}

4.3 State_Proc()

格式为:

//当前事件为转移事件,且满足守卫条件
if ((CurEvent == TranEvent) && Guard())
{
//转移action
Tran_Action();
//上一个状态子状态Exit
LastSubState_Exit();
//上一个状态Exit
LastState_Exit();
//状态变为下一个状态
CurState = NextState;
NextState_Entry();
//下一个状态子状态Entry
NextSubState_Entry();
}

如果存在条件伪状态(一般情况条件伪状态前是事件,后面是守卫条件):

else if((CurEvent == TranEvent2))
{
//有条件伪状态
if(Guard2())
{
...
}
else if(Guard3())
{
...
}
else
{
...
}
}

如果没有转移,那么就执行during。

 else
{
LastState_During();
if (is_active_lastsubstate != 0U)
{
LastSubState_Select();
}
}

4.4 LastSubState_Exit()

switch (is_LastSubState) {
case LastSubState_Substate1:
Substate1_exit();
is_LastSubState = NO_ACTIVE_CHILD;
break;
case LastSubState_Substate2:
...
}
is_active_LastSubState = 0U;

4.5 NextSubState_Entry()

有历史伪状态,上一次退出状态保存在was_中。

is_active_NextSubState = 1U;
switch (was_NextSubState) {
case NextSubState_SubState1:
is_NextSubState = NextSubState_SubState1;
was_NextSubState = NextSubState_SubState1;
SubState1_entry();
break;
case NextSubState_SubState2:
...
}

无历史伪状态,进入默认初始状态。

is_active_NextSubState = 1U;
is_NextSubState = NextSubState_SubState1st;
SubState1_entry();

直接转移到子状态中某一状态的,要先处理父状态,然后处理子状态。

is_active_NextSubState = 1U;
is_NextSubState = NextSubState_SubStateInd;
SubState1_entry();

4.6 LastSubState_Select()

switch (is_LastSubState) {
case LastSubState_Substate1:
//与State_Proc()类似,判断转移
SubState1_Proc();
break;
case LastSubState_Substate2:
...
}

按照以上递推直到没有子状态,然后循环执行。

5. 总结

本状态的exit与下一个状态的entry都是在转移的过程中完成的,执行顺序为action->exit->entry。不发生状态转移才会执行本状态的during。
另外,stateflow中的OR状态有严格的先后执行顺序。

最后

以上就是狂野香烟为你收集整理的matlab状态机stateflow生成C语言代码解析1. 简介2. 事件3. 状态4. 流程5. 总结的全部内容,希望文章能够帮你解决matlab状态机stateflow生成C语言代码解析1. 简介2. 事件3. 状态4. 流程5. 总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部