Simulink代码生成: 通过Stateflow调用外部C代码

本文描述通过通过Stateflow调用外部C代码调用外部C代码的方法。

1 问题引入

情形1:在汽车嵌入式软件开发的过程中,通常是用模型生成代码的方式开发应用层软件,用手写代码的方式开发底层软件和接口函数。应用层经常需要调用到底层的函数,比如应用层通过接口函数获取底层的变量值。

情形2:很多早期的项目没有引入MBD(基于模型的设计),而是全部通过手写代码完成。等到后面采用模型生成代码的时候,也会想要调用以前开发的成熟的代码。

以上两种情况,都需要通过在Simulink模型中调用外部的C代码。一种方法是通过S-function封装来实现,但是比较麻烦。本文介绍通过Stateflow实现调用外部C代码。

2 调用外部C代码的过程

2.1 准备外部文件

想要调用外部C代码,首先得要在Matlab路径下能找到这个C代码所在的文件。如果暂时没有开发也没关系,可以建立一个空壳代码,先“骗一下”Matlab。

如图所示,在Matlab当前路径下建立两个文件:myfile.cmyfile.h:
在这里插入图片描述
myfile.c中写入代码:

#include "myfile.h"
void HandCode(void)
{
}

myfile.h中写入代码:

void HandCode(void);

可以看到,HandCode()这个函数没有参数也没有返回值,而且里面是空的,啥都没有。

2.2 搭建模型

1.新建一个空白Simulink,建立一个Chart。
在这里插入图片描述
2.点击去这个Chart,打开Model Explorer,将Action Language设置为C。
在这里插入图片描述

3.建立一个简单的流程图,并在圆括号的动作中写上之前的那个HandCode的C代码。
在这里插入图片描述
3.打开设置——Simulation Target,填写右侧的Source file和Header file并确定。
在这里插入图片描述

2.3 生成代码

Ctrl+B生成代码,在打开的报告中就可以看到step函数中调用了这个C代码,以及头文件中包含了myfile.h。
在这里插入图片描述
在这里插入图片描述
最后别忘了,集成的时候要把真正的外部调用代码拿来编译,而不是我们自己建立的空壳代码。

3 调用有参数和返回的函数

上面举的例子是没有参数和返回值的,对于有参数和返回值的函数也是可以调用的。

1.首先修改一下C代码,加上参数和返回。
C文件:

#include "myfile.h"
single HandCode(single Input1)
{
}

头文件:

typedef float single;
single HandCode(single Input1);

这里用typedef定义一个single类型。

2.重新打开Chart,加上输入输出参数,定义好Name,Scope和Datatype,注意Datatype保持和代码中一致。
在这里插入图片描述
此时,Chart外面就会多出两个输入输出口,连接上Inport和Outport。
在这里插入图片描述
3.修改Chart中的调用语句如下;
在这里插入图片描述
4.Ctrl+B生成代码,就会生成调用了参数的代码。
在这里插入图片描述

4 调用参数为指针的函数

在第3章的基础上,如果调用的函数参数是指针,也可以简单地配置一下,就能生成出来。

1.还是要先修改一下C文件和头文件;

C文件:

#include "myfile.h"
single HandCode(single* Input1)
{
}

头文件:

typedef float single;
extern single HandCode(single* Input1);

需要注意,这里传参地Input的类型改成了指针。

2.对于Chart中的输入输出参数,和第3章中的定义是一致的,这里没法体现出指针。

3.在Chart中的语句就有所不同了,参数Input的前面要加上&,表示获取该变量的地址;
在这里插入图片描述
4.Ctrl+B生成代码,就会生成指针参数。可以和第3章中的代码做一下比较。
在这里插入图片描述

5 总结

通过Stateflow调用外部C代码是一种很方便的方法。不过在2018b以后的版本,推出了C Caller的模块可以调用外部C代码。