最近在做基于模型设计的开发,不仅仅要做MBD还要做配套的硬件支持包,即MCU对应的底层驱动,查阅了很多资料后发现,这方面的资料实在是太少了,自己整理了一些硬件支持包的开发流程,和大家分享一下。

目录

1 基于模型开发的设计流程

2 S-Function

2.1 C-MEX S-Function

2.1.1 C MEX S函数的构成

2.1.2 C MEX S函数的编译

3 TLC语言

3.1 TLC语言作用

3.2 TLC的语法

3.2.1基本语法

3.2.2 常用指令

3.3 为S函数编写TLC文件

3.3.1 C MEX S函数获取GUI参数的宏

3.3.2 C MEX S函数的mdlRTW函数

3.3.3 TLC文件的构成


1 基于模型开发的设计流程

基于模型开发的设计流程一般分为以下两种方式:

  1. 代码生成+手动集成。通过集成开发环境生成驱动代码,然后配合Simulink自动生成的C语言代码,手动编译下载到MCU中,利用IDE调试。
  2. 全代码生成,需要配合开发硬件支持包TSP(Target Support Package),不需要用集成开发环境,纯Simulink代码生成。

设计TSP前提:C语言、C-MEX S-Function、TLC语言等。

来自:https://zhuanlan.zhihu.com/p/138008476

2 S-Function

Simulink中的系统函数(System Function),是用来描述某个模块特性及功能的函数,当Simulink库提供的模块不足以满足需求时,可以通过S函数自己创建模块。S函数支持C语言等手写和自动生成的方式,可以利用Simulink模块自动生成,也可以用自定义工具写完代码连接到S函数中。

S函数可以分为两类:①直接运行的M S函数(用M语言描述的S函数)。②编译为Mex文件后执行的C MEX S-Function。第一类S函数可以分为两类,下表:

S函数分类

分类

区别

Level 1 M S

输入输出端口最多为1且数据维数固定

Level 2 M S

输入输出端口可以为多个,数据维数可以动态改变

C Mex S

可以包含已有的C算法,并在Output子方法中调用既有C函数。

S函数可以编写算法或者支持某个目标硬件的驱动模块。例如,编写简单的数学算法等用来仿真时,只需要Level 1 M S函数;所编写算法需要传递多个输入输出端口且每个端口数据都是多维(矩阵)时,需要使用Level 2 M S函数;如果要编写支持目标硬件外设寄存器配置的驱动模块,则需要使用C-MEX S-Function(C语言描述的S函数), 但是需要编写同名的TLC文件。

2.1 C-MEX S-Function

用C语言编写的S函数。它的可执行文件为MEX文件,是Matlab环境下的动态链接可执行文件,当模型运行时,S函数模块通过文件名寻找对应的M文件或者MEX文件来调用执行。

需求

建议

使用M或C语言的S-Function但是不知道如何手写

使用Simulink提供的S-Function builder生成

编写S-Function用于生成嵌入式代码

编写C-MEX S-Function并提供与

S-Function同名的TLC文件

将算法或者部门核心模块保密,仅提供使用而不能看到源代码

编写C-MEX S-Function,将C文件通过mex XXX.C格式编译,仅提供mexw32/64

S函数包括一组输入、一组状态和一组输出。

模型中的变量包括:

时间量t随着Simulink解算器运行而记录当前时间。

输入量u通常为前一个模块的输出量,当作为信号源时,可以没有输入量。

状态量x根据系统性质分为连续系统中的微分量和离散系统中的差分量,通过前后不同时刻的输入值计算得到。

输出量y可以没有输出量。

S函数执行的流程

1:

初始化模型参数

2:

计算下一个采样时间点

3:

for  0→仿真终止时间

4:

计算模块的输出

5:

更新离散状态量

6:

if (此模型带有连续状态模块)

7:

here:计算微分

8:

计算模块的输出;

9:

if (精度未达标)

10:

goto here

11:

endif

12:

过零检测

13:

计算下一个采样时间点

14:

   endif

15:

endfor

16:

执行仿真终止动作

