所需的Simulink模块(toolbox)
本教程不需要stm32的硬件支持包,对穷人(dao)版matlab比较友好,仅需要将穷人版matlab带的matlab全装就完事了。
模型初始化
在初始化模型时选择embedded coder的example,
选择single-rate application
选择这个模型的目的是:
1. 模型直接被配置为fixed-step-solver,这个在simulink代码生成中是必须的。
加入stateflow模块
在这个例子里,我们实现一个简单的报错锁定功能,
1. 正常状态下,flag=0;
2. brk=1时,从正常状态进入错误状态,flag=1;
3. 锁定,现在即使brk=0, 状态机还是在错误状态,flag=1;
这个状态机stateflow的建模为
记得配置Symbols Pane设置stateflow中的变量类型。
此外我们的fag和brk都是uint8类型的变量,所以在stateflow中赋值时,需要对默认的数值类型进行转换,即flag=1会使flag变成single类型,而flag=uint8(0)才能使得我们获得正确类型的flag。
最终,这个简单例子里的simulink模型如下所示
记得把输入端口brk的类型改为uint8。另外,在代码生成的模型中,可以选择显示信号的数据类型,以确定是否符合预期。
代码生成的模型选项配置(model setting选项卡的配置)
我们这里代码生成主要是为了产生一个关于状态机的C代码模块,其功能比较简单,选择代码生成的主要目的是方便在simulink中测试模块功能,并防止手写代码出错。
所以我们的代码应该能够(或属于)
1. 支持stm32
2. 非重复利用的函数,因为程序里只涉及一个主状态机
3. 命名清楚且独特,因为我们程序里可能涉及到很多的matlab代码生成,我们不想让各个生成的模块在全局变量的命名上产生冲突
为了实现第1点,我们选择ARM Cortex-M,即stm32的构架,但是这里我们无须指定我们的硬件类型。
为了实现第2点,我们选择Code interface packaging为Nonreusable function
并且我们可以选择勾选”remove error status field in real-time model data structure”来简化代码生成。
另外我们的代码仅需支持浮点数,所以在Software environment的support一节中我们只需要勾选floating-point number即可。
为了实现第三点,我们需要对simulink自动生成变量的规则进行修改,尤其是全局变量,修改的结果如下所示。
我们一定要修改的包括:
+ Global variables
+ Global types
+ Constant macros
在这些对话框里,我们增加了$U
的选项,可以使得这些变量命名带上我们定义的后缀,这个定义在adavanced parameters里可以被设置,我们这里将它设置为chart。
代码生成和阅读生成报告
在simulink中的C CODE选项卡中,点击build(其实点下拉菜单里的generate code就可以了)进行代码生成,
然后我们就可以在右侧面板上看到我们生产的代码文件。
点击build按钮边上的open report,可以看到一个详细的代码生成文档。
我们可以看见一共生成了三个文档,其中chart.c和chart.h是我们需要搬到stm32中的文件,而ert_main则告诉我们如何在主程序中调用所生成的函数。
code interface report告诉我们所生成的代码接口信息,比如我们的故障信号brk是需要被写入rtU_chart.brk中,而我们的输出信号flag可以从rtY_chart.flag中读取。
这里我们可以看到在上一节中设置$U=chart
的重要性,因为不设置$U,simulink会将所有全局输入命名成rtU,所有全局输出命名成rtY,这样会导致我们如果进行了多次代码生成,就无法简单将多次生成结果直接迁移到stm32中。
最后我们看以下生成的完整代码
chart
simulink模型链接:
chart-model
如何使用
我们可以用extern void chart_initialize(void)
对chart进行初始化,
然后用extern void chart_step(void)
对chart的状态进行监控
如果产生错误,就将故障信号brk写入到rtU_chart.brk中,
当进行一次 chart_step(void)后,便可以从rtY_chart.flag中读取输出信号flag。