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来提高系统的可靠性和效率。