仿真运行时,模型首先要对模块进行初始化,这个过程包括模块的实例化、输入/输出端口、信号维度、端口数据类型及采样时间等的确定,模块参数的获取及个数检查,并决定模块的执行顺序等。

实例化:Simulink标准库中提供的模块类似于C++等面向对象语言中的一个类,每当模块被拷贝或拖曳到模型中时,就相当于创建了这个类的一个对象,继承了这个类的属性并载入了默认的构造函数方法对其参数、端口等各个属性进行了初始化工作。

信号维度:一根信号线传递的数据不仅可以是标量,也可以是一个向量或矩阵,一个模块的输出端口将具有这个数据维度的信号传递给相连的信号线然后再传递给下一个模块的输入端口,这些都是需要在初始化阶段确定下来的。

端口数据类型:模块的输入/输出数据是浮点数还是固定点数,是8位、16位、32为或64位,有无符号,内建类型或者用户自定义类型,这些也在初始化阶段指定。

采样时间:对于Simulink模型来说,解算器中的一个步长决定了整个模型最小的采样时间间隔。

模型中模块的执行顺序:当众多模块同时存在于一个模型中时,Simulink是有明确的顺序优先度的。

设计S函数时,需要调用S函数的子方法,子方法的名称与功能如下表:

C MEX S函数子方法

子方法功能

mdllnitializeSizes

模块属性初始化

mdIDerivatices

更新连续状态变量的微分值

mdllnitializeConditions

初始化工作向量的状态值

mdlOutputs

计算模块的输出

mdlSetWorkWidths

当S函数模块存在于使能子系统中时,每次子系统被使能均进行工作向量属性的初始化工作

mdlStart

在仿真开始时初始化工作向量及状态变量的属性

mdITerminate

在仿真终上时所调用的子方法

mdlUpdate

更新离散状态变量的子方法

mdlRtw

将S函数中获取到的GUI参数变量值写入到rtw文件中以使TLC文件用来生成代码

2.1.1 C MEX S函数的构成

(1)首先必须定义的两个宏:C Mex S函数名及C Mex S函数的等级。

  1. #define S_FUNCTION_NAME  two
  2. #define S_FUNCTION_LEVEL 2

(2)头文件包含部分C Mex S函数核心数据结构simstruct类型的声明及其他库文件,根据使用需要也可以包含其他头文件。

  1. #include<math.h>
  2. #include"simstruc.h"

(3)参数对话框访问宏函数的定义。包括常用宏变量TRUE/FALSE的定义,C MexS函数模块通过这些宏能够方便地获取参数对话框各个控件中的值,以方便在之后的各个子方法中使用,但是这个部分不是必需的。

(4)紧接着定义C Mex S函数的各个子方法。需要注意,这些子方法都是static子函数,被static修饰函数的作用域仅局限于本文件,而不会被其他S函数所调用。

  1. static void mdlInitializeSizes(SimStruct *S){}
  2. static void mdlInitializeSampleTimes(SimStruct *S){}
  3. static void mdlOutputs(SimStruct *S, int_T tid){}
  4. ......

(5)S函数必须根据使用情况(编译为Mex文件用来仿真还是用于自动代码生成)包含必要的源文件和头文件,从而将该S函数文件与Simulink或Simulink Coder产品进行连接。

  1. //编译C文件时用到,表示S函数是否正在编译为mex文件
  2. #ifdef  MATLAB_MEX_FILE /*Is this file being compiled as a MEXfile*/
  3. //包含mex文件需要的接口机制,以此将S函数的C文件编译为mex文件
  4. #include"simulink.c"      /* MEX-file interface mechanism */
  5. #else
  6. //想要自动生成代码,调用Simulink Coder工具箱
  7. #include"cg_sfun.h"     /* Code generation registration function */
  8. #endif

2.1.2 C MEX S函数的编译

编译型语言编写的程序执行之前,需要一个专门的编译过程,把程序编译成为机器语言的文件,比如exe文件或mexw32/mexw64文件,运行时不用重新编译,直接使用编译的结果就行了(exe文件),所以程序执行效率高,这也是使用C MEX S函数仿真速度快的原因。解释性语言的程序没有编译这道工序,在运行程序时进行翻译,例如M语言,专门有一个解释器能够直接执行程序,每个语句都是执行的时候才编译,效率比较低。

