Stateflow是MATLAB工具箱中的一个重要组件,主要用于事件驱动系统的建模、仿真、验证和代码自动生成。Stateflow可以快速地建立可视化的状态图,用于描述离散状态和连续状态的动态行为。本文将从多个方面对Stateflow基本语法进行详细阐述,并给出相应的代码示例。
一、状态和事件
在Stateflow中,状态可以理解为系统的一个特定的状态,例如:假设我们建立了一个售货机的状态图,而状态可以是“等待投币”、“选择商品”、“支付”、“出货”等状态。用Stateflow图描述状态之间的转移,以及状态与事件之间的关系,其中事件是使系统从当前状态转移到下一个状态的触发源。 一个Stateflow图通常包含一个或多个state,以及它们之间的transition。一个state有如下的特征:
- 拥有一个名字,表示当前状态。
- 可以有一个或多个入口,表示进入当前状态的条件。
- 可以有一个或多个出口,表示状态转移后的下一个状态。
- 可以有一个或多个事件,表示触发状态转移的事件。
- 可以有一个可选择的default transition,表示当没有任何条件满足时,状态转移到的下一个状态。 下面给出一个简单的状态机的示例,实现了一个红绿灯的控制,以及一个按钮等待信号并在按下后触发状态转移:
chart light_controller
state (Idle) //初始状态
entry / no_light();
state (Green)
entry / green_light();
state (Red)
entry / red_light();
state (Button_Pressed) //按下状态
entry / button_pressed();
transition (Idle, Green) / (green_light_on) //初始状态到绿灯状态
transition (Green, Red) / (time_out) //绿灯到红灯状态
transition (Red, Green) / (time_out) //红灯到绿灯状态
transition (Red, Button_Pressed) / (button_pressed) //红灯到按下状态
transition (Green, Button_Pressed) / (button_pressed) //绿灯到按下状态
transition (Button_Pressed, Green) / (time_out) //按下状态到绿灯状态
transition (Button_Pressed, Red) / (time_out) //按下状态到红灯状态
event green_light_on;
event time_out;
event button_pressed;
// 操作函数
function no_light()
clear light;
end
function green_light()
light = 1;
end
function red_light()
light = 2;
end
function button_pressed()
light = 0;
end
二、Truth Table 与 Decision Block
Truth Table 是 Stateflow 决策块(Decision Block)最常用的子块之一。Truth Table通常用于将输入信号映射到输出信号,以便在决策块中具有更清晰的逻辑表达式。常见的使用方式是给定一系列的输入值和对应的输出值,通过Truth Table来完成映射,并将她们嵌入到决策块中,组合成决策逻辑。 下面是一个更加实际的例子,假设我们要实现一个简单的闹铃系统,需要根据当前的时间和用户设定的闹铃时间来触发闹铃。特别的,如果设定了“重复”功能,则每天该时间点都会触发闹铃。
chart alarm_system
input int alarm_time; //用户设定的闹铃时间
input int current_time; //当前时间
input boolean repeat; //是否重复
output boolean alarm;//输出信号,用于触发闹铃
// 决策块
decision Alarm_Decision
truth_table
//TureTable中的输入,即映射规则
TC: alarm_time
DZ: current_time
CX: repeat
//TrueTable中的输出,即映射的结果
0 1 1 0;
0 1 0 0;
1 1 1 1;
1 1 0 1;
end_truth_table
//根据TruthTable的结果,判断是否响铃
if (Alarm_Decision) {
alarm = true;
} else {
alarm = false;
}
三、超时和计数器
超时和计数器可以帮助我们在Stateflow中实现更加复杂的逻辑,例如倒计时、时序控制等。超时通常可以理解为在经过一定等待时间后触发某个事件。计数器可以帮助我们记录某个事件在state中执行的次数。以下是两个相关的例子:
chart timeout_example
state Timer
timeout(TIME) / timer_out;
state End
transition (Timer, End) / timer_out;
entry / set_timer();
const int TIME = 1000; // 1s
function set_timer()
reset_timer(Timer, TIME);
end
在这个例子中,我们创建一个state,名为 “Timer”。当进入 Timer 状态时,然后设定一个明确的超时事件,在指定时间后跳转到状态“End”。可以通过reset_time函数来设定超时时间。 下面给出一个计数器的例子,假设我们现在要对汽车的车速进行实时监控,如果车速大于某个阈值,则提示需要减速。我们将这个过程分为三个状态,将车速传感器的读数作为输入值,在“检查”状态中判断车速是否大于阈值,如果大于阈值,计数器计数,则跳转至“提示”状态,弹出提示信息,然后跳转回“检查”状态。
chart speed_monitoring
input int speed; //车速
output boolean prompt; //是否提示
state Check
entry / reset_counter();
on entry {if (speed > THRESHOLD) {counter ++;}}
state Prompt
entry / emit_prompt();
on entry {prompt = true;}
state End
transition (Check, Prompt) / counter > 0;
transition (Prompt, Check) / true;
const int THRESHOLD = 60; //判断阈值
int counter = 0; //计数器
function reset_counter()
counter = 0;
end
function emit_prompt()
prompt = false;
end
四、MATLAB函数的使用
Stateflow与MATLAB紧密集成,可以通过编写MATLAB函数来对Stateflow的状态、变量和事件进行更加灵活的操作。在这个部分,我们将学习如何在Stateflow中使用MATLAB函数。 首先,在Stateflow中必须定义所有的变量类型、输入和输出参数,以保证与MATLAB环境的交互。下面是一个简单的例子,其中使用了MATLAB内置的sin函数来生成一个简单的正弦波形:
chart sine_wave
output int y;
state SineWave {
entry / set_phase();
during / y = amplitude * sin( 2 * pi * frequency * time + phase_offset );
}
function set_phase()
time = 0;
phase_offset = pi/4;
end
const double amplitude = 5.0;
const double frequency = 1.0;
double time = 0;
double phase_offset = 0;
在这个例子中,我们定义了一个SineWave状态,并在其中使用sin函数。而这个函数体内的变量(time,phase_offset)均为类似MATLAB脚本的变量。此外,我们还需要在Stateflow图的Parameter Viewer中针对输入和输出参数定义相应的类型和名称,以将它们与MATLAB代码进行对接。
五、测试和仿真
最后,我们需要进行测试和仿真以验证Stateflow图的正确性。Stateflow可以通过生成C代码进行桌面仿真,也可以通过Simulink进行实时仿真。通常情况下,我们可以先在桌面上进行仿真,当Stateflow图的行为被验证后,再通过Simulink进行硬件验证。 在Simulink中使用Stateflow特别简单。首先,我们需要将Stateflow模块向Simulink模型中添加,并将它与其他Simulink模块进行连接。然后,我们需要将Stateflow图编译成C代码,从而生成可执行文件。最后,我们可以在Simulink的软件仿真环境中,通过执行生成的可执行文件来计算状态转移到的结果,并进行相应的输出。下面是如何进行桌面仿真和硬件验证的一个简单例子:
% 桌面仿真代码
load_system("model.slx"); % 加载模型
configure(model); % 参数配置
sim(model); % 开始仿真
有关如何进行硬件验证的详细步骤,参见Simulink的相关文档。
结论
通过以上的介绍,我们详细了解了Stateflow的基本语法和使用,包括状态和事件、Truth Table和Decision Block、超时和计数器、MATLAB函数的使用和测试和仿真。 Stateflow是一个非常强大的建模和仿真工具,为许多关键系统提供可视化的状态转移模型,并实现了高效的代码自动生成和测试验证功能。在实际的软件开发过程中,我们可以灵活运用Stateflow来提高系统的可靠性和效率。