我是靠谱客的博主 狂野香烟,这篇文章主要介绍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表示没有事件发生。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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开始。

复制代码
1
2
3
4
5
#define untitled_IN_Off ((uint8_T)1U) #define untitled_IN_On ((uint8_T)2U)

3.2 嵌套子状态

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

复制代码
1
2
3
4
5
6
7
8
9
#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状态的子状态:

复制代码
1
2
3
4
5
6
7
8
9
#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 状态结构体

状态结构体:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;

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

复制代码
1
2
3
4
real_T data; /* '<Root>/Chart' */

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

复制代码
1
2
3
int32_T sfEvent; /* '<Root>/Chart' */

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

复制代码
1
2
3
4
5
6
uint8_T is_active_c3_untitled; /* '<Root>/Chart' */ uint8_T is_c3_untitled; /* '<Root>/Chart' */

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

复制代码
1
2
3
4
5
6
7
8
uint8_T is_COLOR; /* '<Root>/Chart' */ uint8_T was_COLOR; /* '<Root>/Chart' */ uint8_T is_active_COLOR; /* '<Root>/Chart' */

4. 流程

以下代码均为伪代码。

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
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()

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

复制代码
1
2
CurEvent = untitled_CALL_EVENT;

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

复制代码
1
2
3
4
5
6
7
8
9
if (is_active_c3 == 0U) { is_active_c3 = 1U; is_c3 = InitState; InitState_Entry(); } else { StateMachine_Select(); }

4.2 StateMachine_Select()

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

复制代码
1
2
3
4
5
6
7
8
9
10
switch (is_c3) { case State1: State1_Proc(); break; case State2: State2_Proc(); break; ... }

4.3 State_Proc()

格式为:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//当前事件为转移事件,且满足守卫条件 if ((CurEvent == TranEvent) && Guard()) { //转移action Tran_Action(); //上一个状态子状态Exit LastSubState_Exit(); //上一个状态Exit LastState_Exit(); //状态变为下一个状态 CurState = NextState; NextState_Entry(); //下一个状态子状态Entry NextSubState_Entry(); }

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
else if((CurEvent == TranEvent2)) { //有条件伪状态 if(Guard2()) { ... } else if(Guard3()) { ... } else { ... } }

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

复制代码
1
2
3
4
5
6
7
8
9
else { LastState_During(); if (is_active_lastsubstate != 0U) { LastSubState_Select(); } }

4.4 LastSubState_Exit()

复制代码
1
2
3
4
5
6
7
8
9
10
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_中。

复制代码
1
2
3
4
5
6
7
8
9
10
11
is_active_NextSubState = 1U; switch (was_NextSubState) { case NextSubState_SubState1: is_NextSubState = NextSubState_SubState1; was_NextSubState = NextSubState_SubState1; SubState1_entry(); break; case NextSubState_SubState2: ... }

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

复制代码
1
2
3
4
is_active_NextSubState = 1U; is_NextSubState = NextSubState_SubState1st; SubState1_entry();

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

复制代码
1
2
3
4
is_active_NextSubState = 1U; is_NextSubState = NextSubState_SubStateInd; SubState1_entry();

4.6 LastSubState_Select()

复制代码
1
2
3
4
5
6
7
8
9
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.内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部