C语言是编译性语言,与直接解释执行的M语言不同,需要通过编译器编译为可执行文件之后,才能被Simulink执行。为了将C语言文件编译为mex文件,需在PC上安装编译器,在Matlab的CommandWindow中输人mex -setup可查看是否安装了编译器,最后通过mex XXX.c对S函数进行编译。

3 TLC语言

Simulink模型在Simulink Coder和Embedded Coder的支持下可以生成嵌入式C语言代码,应用于MCU、DSP等芯片。模型生成代码需要靠系统目标文件与模块目标文件的支持。这两个等级的目标文件都是由TLC(Target Language Compiler,目标语言编译器)进行语言转换的TLC文件。

Similink自动代码生成的流程为:使用Embedded Coder或Simulink Coder将.mdl或.slx文件转换为.rtw文件,然后利用TLC文件将.rtw文件转换为C语言代码,转换过程中,系统会按照TLC文件的描述自动生成代码。

3.1 TLC语言作用

(1)支持模型针对通用或特定目标硬件的代码生成功能;

(2)为S函数模块提供代码生成功能,可以自己增加支持代码生成的模块;

(3)在代码生成过程中,生成不依赖S函数模块的自定义过程代码。

3.2 TLC的语法

TLC是一种以单个%开头的关键字为命令,空格之后跟参数的脚本语言,自身包含了流控制语法、内建函数、关键字和常用命令。

3.2.1基本语法

(1)[text|%<expression>]*

  1. <LibBlockOutputSignal(0,"", lcv, i)>

text表示字符串,将文本展开到输出流中。在%<>之中的是TLC变量,通过%<>作用将变量的执行结果显示到输出流中。

(2)%keyword [arguement1,arguement2,...]

  1. % assign Str ="Hello World"

%keyword表示TLC语言中的命令符,[arguement1, arguement2, ...]则表示这个命令符所操作的参数。

%warning、%error、%trace命令可以将其后的变量或字符串的内容输出。

例如:

  1. %  warning Simulink Coder

输出为:

  1. >> tlc test.tlc
  2. Warning:  Simulink User

3.2.2 常用指令

注释:

单行注释:%%双百分号

多行注释:/%***%/

变量内容扩展:

通过%<>操作符将其内容扩展到输出流中。

  1. %% test.tlc
  2. %assign input1 =3
  3. %assign input2 =5
  4. %warning%<input1>+%<input2>=%<input1 + input2>

输出:

  1. >> tlc text.tlc
  2. Warning:  3 + 5 = 8

条件分支:

% if expression

% elseif expression

% else

% endif

例:判断给定值是否为1

  1. %% test.tlc
  2. %assignvar=2
  3. %ifISEQUAL(var,1)
  4. %warning everingisOK.
  5. %else
  6. %warningvarshould be1but now thereissomething wrong.
  7. %endif

输出:

  1. >> tlc text.tlc
  2. Warning:varshould be1but now thereissomething wrong.

3.3 为S函数编写TLC文件

带有参数的S函数首先从GUI上获取用户的输人作为参数,通过C语言的宏将GUI控件上的值读人S函数,再通过S函数的子方法mdlRTW将参数值写人到模型的.rtw文件中,使得TLC文件能够获取这些参数的值,最终生成C语言代码。代码生成流程及参数数据的流向如下图。

代码生成流程图

3.3.1 C MEX S函数获取GUI参数的宏

GUI制作的参数对话框作为S函数的最前端能够提供方便简洁的操作方式。常用的 Simulink Mask控件包括Edit、popup、radiobutton、check-box和pushbutton等。不同控件所容纳的数据类型不同,Edit中可以输入数值也可以输人字符串,从popup/radiobutton中既可以提取表示所选项目的编号也可以提取所选项目的字符串内容。可以根据使用场景不同,有选择地提取数据类型。在C MEX S函数中以Edit为例:

(1)获取Edit中的数值

  1. #define PARAM(S)(mxGetScalar(ssGetSFcnParam(s,g_param)))

g_param为Edit等控件的参数在GUI控件中的索引号,首先通过ssGetSFcnParam宏函数获取指向Edit控件中参数的数值,再使用mxGetScalar宏函数获取指针指向地址的数值。

(2)获取Edit中的数组

  1. #define PARAM(S)mxGetNumberOfElements(ssGetSFcnParam(s, g_param))

在使用ssGetSFcnParam宏函数获取Edit控件的指针之后,使用mxGetNumberOfEle ments获取此数组的数据长度,以传递相同长度的数据到rtw文件。

(3)获取Edit中的字符串

  1. #define PARAM(S)(ssGetSFcnParam(s, g_param))

仅在宏定义中获取指向参数的指针,在S函数的mdIRTW函数中再进行字符串传递。

3.3.2 C MEX S函数的mdlRTW函数

mdlRTW函数是专为支持代码生成的S函数设计的,不支持仅用于仿真的C MEX S函数,它的功能是传递S函数的参数数据到rtw文件。它必须被包含在以下这个预处理语句中:

  1. #ifdefined(MATLAB_MEX_FILE)
  2. #define MDL_RTW
  3. staticviodmdlRTW(SimStruct *S){}
  4. ...
  5. #ifend

函数内实现两个作用:①通过定义的宏获取GUI上的数据;②将这些输入写入到rtw文件中。

3.3.3 TLC文件的构成

TLC文件是具体实现一个S函数如何生成代码的,与S函数的构成类似,TLC文件也由多个执行顺序有先后的子函数构成。

子函数

输出

功能说明

BlockInstanceSetup

(block,  system)

不产生输出

同种类的模块存在多个时,每一模块都会执行一次此函数,可以将模块共同的操作或特例的操作写入此函数中

Start

(block, system)

产生输出

模块中仅执行一次的函数,内部代码会生成到model_initialize()函数中,通常将模型各变量、状态或硬件外设初始化的代码写在此函数中,因为他们不需要重复执行

Outputs

(block, system)

产生输出

用于编写模块计算输出的代码,并将其生成到model_step()函数中

Terminate

(block, system)

产生输出

此函数用于自定义代码用,可以存储数据,释放内存,复位硬件寄存器等操作,此函数内的代码将生成到MdlTerminate()中

TLC文件并非必须包括上面所有子函数,根据需要选择其中部分函数。每个子函数都有两个参数:blocksystem,分别表示当前函数所属的模块名和该模块所属的子系统名。每一个S函数的TLC文件都拥有相同的函数名,即使多个模块的TLC文件同时存在也不会出现访问冲突,在执行时才由TLC决定调用哪个模块的子函数。

       产生输出的函数不需指定,即可将内部代码创建成文件流生成到特定的位置;不产生输出的函数中则需要用户编写代码创建文件流再指定其生成的位置。产生输出的函数在其承数参数列表后有output标注,不产生输出的函数参数列表后则以void标注,如:

  1. %function BlockTypeSetup(blocksystem)void
  2. %function Start(blocksystem)Output

每个模块TLC文件都以%implements命令开头,其后注明S函数名及生成代码的目标语言。如:

  1. %implementstest "C"

在TLC文件结尾需要补上结束命令:

  1. %endfunction

如有错误还请大家多多指教。

参考书籍:

《基于模型的设计-MCU篇》 刘杰 北京航空航天大学出版社;

Matlab硬件支持包开发流程相关推荐

  1. MATLAB和SIMULINK硬件支持包安装的问题总结

    安装MATLAB SUPPORT PACKAGES FOR ARDUINO 和 SIMULINK PACKAGES FOR ARDUINO 时,经常出现报错信息第三方支持包Arduino Softwa ...

  2. 玩转 MATLAB 附加功能/硬件支持包安装

    解决不能下载附加功能.硬件支持包的使用方法. MATLAB 作为一个开放的科学计算.系统仿真与设计.以及软件产品开发的工程平台,其生态圈有非常丰富的内容. 尽管时至今日 MathWorks 已在最新的 ...

  3. MATLAB的RTL-SDR硬件支持包使用详细教程

    本文内容.开发板及配件仅限用于学校或科研院所开展科研实验! 温馨提示:"开源SDR实验室"是北京的. 本文原文作者是sund,原文链接是http://www.sund-xys.cn ...

  4. 如何安装第三方站点下载的Matlab工具箱或硬件支持包,亲测有效。

    如何安装第三方站点下载的Matlab工具箱或硬件支持包,亲测有效. 背景说明 安装方法 说明 背景说明 今天给大家说一说,有时候我们下载Matlab官方的工具箱或者硬件支持包会出现下载时间过长,下载到 ...

  5. Matlab安装硬件支持包

    Matlab安装硬件支持包 由于我们使用的版本是未激活的版本,所以在线安装就会出现下面的问题 1.只能去下列网址下载离线包下载工具下载硬件支持包和可选功能 根据自己的操作系统选择对应版本,得到的如下 ...

  6. Matlab 2017b安装硬件支持包

    Matlab 2017b安装硬件支持包 最新不知道怎么了,Matlab R2017b在线安装硬件支持包总是显示"网络连接问题".搜索了一下,找了解决方案: 1.去下列网址下载离线包 ...

  7. 解决matlab无法下载arduino的simulink硬件支持包的方法

    在下载arduino硬件支持包时,simulink和matlab下载多达十几个第三方支持包. 由于网速或者被墙的原因往往下载到一半就会报错,提示下载出现问题  应对方法如下:打开硬件支持包的下载位置, ...

  8. TIA博途中无法添加HSP硬件支持包的解决办法

    TIA博途中无法添加HSP硬件支持包的解决办法 硬件支持包安装的过程应该很简单,但是在安装的时候遇到了一个奇怪的问题. 如下图所示,下面就描述一下问题发生和自己的解决方法: 打开TIA博途V16,在 ...

  9. MATLAB R2021a离线下载并安装硬件支持包

    操作系统:Win10 MATLAB版本: R2021a 第三方包:Simulink Coder Support Package for STMicroelectronics Nucleo Boards ...

最新文章

  1. 另一种思考:为什么不选JPA、MyBatis,而选择JDBCTemplate?
  2. ZooKeeper服务命令
  3. linux 必须掌握的60个命令
  4. eclipse color theme 主题颜色
  5. php 直接定义 和 construct,PHP _construct()函数讲解
  6. lombok时运行编译无法找到get/set方法 看这篇就够了
  7. Spring Data ElasticSearch入门案例
  8. java环境变量设置的作用_JDK环境变量的配置及作用
  9. 什么叫白户,白户能贷款吗?
  10. pip安装wxpython报错_Ubuntu 上搭建robotframework
  11. React.js 小书 Lesson18 - 挂载阶段的组件生命周期(一)
  12. hnu 暑期实训之到底买不买
  13. 读《王垠-天才是什么》有感
  14. 《白帽子讲web安全》学习笔记——web安全概述
  15. python 学习笔记——线性回归预测模型
  16. SSH框架搭建和整合(struts2、spring4、hibernate5)
  17. mm游戏大全HTML5小游戏,HTML5小游戏——看你有多色(示例代码)
  18. 通达信破底翻形态选股公式,选出破底之后再翻回的标的
  19. 第一台超高速巨型电子计算机,1997年,( )巨型机的研制成功,使我国在这个领域跨入了世界先进行列。...
  20. PaddlePaddle飞桨 CV训练营心得

热门文章

  1. 双击SumatraPDF无法进入latex对应位置的解决办法
  2. python未定义_python-未定义名称“sc”,
  3. Prim和Kruskal算法应用----城市水管连接
  4. 分治法解决矩阵乘法问题
  5. matlab做信号发生,声卡和Matlab的虚拟信号发生器的工作原理
  6. .vimrc配置(持续更新)
  7. CAD转JPG怎样才能清晰?几个步骤快来拿捏
  8. android四大组件---ContentProvider
  9. [LinuxService][Yum][problem] 在fedora 9上解决依赖问题
  10. 在java中保留六位小数_java中保留指定小数位的方法